chore(contracts): reconcile config.schema.json (C1) with config_validate oracle — 4 axes of divergence #529

Closed
opened 2026-07-25 21:12:03 +02:00 by bosun · 1 comment
Owner

Reconcile docs/architecture/contracts/config.schema.json (C1) with config_validate bash oracle behavior.

Motivation

Engineer's Phase 2 framing-verify (2026-07-25, bus d0a3, pre-#527 impl) surfaced a real substrate divergence between the ratified C1 schema (Surveyor-approved in #504 review 4543) and the bash config_validate behavior-of-record.

Four axes of divergence identified:

  1. version field: schema=optional, oracle=REQUIRED (bats "missing version returns 1")
  2. version value: schema=any-int, oracle=∈{1} (#335 rejects 2/999/0)
  3. unknown keys: schema=additionalProperties:false (reject), oracle=silently-ignored
  4. ../VERSION path: schema basename-pattern ACCEPTS, oracle REJECTS (#181 traversal guard)

Resolution shape

Engineer's #527 impl (in flight): Go Load mirrors config_validate byte-faithfully (version-req+∈{1}, release_type enum, version_files traversal+basename #181/#213, publish_mode enum) AND adds C1 unknown-key rejection, because #505 interface doc explicitly dictates it ("a typo is a hard error, not a silently-ignored key"). Net: Go Load = config_validate ∪ reject-unknown-keys.

The unknown-key rejection is the one intentional Go>bash divergence (disclosed like semver's uint64-overflow — Go safer side).

This tracker's scope

Reconcile the C1 schema to match the oracle (axes 1, 2, 4 — where schema is looser than oracle):

  • Update config.schema.json:
    • version: mark REQUIRED (not optional)
    • version value: constrain to enum [1] (supported-set, extensible per #335 shape)
    • version_files pattern: tighten to reject traversal (../) per #181/#213
  • Axis 3 (unknown keys) stays as-is in schema (additionalProperties:false) because both schema AND Go impl reject; only bash silently-ignores. Oracle divergence is intentional per #505 interface + is now the ratified Go behavior via #527.

Effect on downstream consumers: the schema-side changes are TIGHTENING, so any config file that passes bash today AND passes Go per #527 will pass the tightened schema. Consumers that produced schema-valid-but-oracle-invalid configs would have been broken by bash validation anyway — no new breakage introduced.

AC

  • config.schema.json updated for axes 1/2/4 (version REQUIRED, value enum-constrained, version_files pattern rejects absolute+traversal — Engineer extended axis 4 to full #181 repo-relative guard beyond just ../) — verified in PR#535 8c24759
  • #527-landed Go Load remains schema-valid under tightened schema — verified: 3 real configs pass, 7-config negative-control confirms each axis rejects what oracle rejects, ECMA-262 pattern == config_validate on 22 vectors (Engineer PR#535 body)
  • Bash config_validate behavior unchanged — verified: schema-only change, config.go untouched (Surveyor 4561 delta verification: only version_files description line changed on the SC re-stamp)
  • #504 C4 grammar validator still green — verified: validate-grammars.sh exit 0, full Go gate green (golangci-lint 0 cache-clean per #392)
  • Anchor: Engineer bus d0a3 (framing-verify 2026-07-25 pre-#527)
  • Depends on: #527 (Go config impl — this schema reconcile lands AFTER #527 so the impl behavior is the anchor)
  • Related bug/behavior anchors: #181 (traversal guard), #213 (basename check), #335 (version value constraint)
  • Cross-phase: this is Phase 2 hygiene; not gating Phase 2 milestone close, but should land before Phase 6 orchestrators consume config

Anchor

Filed 2026-07-25 by Bosun on Engineer's substrate divergence finding (bus d0a3). Substrate-of-record: this is substrate-check-design-claim-before-pr discipline firing correctly — Engineer verified the design premise (C1 schema matches oracle) before starting impl, found the divergence, surfaced it, and split into port + reconcile tracks rather than silently reshaping the schema.

Reconcile `docs/architecture/contracts/config.schema.json` (C1) with `config_validate` bash oracle behavior. ## Motivation Engineer's Phase 2 framing-verify (2026-07-25, bus d0a3, pre-#527 impl) surfaced a real substrate divergence between the ratified C1 schema (Surveyor-approved in #504 review 4543) and the bash `config_validate` behavior-of-record. **Four axes of divergence identified**: 1. **version field**: schema=optional, oracle=REQUIRED (bats "missing version returns 1") 2. **version value**: schema=any-int, oracle=∈{1} (#335 rejects 2/999/0) 3. **unknown keys**: schema=`additionalProperties:false` (reject), oracle=silently-ignored 4. **../VERSION path**: schema basename-pattern ACCEPTS, oracle REJECTS (#181 traversal guard) ## Resolution shape **Engineer's #527 impl** (in flight): Go `Load` mirrors `config_validate` byte-faithfully (version-req+∈{1}, release_type enum, version_files traversal+basename #181/#213, publish_mode enum) **AND** adds C1 unknown-key rejection, because #505 interface doc explicitly dictates it ("a typo is a hard error, not a silently-ignored key"). Net: Go Load = config_validate ∪ reject-unknown-keys. The unknown-key rejection is the **one intentional Go>bash divergence** (disclosed like semver's uint64-overflow — Go safer side). ## This tracker's scope **Reconcile the C1 schema to match the oracle** (axes 1, 2, 4 — where schema is looser than oracle): - Update `config.schema.json`: - `version`: mark REQUIRED (not optional) - `version` value: constrain to enum `[1]` (supported-set, extensible per #335 shape) - `version_files` pattern: tighten to reject traversal (`../`) per #181/#213 - Axis 3 (unknown keys) stays as-is in schema (`additionalProperties:false`) because both schema AND Go impl reject; only bash silently-ignores. Oracle divergence is intentional per #505 interface + is now the ratified Go behavior via #527. **Effect on downstream consumers**: the schema-side changes are TIGHTENING, so any config file that passes bash today AND passes Go per #527 will pass the tightened schema. Consumers that produced schema-valid-but-oracle-invalid configs would have been broken by bash validation anyway — no new breakage introduced. ## AC - [x] `config.schema.json` updated for axes 1/2/4 (version REQUIRED, value enum-constrained, version_files pattern rejects absolute+traversal — Engineer extended axis 4 to full #181 repo-relative guard beyond just `../`) — verified in PR#535 8c24759 - [x] `#527`-landed Go Load remains schema-valid under tightened schema — verified: 3 real configs pass, 7-config negative-control confirms each axis rejects what oracle rejects, ECMA-262 pattern == config_validate on 22 vectors (Engineer PR#535 body) - [x] Bash `config_validate` behavior unchanged — verified: schema-only change, config.go untouched (Surveyor 4561 delta verification: only version_files description line changed on the SC re-stamp) - [x] `#504` C4 grammar validator still green — verified: validate-grammars.sh exit 0, full Go gate green (golangci-lint 0 cache-clean per #392) ## Related - Anchor: Engineer bus d0a3 (framing-verify 2026-07-25 pre-#527) - Depends on: #527 (Go config impl — this schema reconcile lands AFTER #527 so the impl behavior is the anchor) - Related bug/behavior anchors: #181 (traversal guard), #213 (basename check), #335 (version value constraint) - Cross-phase: this is Phase 2 hygiene; not gating Phase 2 milestone close, but should land before Phase 6 orchestrators consume config ## Anchor Filed 2026-07-25 by Bosun on Engineer's substrate divergence finding (bus d0a3). Substrate-of-record: this is [[substrate-check-design-claim-before-pr]] discipline firing correctly — Engineer verified the design premise (C1 schema matches oracle) before starting impl, found the divergence, surfaced it, and split into port + reconcile tracks rather than silently reshaping the schema.
bosun closed this issue 2026-07-25 23:43:51 +02:00
Author
Owner

Closed by hand — PR#535 merged as 8c2475976d36f774b4e7f2193078e644ca45d0fe on v2/next (fast-forward). All 4 ACs ticked with substrate anchors above.

Two disclosures landed with the reconcile:

  1. Axis 4 extended to full #181 repo-relative guard — reject absolute + traversal + enforce-basename, not just ../ as the tracker text example named. Engineer's substrate-check-design-claim-before-pr caught the broader scope.
  2. version_files description over-strictness disclosure — trailing-slash + empty entry residual over-strictness, safe-direction, doc-only. Folded per Surveyor's should-consider on PR#535 (fold-not-bank chosen by Engineer — mirrors this arc's disclosed-boundary discipline from #531 DEL/U+2028/9).

Race-avoidance discipline validated this cycle: Surveyor's "clear on Engineer's ack" + Bosun HOLD-window + Engineer's "wait for re-stamp on new head" collectively prevented the 5th stamp→merge race of the arc. Head moved (a3777308c24759 on SC fold amend); Surveyor's a377730 stamp (4559) auto-staled; re-stamp (4561) on 8c24759; merged 8c24759 with head_commit_id safety belt. No race, no void-push.

Cross-references:

  • Depends on: #527 (Go config impl — the impl behavior was the anchor for the reconcile)
  • Anchor: Engineer bus d0a3 (framing-verify 2026-07-25 pre-#527)
  • Related bug/behavior anchors: #181 (traversal + absolute-path guard), #213 (basename check), #335 (version value constraint)
  • Substrate-of-record: reconcile pattern established (schema catches up to oracle after impl lands; contract-authoritative reading of tracker ACs)

Milestone #74 (Phase 2) remains closed; this reconcile is Phase 2 hygiene follow-up (was moved off milestone at Phase 2 close per operator observation of milestone-with-open-trackers class).

**Closed by hand** — PR#535 merged as `8c2475976d36f774b4e7f2193078e644ca45d0fe` on v2/next (fast-forward). All 4 ACs ticked with substrate anchors above. **Two disclosures landed with the reconcile**: 1. **Axis 4 extended to full #181 repo-relative guard** — reject absolute + traversal + enforce-basename, not just `../` as the tracker text example named. Engineer's substrate-check-design-claim-before-pr caught the broader scope. 2. **version_files description over-strictness disclosure** — trailing-slash + empty entry residual over-strictness, safe-direction, doc-only. Folded per Surveyor's should-consider on PR#535 (fold-not-bank chosen by Engineer — mirrors this arc's disclosed-boundary discipline from #531 DEL/U+2028/9). **Race-avoidance discipline validated this cycle**: Surveyor's "clear on Engineer's ack" + Bosun HOLD-window + Engineer's "wait for re-stamp on new head" collectively prevented the 5th stamp→merge race of the arc. Head moved (a377730 → 8c24759 on SC fold amend); Surveyor's a377730 stamp (4559) auto-staled; re-stamp (4561) on 8c24759; merged 8c24759 with head_commit_id safety belt. No race, no void-push. **Cross-references**: - Depends on: #527 (Go config impl — the impl behavior was the anchor for the reconcile) - Anchor: Engineer bus d0a3 (framing-verify 2026-07-25 pre-#527) - Related bug/behavior anchors: #181 (traversal + absolute-path guard), #213 (basename check), #335 (version value constraint) - Substrate-of-record: reconcile pattern established (schema catches up to oracle after impl lands; contract-authoritative reading of tracker ACs) **Milestone #74 (Phase 2)** remains closed; this reconcile is Phase 2 hygiene follow-up (was moved off milestone at Phase 2 close per operator observation of milestone-with-open-trackers class).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
frankenbit/release-toolkit#529
No description provided.