Issue #9 asked for the spec.md TODOs to be filled from implemented platform behaviour. In three places #13 decided against the platform instead, with the reasoning recorded in the prose each time.
None of these is a gap someone forgot to fill. Each is a live divergence: an implementation conforming to this specification and the platform as it stands today produce different verdicts on the same document. They are collected here so that closing #9 does not read as closing them.
The grounds in every case are ADR 0001 §1 — "Where an implementation and the conformance suite disagree, the implementation is defective" — but that decides who changes, not whether the specification chose correctly. Each still deserves a second look before v1 is declared stable.
1. Cycle detection — the specification is stricter
blueprint §4.2: the connection graph MUST be acyclic, ERR_DEPENDENCY_CYCLE.
The platform deliberately permits cycles, recorded in its ADR 0116, to support mutual service discovery — two services that each need the other's address. Because an output is a function of its own node alone, compose resolves every output before binding any edge and needs no topological order, so a cycle is not a resolution hazard.
§4.2 concedes that argument outright ("Acyclicity is not a resolution hazard") and overrides it on different grounds: permitting cycles obliges every implementation in every language to be that two-pass resolver in perpetuity, forecloses any later rule that needs an order, and leaves every reader of a six-node graph working out whether it terminates.
Consequence: the platform gains a check that rejects a composition it accepts today, and mutual service discovery stops being expressible.
Covered by conformance/blueprint/v1/semantic/002-connection-cycle and 011-three-node-cycle-reporting.
2. Parameter merge — the specification errors where the platform is silent
blueprint §5.2. Two divergences in one rule:
|
platform |
specification |
| Order |
(ordering, componentId) |
lexicographic node name |
| Conflicting redeclaration |
silent first-wins (setdefault) |
ERR_CONFLICTING_INPUT_SCHEMA |
The ordering change is forced: neither ordering nor componentId exists in this contract, and node name is the only total order the document itself supplies. The conflict change is a choice, and issue #9 itself invited it — "First-wins is a defensible rule, but … silently discards a conflicting declaration is the kind of behaviour a specification should either bless explicitly or replace with a diagnostic."
Consequence: merge_user_inputs needs both changes. Blueprints the platform accepts today will be rejected.
Covered by conformance/blueprint/v1/semantic/009-conflicting-input-schema.
3. SERVICE endpoints — the specification is looser
component §5: a SERVICE MAY declare no endpoint.
assert_component_shape requires at least one. #13 declined to adopt it because doing so would reject specifications/component/v1/examples/minimal.yaml and the structural-001-minimal-valid fixture — the smallest component that validates is a service running a pinned image and nothing else.
This is the one that runs the other way, and the one worth revisiting soonest. §5 says so itself: "requiring at least one endpoint is a defensible rule. It is simply not this version's rule, and adopting it later rejects documents v1 accepts."
Consequence: either the platform relaxes, or the two disagree about what a SERVICE minimally is. Adopting the platform's rule is breaking after the first tag, and release PRs #1, #2 and #3 are open right now.
What closing this looks like
For each: either the platform changes to match, or this repository records an accepted deviation, or the specification is revised. Divergence 3 in particular has a deadline — the window in which adopting the stricter rule is free closes when #1/#2/#3 merge.
Refs #9
Issue #9 asked for the
spec.mdTODOs to be filled from implemented platform behaviour. In three places #13 decided against the platform instead, with the reasoning recorded in the prose each time.None of these is a gap someone forgot to fill. Each is a live divergence: an implementation conforming to this specification and the platform as it stands today produce different verdicts on the same document. They are collected here so that closing #9 does not read as closing them.
The grounds in every case are ADR 0001 §1 — "Where an implementation and the conformance suite disagree, the implementation is defective" — but that decides who changes, not whether the specification chose correctly. Each still deserves a second look before v1 is declared stable.
1. Cycle detection — the specification is stricter
blueprint §4.2: the connection graph MUST be acyclic,
ERR_DEPENDENCY_CYCLE.The platform deliberately permits cycles, recorded in its ADR 0116, to support mutual service discovery — two services that each need the other's address. Because an output is a function of its own node alone, compose resolves every output before binding any edge and needs no topological order, so a cycle is not a resolution hazard.
§4.2 concedes that argument outright ("Acyclicity is not a resolution hazard") and overrides it on different grounds: permitting cycles obliges every implementation in every language to be that two-pass resolver in perpetuity, forecloses any later rule that needs an order, and leaves every reader of a six-node graph working out whether it terminates.
Consequence: the platform gains a check that rejects a composition it accepts today, and mutual service discovery stops being expressible.
Covered by
conformance/blueprint/v1/semantic/002-connection-cycleand011-three-node-cycle-reporting.2. Parameter merge — the specification errors where the platform is silent
blueprint §5.2. Two divergences in one rule:
(ordering, componentId)setdefault)ERR_CONFLICTING_INPUT_SCHEMAThe ordering change is forced: neither
orderingnorcomponentIdexists in this contract, and node name is the only total order the document itself supplies. The conflict change is a choice, and issue #9 itself invited it — "First-wins is a defensible rule, but …silently discards a conflicting declarationis the kind of behaviour a specification should either bless explicitly or replace with a diagnostic."Consequence:
merge_user_inputsneeds both changes. Blueprints the platform accepts today will be rejected.Covered by
conformance/blueprint/v1/semantic/009-conflicting-input-schema.3.
SERVICEendpoints — the specification is loosercomponent §5: a
SERVICEMAY declare no endpoint.assert_component_shaperequires at least one. #13 declined to adopt it because doing so would rejectspecifications/component/v1/examples/minimal.yamland thestructural-001-minimal-validfixture — the smallest component that validates is a service running a pinned image and nothing else.This is the one that runs the other way, and the one worth revisiting soonest. §5 says so itself: "requiring at least one endpoint is a defensible rule. It is simply not this version's rule, and adopting it later rejects documents v1 accepts."
Consequence: either the platform relaxes, or the two disagree about what a
SERVICEminimally is. Adopting the platform's rule is breaking after the first tag, and release PRs #1, #2 and #3 are open right now.What closing this looks like
For each: either the platform changes to match, or this repository records an accepted deviation, or the specification is revised. Divergence 3 in particular has a deadline — the window in which adopting the stricter rule is free closes when #1/#2/#3 merge.
Refs #9