Authoring Rules¶
Make targets are public operator contracts when they appear in make help or
CI. Their names, prerequisites, environment, artifacts, and failure behavior
must remain understandable without reading an opaque recipe body.
Authoring Model¶
flowchart TB
target["new or changed target"]
fragment["named fragment owns the logic"]
concept["target name matches owning concept"]
boundary["shared target avoids hidden package behavior"]
accept["command stays auditable"]
target --> fragment
fragment --> concept
concept --> boundary
boundary --> accept
The smallest correct owner is preferred: shared mechanics in synchronized
fragments, repository policy in a tested repository helper, package variation
in a named profile, and top-level aliases in makes/root.mk.
Place behavior by ownership¶
| Behavior | Correct owner | Reject when |
|---|---|---|
| thin public alias or prerequisite ordering | makes/root.mk or a named repository fragment |
recipe embeds domain policy or long shell control flow |
| package inventory and capability membership | makes/packages.mk |
package selection is inferred from directory globs |
| package-specific variables and narrow overrides | makes/packages/<package>.mk |
shared recipe branches repeatedly on package name |
| reusable Python-project mechanics | synchronized makes/bijux-py/ modules |
repository-only assumptions enter shared mechanics |
| quality, governance, or release decision | tested bijux-proteomics-dev implementation |
Make recipe becomes the only policy definition |
| generated output | named generator plus governed destination | recipe hand-edits or silently normalizes tracked evidence |
Target acceptance checklist¶
flowchart TD
proposal["target proposal"] --> owner{"one durable owner?"}
owner -->|no| split["split or relocate behavior"]
owner -->|yes| contract["name inputs · prerequisites · outputs · failures"]
contract --> parity{"same meaning locally and in CI?"}
parity -->|no| reject["remove parallel meaning"]
parity -->|yes| artifacts{"outputs governed under artifacts/?"}
artifacts -->|no| repair["define governed destination"]
artifacts -->|yes| accept["publish help text and tests"]
A new public target needs a durable verb and object, a help description, a
declared .PHONY posture when appropriate, and a direct path to the owner that
can be tested independently. Composite targets list prerequisites; they do not
copy child recipes.
Rules¶
- prefer named fragments over dense inline shell logic;
- keep target names and file names aligned with the owning concept;
- quote paths and propagate nonzero exits from every child process;
- never use a successful summary line to conceal a failed prerequisite;
- keep generated outputs, caches, and reports under governed destinations;
- replace repeated package conditionals with capability groups or profiles;
- add event mechanics in workflows without changing the root target’s proof meaning.
First proof route¶
Trace the proposed command from make help through its declaration,
prerequisites, selected package group, profile, implementation, and artifact
path. Run the narrow target once in a developer shell and inspect the workflow
invocation that relies on the same meaning.
Design Pressure¶
Target count is not the main risk; hidden semantic duplication is. Two commands that look distinct but execute the same owned contract may be aliases. Two commands with the same name but different local and CI meanings are a defect.