docs(l0): parameterize hard gates on the project's integration trunk (#1216, Option A) #1217

Merged
fred merged 3 commits from docs/1216-trunk-parameterization into next 2026-08-20 18:38:19 +00:00

Executes Jason's Option (a) ruling on #1216 (comment 22359): the constitution supplies the general framework; the project declares its own flow; no branch naming convention is forced by L0.

What changes

  • CONSTITUTION.md — defines the integration trunk once, ahead of the Hard Gates: declared by exactly one Integration trunk: <branch> line in the project's root AGENTS.md; default main; value bound by git check-ref-format --branch semantics (no remote refs, revisions, option-like values, traversal/control characters); malformed or multiple declarations are a hard stop (blocked), never a silent fallback; prose mentioning branch names designates nothing; exactly ONE trunk; designation relaxes no gate (reviewed-PR-only, squash, independent review, queue guards, terminal-green CI all bind to the declared trunk). Gates 5 and 15 now bind to the term.
  • defaults/AGENTS.md — session-closure evidence binds to the integration trunk.
  • guides/CODE-REVIEW.md — HARD RULE block, review diff command, and after-review merge step parameterized.
  • guides/E2E-DELIVERY.md — step 10 (PR integration) and post-PR hard-gate item 13 parameterized.
  • guides/ORCHESTRATOR.md / ORCHESTRATOR-PROTOCOL.md — trunk-workflow enforcement lines, worker branch/PR/merge policy, wrapper command templates, remediation checkout template, Merge-to-Trunk candidate protocol, milestone checklist.
  • guides/BOOTSTRAP.md — day-one consistency claims and Step 5b branch-protection provisioning target the declared trunk.
  • guides/CI-CD-PIPELINES.md — worked YAML examples stay on the default trunk main; a substitution note at the top classifies them; normative sentences (non-trunk-branch testing, merge step, PR-build audit) parameterized.

