Summary
PROTOCOL_SPEC §5.12.2's binding-file field table declares:
| target_id | string | MUST | Target callable (format: module.path:callable_name) |
and its worked examples use target_id. Nothing else in the ecosystem agrees:
| Source |
Field name |
docs/spec/protocol-spec.md §5.12.2 — table and examples |
target_id (declared MUST) |
docs/spec/DECLARATIVE_CONFIG_SPEC.md §3.2 field table (:169), error table (:482-483) |
target |
schemas/binding.schema.json — the canonical schema |
target |
conformance/fixtures/binding_errors.json |
target |
conformance/fixtures/binding_yaml_canonical.yaml |
target |
apcore-python (src/apcore/bindings.py) |
target |
apcore-typescript (src/bindings.ts) |
target |
apcore-rust (src/bindings.rs) |
target |
The protocol spec is the sole outlier, and it is the outlier on a MUST.
Impact
A binding file written from §5.12.2 — the section whose entire purpose is to define the binding-file format — loads in no SDK. The field is not optional and has no alias: all three loaders require target and reject a descriptor without it. §5.12.2 is the user-facing YAML contract, so this is the one place where a spec-conformant author is guaranteed a broken file.
It also propagates. conformance/fixtures/bindings_dir_resolution.json, added in spec v1.35.0, spells the field target_id because its author followed §5.12.2. Every SDK driver written against that fixture had to rewrite the key before the descriptor would load — independently, in all three repos, each reporting it as a fixture defect.
How it was found
Three conformance drivers for bindings_dir_resolution.json were written in parallel in the three SDK repos. All three reported the same mismatch without knowledge of each other. That is the failure signature of a spec statement no implementation has ever satisfied: nothing was wrong in any SDK, and nothing detected the divergence, because no fixture had ever exercised §5.12.2's spelling against a real loader.
Proposal
Correct §5.12.2 to target, in the field table and in every example in that section. Check §5.12.3 (resolve_target / BINDING_CALLABLE_NOT_FOUND), §5.12.4 (schema_ref) and §5.12.5 (auto_schema) for the same spelling and correct those too.
This is a correction to the specification, not a change to any implementation: target is what the canonical schema declares, what the companion spec documents, what both existing binding fixtures use, and what all three SDKs have always required. No SDK behaviour changes and no deployed binding file is affected — the population of files that used target_id is empty, because such a file has never loaded.
Also fix conformance/fixtures/bindings_dir_resolution.json to use target, so the three SDK drivers can drop their rewrite shims.
Version
A MUST-level field name changes, so it needs a version bump and a changelog entry. It is a contradiction-resolution rather than a relaxation — comparable to the v1.9.0 entries in §13's revision table where the spec was corrected to what every implementation already did — so no dual-accept window is required: there is no prior behaviour to accept.
Approval
Per CLAUDE.md and GOVERNANCE.md § Decision Making, a docs/spec/protocol-spec.md change needs a linked issue (this one) and maintainer approval — 2 maintainers, or all of them when fewer than 3 exist. MAINTAINERS.md lists one, so one approval satisfies it.
Summary
PROTOCOL_SPEC§5.12.2's binding-file field table declares:and its worked examples use
target_id. Nothing else in the ecosystem agrees:docs/spec/protocol-spec.md§5.12.2 — table and examplestarget_id(declared MUST)docs/spec/DECLARATIVE_CONFIG_SPEC.md§3.2 field table (:169), error table (:482-483)targetschemas/binding.schema.json— the canonical schematargetconformance/fixtures/binding_errors.jsontargetconformance/fixtures/binding_yaml_canonical.yamltargetsrc/apcore/bindings.py)targetsrc/bindings.ts)targetsrc/bindings.rs)targetThe protocol spec is the sole outlier, and it is the outlier on a MUST.
Impact
A binding file written from §5.12.2 — the section whose entire purpose is to define the binding-file format — loads in no SDK. The field is not optional and has no alias: all three loaders require
targetand reject a descriptor without it. §5.12.2 is the user-facing YAML contract, so this is the one place where a spec-conformant author is guaranteed a broken file.It also propagates.
conformance/fixtures/bindings_dir_resolution.json, added in spec v1.35.0, spells the fieldtarget_idbecause its author followed §5.12.2. Every SDK driver written against that fixture had to rewrite the key before the descriptor would load — independently, in all three repos, each reporting it as a fixture defect.How it was found
Three conformance drivers for
bindings_dir_resolution.jsonwere written in parallel in the three SDK repos. All three reported the same mismatch without knowledge of each other. That is the failure signature of a spec statement no implementation has ever satisfied: nothing was wrong in any SDK, and nothing detected the divergence, because no fixture had ever exercised §5.12.2's spelling against a real loader.Proposal
Correct §5.12.2 to
target, in the field table and in every example in that section. Check §5.12.3 (resolve_target/BINDING_CALLABLE_NOT_FOUND), §5.12.4 (schema_ref) and §5.12.5 (auto_schema) for the same spelling and correct those too.This is a correction to the specification, not a change to any implementation:
targetis what the canonical schema declares, what the companion spec documents, what both existing binding fixtures use, and what all three SDKs have always required. No SDK behaviour changes and no deployed binding file is affected — the population of files that usedtarget_idis empty, because such a file has never loaded.Also fix
conformance/fixtures/bindings_dir_resolution.jsonto usetarget, so the three SDK drivers can drop their rewrite shims.Version
A MUST-level field name changes, so it needs a version bump and a changelog entry. It is a contradiction-resolution rather than a relaxation — comparable to the v1.9.0 entries in §13's revision table where the spec was corrected to what every implementation already did — so no dual-accept window is required: there is no prior behaviour to accept.
Approval
Per
CLAUDE.mdandGOVERNANCE.md§ Decision Making, adocs/spec/protocol-spec.mdchange needs a linked issue (this one) and maintainer approval — 2 maintainers, or all of them when fewer than 3 exist.MAINTAINERS.mdlists one, so one approval satisfies it.