--- id: MAN-18 family: GR-MAN level: extended profiles: [storage-api] posture: normative-target added: "1.0" changed: "1.0" source: https://flowdrop.io/spec/rules/gr-man/man-18 specification: FlowDrop Workflow Specification 1.0-draft licence: CC BY 4.0 --- # MAN-18 — The contract is rebuilt when the manifest changes, and versioned when it is *GR-MAN (Part I) · level: extended · profiles: storage-api · added in 1.0* Rebuilding is triggered by the manifest, not by the schemas underneath it, so a caller reads a contract that was published deliberately rather than one that drifts. ## The rule > **Normative.** This is the rule. > > 1. A workflow's contract is rebuilt when its declared input or output manifest differs from the stored one, or when a rebuild is forced. > > 2. A change inside a bound port's own schema does not trigger a rebuild, so the published contract stays as it was until something else rebuilds it. > > 3. A side with no declared entries stores no schema for that side. > > 4. On rebuild the contract version is bumped: from an all-zero version any of a major, minor or patch bump yields the first released version; otherwise the named digit is incremented and the lower digits reset. > > 5. A rebuild that bumps nothing writes the schemas and leaves the version untouched. > > 6. A build that fails logs an error, preserves the previously published contract, and does not prevent the workflow from being saved. ## What it means The trigger is the port list, not what changed underneath it. A bound port's own schema can change entirely — a fragment's `type`, its `minLength`, anything a node type declares — and the published contract does not move, because nothing rebuilds it until the input or output port list itself differs from the one already stored, or a rebuild is forced. A caller reading the published contract is reading what was last published, not a live reflection of the ports it names. A side with no declared entries stores no schema for that side at all — there is nothing to build. And a build that fails leaves the previously published contract in place: the workflow still saves, the failure is recorded, and nothing about the failed rebuild reaches the caller. ## Example ```json title="An input port list identical to the one already published" verdict="skipped" [ { "name": "in", "node_id": "n1", "port": "p1" } ] ``` ```json title="A workflow declaring no output ports at all" [ ] ``` ```json title="What is stored for that side" verdict="none" null ``` ## Related rules - Names: MAN-5, MAN-21 - Referenced by: MAN-21, STORE-8 --- Rule identifiers are permanent and are never renumbered. This specification carries no implementation status: each implementation publishes its own standing against these rules. Licensed CC BY 4.0.