Consumer classification (reviewer anchors, scrappy 20260813T184158Z)

  • Controlling prose — all amended atomically in this PR (list above).
  • Executable wrapper — framework/tools/git/pr-merge.sh:133 hardcodes a {main, next} base allowlist. Fail-closed: it can refuse a legally-declared exotic trunk but cannot misroute a merge. Parameterizing it to consume the declaration (policy data, never shell text; validated per the constitution grammar) is a code change with its own red-first test surface — tracked as follow-up on #1216, not smuggled into a docs PR.
  • Non-controlling — codex-code-review.sh (--base flag, defaulted), init-project.sh (--cicd-branches flag), test-pr-metadata-gitea.sh (test fixtures), mosaic-release-upgrade* (main there is the stack repo's own bootstrap ref, not a project trunk), defaults/README.md (install URLs/lanes), CI-CD YAML examples (covered by the note).

Behavioral controls (prose contract)

  • Absent declaration → main (every existing project unchanged).
  • Explicit Integration trunk: next → next through branch/PR/completion wording end-to-end.
  • Malformed/multiple declarations → hard stop, loud, no fallback.
  • Ordinary AGENTS prose containing branch words cannot select a trunk (exact line-start grammar).
  • Tightening boundary stated: one trunk only; no relaxation of review/queue/CI gates.

Notes

  • Pre-existing prettier --check warnings on CI-CD-PIPELINES.md / ORCHESTRATOR-PROTOCOL.md are on the base (VAULT-SECRETS.md, untouched, warns identically) — not introduced here.
  • L0 change — operator-owned. No merge before Jason's explicit GO. Independent gate: scrappy (fresh exact-head diff, source-to-installed parity, composition, terminal CI).
  • After this lands on next: #1215 comes off HOLD as a now-legal tightening and gets its fresh-head re-gate.

No self-merge.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WYgWocp36goy8hj2ui6ps1

Executes Jason's **Option (a)** ruling on #1216 (comment 22359): the constitution supplies the general framework; the project declares its own flow; no branch naming convention is forced by L0. ## What changes - **CONSTITUTION.md** — defines the **integration trunk** once, ahead of the Hard Gates: declared by exactly one `Integration trunk: <branch>` line in the project's root `AGENTS.md`; default `main`; value bound by `git check-ref-format --branch` semantics (no remote refs, revisions, option-like values, traversal/control characters); malformed or multiple declarations are a hard stop (`blocked`), never a silent fallback; prose mentioning branch names designates nothing; exactly ONE trunk; designation relaxes no gate (reviewed-PR-only, squash, independent review, queue guards, terminal-green CI all bind to the declared trunk). Gates 5 and 15 now bind to the term. - **defaults/AGENTS.md** — session-closure evidence binds to the integration trunk. - **guides/CODE-REVIEW.md** — HARD RULE block, review diff command, and after-review merge step parameterized. - **guides/E2E-DELIVERY.md** — step 10 (PR integration) and post-PR hard-gate item 13 parameterized. - **guides/ORCHESTRATOR.md / ORCHESTRATOR-PROTOCOL.md** — trunk-workflow enforcement lines, worker branch/PR/merge policy, wrapper command templates, remediation checkout template, Merge-to-Trunk candidate protocol, milestone checklist. - **guides/BOOTSTRAP.md** — day-one consistency claims and Step 5b branch-protection provisioning target the declared trunk. - **guides/CI-CD-PIPELINES.md** — worked YAML examples stay on the default trunk `main`; a substitution note at the top classifies them; normative sentences (non-trunk-branch testing, merge step, PR-build audit) parameterized. ## Consumer classification (reviewer anchors, scrappy 20260813T184158Z) - **Controlling prose** — all amended atomically in this PR (list above). - **Executable wrapper** — `framework/tools/git/pr-merge.sh:133` hardcodes a `{main, next}` base allowlist. **Fail-closed**: it can refuse a legally-declared exotic trunk but cannot misroute a merge. Parameterizing it to consume the declaration (policy data, never shell text; validated per the constitution grammar) is a code change with its own red-first test surface — tracked as follow-up on #1216, not smuggled into a docs PR. - **Non-controlling** — `codex-code-review.sh` (`--base` flag, defaulted), `init-project.sh` (`--cicd-branches` flag), `test-pr-metadata-gitea.sh` (test fixtures), `mosaic-release-upgrade*` (`main` there is the stack repo's own bootstrap ref, not a project trunk), `defaults/README.md` (install URLs/lanes), CI-CD YAML examples (covered by the note). ## Behavioral controls (prose contract) - Absent declaration → `main` (every existing project unchanged). - Explicit `Integration trunk: next` → next through branch/PR/completion wording end-to-end. - Malformed/multiple declarations → hard stop, loud, no fallback. - Ordinary AGENTS prose containing branch words cannot select a trunk (exact line-start grammar). - Tightening boundary stated: one trunk only; no relaxation of review/queue/CI gates. ## Notes - Pre-existing `prettier --check` warnings on CI-CD-PIPELINES.md / ORCHESTRATOR-PROTOCOL.md are on the base (VAULT-SECRETS.md, untouched, warns identically) — not introduced here. - **L0 change — operator-owned. No merge before Jason's explicit GO.** Independent gate: scrappy (fresh exact-head diff, source-to-installed parity, composition, terminal CI). - After this lands on `next`: #1215 comes off HOLD as a now-legal tightening and gets its fresh-head re-gate. No self-merge. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01WYgWocp36goy8hj2ui6ps1
Ghost added 1 commit 2026-08-13 18:46:26 +00:00
Per Jason's Option-A ruling on #1216: the constitution supplies the general
framework; the project declares its own flow. Defines the integration trunk
once in CONSTITUTION.md Hard Gates — declared by exactly one
'Integration trunk: <branch>' line in the project's root AGENTS.md, default
'main', value bound by git check-ref-format --branch semantics, malformed or
multiple declarations are a hard stop, one trunk only, no gate relaxation —
and binds gates 5/15, E2E-DELIVERY, CODE-REVIEW, ORCHESTRATOR(-PROTOCOL),
BOOTSTRAP provisioning, and the defaults AGENTS session closure to that term.
CI-CD-PIPELINES YAML examples stay on the default trunk with a substitution
note.

Known mechanized consumer left as tracked follow-up on #1216: pr-merge.sh:133
hardcodes a {main,next} base allowlist — fail-closed (refuses exotic trunks,
cannot misroute), to be parameterized with red-first tests separately.

Refs #1216

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01WYgWocp36goy8hj2ui6ps1
rev-security-01 approved these changes 2026-08-20 16:26:37 +00:00
Dismissed
rev-security-01 left a comment
Member

Security review — rev-security-01 (sections 2 Security, 2a OWASP). Head measured: 18f960d3e1 (read at the PR head ref; the PR's consumer-classification claim about pr-merge.sh was verified by content at that ref). Reviewed independently; no other review bodies were read.

Verdict: APPROVE with two Should Fix. Reviewed against the criterion for this PR: does parameterization make the gates ENFORCEABLE and unambiguous — not whether it is looser or stricter.

On the criterion. The declaration grammar is single-parse and machine-checkable: exact case-sensitive key at line start, one value (optionally backtick-wrapped), nothing else on the line, root AGENTS.md only; value bound to git check-ref-format --branch semantics; a malformed value or more than one declaration line is a hard stop, never a silent fallback; ordinary prose designates nothing; absent declaration defaults to main. The term is applied consistently across all eight amended files with a default gloss at each use site. This converts a hardcoded assumption into a checkable declaration. The wrapper gap is correctly staged: pr-merge.sh refuses any base outside {main, next} and exits 1 — fail-closed (it can refuse a legal exotic trunk, it cannot misroute a merge), mismatch direction code-stricter-than-prose, which L0 precedence permits; parameterizing it is tracked as the #1216 code follow-up, not smuggled into a docs PR.

[SHOULD FIX] Near-miss keys are silently non-declarations. Integration Trunk: next (case slip) or Integration trunk : next (spacing) is ordinary prose that designates nothing, and the project silently runs on the default main. The intent-failure mode this PR exists to eliminate (the 2026-08-05..08-13 main/next targeting divergence) recurs through a one-character typo with no signal. Fix direction: classify key-near-miss lines (case-insensitive key match, or adjacent whitespace/punctuation variance) as malformed declarations → hard stop, or have the future validator flag them — keeping "never a silent fallback" true for intent, not just the byte-exact grammar.

[SHOULD FIX] Changing an existing declaration is ungated. A PR that adds or edits the Integration trunk: line redirects every gate binding — merge target, completion evidence, and the BOOTSTRAP 5b branch-protection target — through ordinary PR review, with no requirement that branch protection be re-provisioned to the new trunk or that a redeclaration be operator-owned. Gate 16 independent review still applies; the residual risk is a docs-looking line slipping a careless review. Fix direction: one sentence in the amendment making a change to an existing declaration operator-owned (mirroring the L0 GO this PR itself models), and/or a BOOTSTRAP re-protection step on trunk change.

Notes (not defects of this PR). (1) D31 (squash-only vs divergence-absorb) and D29 (compaction-hook revoke with nothing to revoke) are not addressed and remain open: gate 15 keeps squash absolute. This PR makes the trunk binding unambiguous; the merge-strategy and hook ambiguities persist unchanged — out of scope, stated plainly. (2) Enforcement for a legally-declared exotic trunk is incomplete until the #1216 wrapper follow-up lands; interim failure direction is blocked, the correct direction. (3) Deployment step: projects running a non-main trunk must add their declaration line or gates silently bind to the default (the stack itself would need its own Integration trunk: next line — not in this PR).

Merge gating. CI on head 18f960d is green (pipeline 2414), but the branch was cut 2026-08-13, predating the 2026-08-19 23:42Z base-image pin — an UNPINNED green; reproducibility does not extend to it. No restart requested. L0 change: the PR's own operator-GO gate stands regardless of this approval.

Security review — rev-security-01 (sections 2 Security, 2a OWASP). Head measured: 18f960d3e119 (read at the PR head ref; the PR's consumer-classification claim about pr-merge.sh was verified by content at that ref). Reviewed independently; no other review bodies were read. **Verdict: APPROVE with two Should Fix.** Reviewed against the criterion for this PR: does parameterization make the gates ENFORCEABLE and unambiguous — not whether it is looser or stricter. **On the criterion.** The declaration grammar is single-parse and machine-checkable: exact case-sensitive key at line start, one value (optionally backtick-wrapped), nothing else on the line, root `AGENTS.md` only; value bound to `git check-ref-format --branch` semantics; a malformed value or more than one declaration line is a hard stop, never a silent fallback; ordinary prose designates nothing; absent declaration defaults to `main`. The term is applied consistently across all eight amended files with a default gloss at each use site. This converts a hardcoded assumption into a checkable declaration. The wrapper gap is correctly staged: `pr-merge.sh` refuses any base outside `{main, next}` and exits 1 — fail-closed (it can refuse a legal exotic trunk, it cannot misroute a merge), mismatch direction code-stricter-than-prose, which L0 precedence permits; parameterizing it is tracked as the #1216 code follow-up, not smuggled into a docs PR. **[SHOULD FIX] Near-miss keys are silently non-declarations.** `Integration Trunk: next` (case slip) or `Integration trunk : next` (spacing) is ordinary prose that designates nothing, and the project silently runs on the default `main`. The intent-failure mode this PR exists to eliminate (the 2026-08-05..08-13 main/next targeting divergence) recurs through a one-character typo with no signal. Fix direction: classify key-near-miss lines (case-insensitive key match, or adjacent whitespace/punctuation variance) as malformed declarations → hard stop, or have the future validator flag them — keeping "never a silent fallback" true for intent, not just the byte-exact grammar. **[SHOULD FIX] Changing an existing declaration is ungated.** A PR that adds or edits the `Integration trunk:` line redirects every gate binding — merge target, completion evidence, and the BOOTSTRAP 5b branch-protection target — through ordinary PR review, with no requirement that branch protection be re-provisioned to the new trunk or that a redeclaration be operator-owned. Gate 16 independent review still applies; the residual risk is a docs-looking line slipping a careless review. Fix direction: one sentence in the amendment making a change to an existing declaration operator-owned (mirroring the L0 GO this PR itself models), and/or a BOOTSTRAP re-protection step on trunk change. **Notes (not defects of this PR).** (1) D31 (squash-only vs divergence-absorb) and D29 (compaction-hook revoke with nothing to revoke) are not addressed and remain open: gate 15 keeps squash absolute. This PR makes the trunk binding unambiguous; the merge-strategy and hook ambiguities persist unchanged — out of scope, stated plainly. (2) Enforcement for a legally-declared exotic trunk is incomplete until the #1216 wrapper follow-up lands; interim failure direction is blocked, the correct direction. (3) Deployment step: projects running a non-main trunk must add their declaration line or gates silently bind to the default (the stack itself would need its own `Integration trunk: next` line — not in this PR). **Merge gating.** CI on head 18f960d is green (pipeline 2414), but the branch was cut 2026-08-13, predating the 2026-08-19 23:42Z base-image pin — an UNPINNED green; reproducibility does not extend to it. No restart requested. L0 change: the PR's own operator-GO gate stands regardless of this approval.
fred added 2 commits 2026-08-20 18:07:42 +00:00
Amendment per operator GO (ms-grill-me design round, 2026-08-20):

- Declaration is .mosaic/repo.json under integration_trunk, not a
  byte-exact AGENTS.md line. Unknown/misspelled keys and unparsable
  files are a structural hard stop; no prose grammar to near-miss
  (Q15 answer, plan D3/D9).
- Changing an existing declaration is operator-owned, above ordinary
  PR review (SF2, plan D10).
- Seeds this repo's declaration: integration_trunk next,
  release_branch main — prevents the absent-declaration default from
  rebinding the stack to main at land time.
- Gloss references in BOOTSTRAP/CODE-REVIEW/CI-CD-PIPELINES point at
  repo.json; merge of origin/next restores pinned-image CI coverage
  for this pre-pin branch (D27 caveat).
fred dismissed rev-security-01's review 2026-08-20 18:07:42 +00:00
Reason:

New commits pushed, approval review dismissed automatically according to repository settings

rev-security-01 approved these changes 2026-08-20 18:36:29 +00:00
rev-security-01 left a comment
Member

Re-review at amended head 80b8f110 — rev-security-01 (sections 2 Security, 2a OWASP). Supersedes my approval id 229 (stood at 18f960d3). Amendment verified as commit 80b8f11 in isolation from the absorbed origin/next merge (3acd3de): exactly 5 files — the new .mosaic/repo.json seed plus CONSTITUTION, BOOTSTRAP, CI-CD-PIPELINES, CODE-REVIEW.

Verdict: APPROVE at this head. All three D11 conditions verified met:

  1. SF2/D10 is in the L0 text (CONSTITUTION Hard Gates): changing an existing declaration is operator-owned, above ordinary PR review. Its mechanical enforcement (repo-config.sh set refusal + CI check on repo.json diffs) is correctly staged for #1216; the interim is prose-binding with the same fail direction as the wrapper gap I recorded as N2, and a redeclaration now surfaces as a tracked-file diff rather than a docs-looking line.
  2. SF1 is fixed structurally, not by rule. The grammar is .mosaic/repo.json; a parse failure, an unknown or misspelled key, or an invalid value is a hard stop — never a silent fallback to main. JSON has no near-miss prose surface: a key is either exact or refused. Q15 answered (option a), adopted by construction.
  3. Fresh pinned green verified: pipeline 2567, success on 80b8f110, started 2026-08-20T18:07:44Z — after the 2026-08-19 23:42Z image pin — with ALL steps green including test, the step that is red on #1268 and #1281. This is the first pinned green in this review queue.

Also verified: the seed .mosaic/repo.json {integration_trunk: next, release_branch: main} sits at repo root beside quality-rails.yml (the established declarative-policy location), closing the §3 rebind hazard where an absent declaration would default the stack to main; gates 5 and 15 bind to the integration trunk; gloss pointers updated in BOOTSTRAP/CODE-REVIEW/CI-CD-PIPELINES with no stale byte-exact grammar references remaining in framework files (the lone Integration trunk: string is the CI-CD callout heading, not a declaration rule); ledger Q7 and Q15 both carry substantive answers in their own files.

Notes for the #1216/A3 follow-up (non-blocking): (a) duplicate JSON keys — parsers typically last-wins — are the remaining silent-wrong-value path; repo-config.sh should reject duplicates when it lands, closing the last corner of the near-miss class. (b) release_branch is now L0 metadata with no gate binding to it and squash-only text untouched; D5's shape-gated release-PR strategy remains #1216 scope, with ledger Q2 (D31) open until A3. (c) Absent release_branch vs explicit null both read as no-release — fail-safe; the validator may normalize.

Merge authority on this PR remains with fred/Jason per the adoption ruling; this approval is the security-sections verdict at this head.

Re-review at amended head 80b8f110 — rev-security-01 (sections 2 Security, 2a OWASP). Supersedes my approval id 229 (stood at 18f960d3). Amendment verified as commit 80b8f11 in isolation from the absorbed origin/next merge (3acd3de): exactly 5 files — the new `.mosaic/repo.json` seed plus CONSTITUTION, BOOTSTRAP, CI-CD-PIPELINES, CODE-REVIEW. **Verdict: APPROVE at this head.** All three D11 conditions verified met: 1. **SF2/D10 is in the L0 text** (CONSTITUTION Hard Gates): changing an existing declaration is operator-owned, above ordinary PR review. Its mechanical enforcement (repo-config.sh set refusal + CI check on repo.json diffs) is correctly staged for #1216; the interim is prose-binding with the same fail direction as the wrapper gap I recorded as N2, and a redeclaration now surfaces as a tracked-file diff rather than a docs-looking line. 2. **SF1 is fixed structurally, not by rule.** The grammar is `.mosaic/repo.json`; a parse failure, an unknown or misspelled key, or an invalid value is a hard stop — never a silent fallback to main. JSON has no near-miss prose surface: a key is either exact or refused. Q15 answered (option a), adopted by construction. 3. **Fresh pinned green verified**: pipeline 2567, success on 80b8f110, started 2026-08-20T18:07:44Z — after the 2026-08-19 23:42Z image pin — with ALL steps green including `test`, the step that is red on #1268 and #1281. This is the first pinned green in this review queue. **Also verified:** the seed `.mosaic/repo.json` {integration_trunk: next, release_branch: main} sits at repo root beside quality-rails.yml (the established declarative-policy location), closing the §3 rebind hazard where an absent declaration would default the stack to main; gates 5 and 15 bind to the integration trunk; gloss pointers updated in BOOTSTRAP/CODE-REVIEW/CI-CD-PIPELINES with no stale byte-exact grammar references remaining in framework files (the lone `Integration trunk:` string is the CI-CD callout heading, not a declaration rule); ledger Q7 and Q15 both carry substantive answers in their own files. **Notes for the #1216/A3 follow-up (non-blocking):** (a) duplicate JSON keys — parsers typically last-wins — are the remaining silent-wrong-value path; repo-config.sh should reject duplicates when it lands, closing the last corner of the near-miss class. (b) `release_branch` is now L0 metadata with no gate binding to it and squash-only text untouched; D5's shape-gated release-PR strategy remains #1216 scope, with ledger Q2 (D31) open until A3. (c) Absent `release_branch` vs explicit null both read as no-release — fail-safe; the validator may normalize. Merge authority on this PR remains with fred/Jason per the adoption ruling; this approval is the security-sections verdict at this head.
fred merged commit e9485c3d96 into next 2026-08-20 18:38:19 +00:00
Sign in to join this conversation.