--- id: MAN-17 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-17 specification: FlowDrop Workflow Specification 1.0-draft licence: CC BY 4.0 --- # MAN-17 — Declared outputs are collected by the same mapping, in reverse *GR-MAN (Part I) · level: extended · profiles: storage-api · added in 1.0* The output side of the manifest, with one distinction that matters: a node that produced null produced something, and is not the same as a node that produced nothing. ## The rule > **Normative.** This is the rule. > > 1. Each declared output name resolves to the result the bound node produced on the bound port. > > 2. Presence is decided by whether the key exists, so a null value counts as produced and is returned. > > 3. An output whose node produced nothing at all is dropped from the result with a warning. > > 4. A malformed output entry is skipped. ## What it means Presence is decided by whether the key exists, not by whether the value is truthy. A node that produced `null` on its bound port produced something, and that null is returned under the declared output name. That is different from a node whose bound port never appears in what it produced at all — that case is dropped from the result, with a warning, because there is nothing to return. A malformed entry — one missing its name, its node id or its port — is skipped without a warning: it never named a real output in the first place, so there is nothing to warn about. ## Example The workflow declares two outputs bound to the same node: `answer`, on its `text` port, and `hidden`, on a `debug` port the node did not produce this run. ```json title="What the bound node produced" verdict="retained" { "llm.1": { "text": null } } ``` ```json title="The declared outputs resolved against it" verdict="retained" { "answer": null } ``` The `debug` port never appears in `llm.1`'s results at all, so `hidden` is dropped from the outputs, with a warning naming it. A malformed entry — an empty name, an empty node id, or an empty port — is skipped the same way, but without the warning the dropped case above gets. ## Related rules - Names: MAN-8, MAN-11 - Referenced by: MAN-8, MAN-11 --- 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.