Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,14 @@ AGENTS.md hard boundary on body-bearing GitHub operations.
- [ ] `OperationShape` remains upstream of `CommandShape`
- [ ] Evidence includes provenance/freshness where applicable
- [ ] Dashboard impact considered
- [ ] **Citation discipline** — every citation used as *authorization* quotes its
enclosing section heading verbatim in the PR body. If the heading reads
"Out of scope", the citation refutes itself on sight. (D-085: an
`adr/0057` line was quoted as a grant when it sat inside "This ADR
explicitly does not authorize:".)
- [ ] **Citation discipline** — a citation used as *authorization* must establish
that the document **authorizes** the thing, not merely that it mentions it.
Quote the ADR's own scope statement and show the cited line falls inside
it. Checking the cited section's heading is NOT sufficient: D-085 quoted an
`adr/0057` line sitting under "This ADR explicitly does not authorize:",
and D-086 then cited `adr/0060` §Provenance verification — correct heading,
correct text — while that same ADR's §Out of scope declined to authorize
the implementation. Two failures, two different locations, one property.
- [ ] **Precedence respected** — `AGENTS.md` §Source of truth ranks `adr/` above
`IMPLEMENT.md`. A rule stated in an accepted ADR is not relieved by
editing `IMPLEMENT.md`; amend the ADR, then restate below it.
Expand Down
1 change: 1 addition & 0 deletions DECISIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ Rows are ordered by **acceptance date**, not by D-number. A few early rows (D-03
| D-083 | Phase-0b hook lane decommissioned on both runtimes. `.claude/settings.json` drops its `hooks` key and `.codex/hooks.json` becomes `{"hooks": {}}`; both `hcs-hook` wrappers stay on disk as the Phase-3 attachment point, and the two never-registered `hcs-log-hook.sh` files are deleted. `scripts/install/install-claude-hook.sh` now refuses to run without an explicit override. Supersedes D-047's *registered* thin-wrapper posture; D-047's substantive rule (no hook-local policy arrays) is unchanged and still gated. | The measurement window closed 2026-04-26 but collection ran 90 days past it: the LaunchAgent fired daily, `.logs/` reached 2.2 GB across 99 partitions, and the user-scope installer captured six repos across three GitHub owners — including `the-nash-group/the-citadel`, a different Organizations entity — into this repo. HCS-cwd records were double-written 2:1 by the overlapping global and project registrations, so any metric derived from those partitions is inflated. Nothing has consumed the output since 2026-04-26. OPEN QUESTION, deliberately not answered here: `scripts/dev/hcs-hook-cli.sh` returns `permissionDecision: "allow"` on every path and has no `deny`, and a `PreToolUse` hook returning `allow` on matcher `Bash` is documented to bypass the permission system — so this hook may have been neutering the `.claude/settings.json` deny list (`sudo`, `csrutil`, `launchctl load|unload`, `rm -rf /`) for its whole life. That must be settled by fixture against the installed CLI, not by reasoning; golden inputs exist at `tests/fixtures/hooks/forbidden__*.json`. Until settled, neither registration returns. Removal is therefore recorded as a net security gain, not neutral cleanup. Retention of the 99 existing `.logs/` partitions is a SEPARATE decision and is NOT authorized by this row — inv-13 requires its own deletion-authority source. | Supersedes the registered half of D-047; ADR 0007 unchanged and still the Phase-3 design (annotated, not reopened) | 2026-07-25 |
| D-084 | ADR-to-ledger bidirectional integrity repair. (a) Markdown render: twelve blank lines inside the Accepted table (former lines 138-158 and 186) split it into thirteen fragments, so every row from D-042 onward — the whole M1/M2 arc, all tool-baseline re-baselines, and the ADR 0073-0078 acceptances — rendered as literal pipe text on github.com. Blanks removed; a note above the table records that rows are ordered by acceptance date, not by D-number. (b) Status flips: ADRs **0002** (runtime), **0003** (transport topology) and **0008** (dashboard auth) each read `status: proposed` while this ledger listed them Accepted at D-002, D-009 and D-015 respectively, all dated 2026-04-22. All three flipped to `accepted`; each decision is accepted **as written**, with no change to its recommendation. (c) Backfilled references: ADRs **0009** (ontology versioning), **0013** (forbidden tier split), **0014** (InterventionRecord) and **0039** (charter v1.4.0 invariants 18+19) are `status: accepted` but appear nowhere in this ledger; they are recorded here rather than given four retroactive rows, because inventing dated acceptance rows for decisions whose real acceptance dates are unrecoverable would fabricate provenance. ADR 0039 is the sharpest case — the charter change log credits invariants 18 and 19 to it, and both are live charter text. The `Decision ledger:` lines in ADRs 0013 and 0014 cited unrelated rows (D-025/D-026/D-032) and now point here. | The ledger is the human-readable decision record and the repo is a public portfolio surface; a table that does not render defeats both. The three flips close a contradiction where the ADR and the ledger disagreed about the same decision — a reader following either one alone got a different answer. Phase 1 Thread B, the accept trigger both 0002 and 0003 named, is retired as a decision gate rather than run: for 0002 the installed runtime settles the axis Thread B was scoped to measure (observed 2026-07-25 on this host, charter inv. 14: `node --version` = v24.18.0; `node:sqlite` exports DatabaseSync/StatementSync/Session/constants/backup; `process.versions.sqlite` = 3.53.1 — Node ships SQLite in-core with the synchronous single-writer API ADR 0077 needs), and for 0003 no finding could argue against localhost-only, which is the conservative option and already the operative posture. ADR 0008 is recorded as a decision, NOT as construction: no dashboard exists, Ring 3 is `.gitkeep`-only, and accepting it authorizes no implementation and starts no milestone. Rows are NOT reordered — D-037..D-044 were accepted out of numeric order and the ledger is append-only; rewriting recorded history for a cosmetic property is a worse defect than the one it fixes. | ADR 0002 / 0003 / 0008 status flips; ADR 0009 / 0013 / 0014 / 0039 reference backfill | 2026-07-25 |
| D-085 | `PLAN.md` collapses 1,579 -> ~290 lines: the ~1,190-line superseded prior-focus stack is removed (preserved at `3063d9f`; `git show 3063d9f:PLAN.md`) and §Current Focus is capped at 20 lines. Milestones 0-6 are **retained** with their acceptance criteria; two demonstrably false statements inside them are corrected — the M3 hash bullet, which specified naive concatenation that `adr/0064:453-456` forbids, and eight scoped `just test` invocations naming targets the justfile rejects. Three checklist rules and regression trap #61 are added, earned by the withdrawn attempt described below. | The prior-focus prose is narration, not obligation: its decisions are in this ledger, its designs in `adr/`, its status in the dated readouts, so a third copy is pure maintenance cost. The milestone blocks were NOT deleted because the ground for doing so did not survive checking — `adr/0010:19` enumerates M4's five tools in accepted text, and `adr/0004` §References anchors M3's `facts`/`fact_observations` to the external research plan, so "no matching ADR" was false for both; correcting the two provably wrong statements removes the implementer trap without a claim that fails scrutiny. **Withdrawn from this change:** an earlier commit (`3e9b314`, dropped, never pushed) also redefined change class I by callability. Five reviewer lenses found it unmergeable — it quoted `adr/0057:422-423` as authorizing an ApprovalGrant mint when that line sits inside "This ADR explicitly does not authorize:" whose final bullet is "Ring 1 service implementation code"; it restated `charter:54`'s "is live" as "exist", weakening a binding invariant; it claimed "supersedes no ADR" while contradicting `adr/0077`'s nine class-I self-classifications; and it placed write paths in a class labelled "kernel read path". It is relocated, not rejected: the audit-append relief belongs in the PR that implements the audit append, where code exercises the wording. Nothing is blocked — the policy-snapshot loader stands on `adr/0060:325-331` and `adr/0061:371`. | Trap #61; `adr/0064:452-456`; `adr/0010:19`; `adr/0004` §References; no ADR superseded | 2026-07-25 |
| D-086 | Ring-1 policy-rule loader lands at `packages/kernel/src/policy/rule-loader.ts` under **ADR 0079**, scoped to rule shape only: parse, project `operation_class_defaults` into `PolicyRule`, validate against `policyRuleSchema`, assert exact `operation_class` set equality both ways. Provenance/digest verification is **explicitly out of scope** and stays with `scripts/ci/snapshot-binding-check.sh`. Every projected value is read from a field policy declares; where policy is silent the loader rejects, with one recorded authored default (`approval_path_allowed` when the tier does not declare it — provably inert, since the schema pins it to `true` on the only branch where it is consulted). | Supersedes a withdrawn attempt (`3e9b314`-lineage, PR #98, converted to draft, never merged) that combined provenance verification with projection. Five reviewer lenses found it unmergeable on two counts. **First, it was not authorized:** it cited ADR 0060 §Provenance verification, while that ADR's §Out of scope declines to authorize "the §Provenance-verification implementation" and defers it to a follow-up gateway ADR that does not exist — the same failure class as trap #61, one day after that trap was seeded, which proved the rule too narrow (it named a location, not a property; now generalized in `IMPLEMENT.md` §Per-PR checklist). **Second, it failed open:** it derived approval posture from the PRESENCE of an `approval_required_details` block, and in YAML `approval_required_details:` with no value parses to `null`, so "not a mapping" read as "absent" and absent projected `approval_required: false` on a `write-destructive` class — while the CI checker it proposed to replace fails closed on the same bytes. That is the fifth instance of one repo-wide pattern (boundary-check rc=2 read as pass; `no-live-secrets` malformed pattern read as clean; the justfile's missing toolchain read as exit 0; the Phase-0b hook's missing deny path read as allow), so the test suite now carries a **fail-closed class** that feeds the null / absent / wrong-type variant of every security-relevant field and asserts rejection. Investigating it established that live policy declares approval posture in **three** places (`tiers.<tier>`, `operation_class_defaults.<class>`, and that class's `approval_required_details.status`) and that `valid_until_ceiling` is declared per tier and per class — values the withdrawn draft authored as `'not_applicable'` rather than read. A schema change was considered and rejected as unnecessary: `policyRuleApprovalSchema` already rejects absent, `null`, and `"false"`; the defect was that the loader never passed policy's declared value to it. Retiring the Ruby lane is NOT part of this decision — with provenance out of scope the two checkers answer disjoint questions, so no inv-1 duplication surface exists. | ADR 0079 (ships with this code per D-085's successor rule); ADR 0060 §Out of scope (why provenance is deferred); trap #61 second occurrence | 2026-07-25 |

## Reversed

Expand Down
13 changes: 8 additions & 5 deletions IMPLEMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,14 @@ Follow `PLAN.md` milestone by milestone.
- [ ] `OperationShape` remains upstream of `CommandShape`
- [ ] Evidence includes provenance/freshness where applicable
- [ ] Dashboard impact considered
- [ ] **Citation discipline** — every citation used as *authorization* quotes its
enclosing section heading verbatim in the PR body. If the heading reads
"Out of scope", the citation refutes itself on sight. (D-085: an
`adr/0057` line was quoted as a grant when it sat inside "This ADR
explicitly does not authorize:".)
- [ ] **Citation discipline** — a citation used as *authorization* must establish
that the document **authorizes** the thing, not merely that it mentions it.
Quote the ADR's own scope statement and show the cited line falls inside
it. Checking the cited section's heading is NOT sufficient: D-085 quoted an
`adr/0057` line sitting under "This ADR explicitly does not authorize:",
and D-086 then cited `adr/0060` §Provenance verification — correct heading,
correct text — while that same ADR's §Out of scope declined to authorize
the implementation. Two failures, two different locations, one property.
- [ ] **Precedence respected** — `AGENTS.md` §Source of truth ranks `adr/` above
`IMPLEMENT.md`. A rule stated in an accepted ADR is not relieved by
editing `IMPLEMENT.md`; amend the ADR, then restate below it.
Expand Down
4 changes: 2 additions & 2 deletions PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ readouts; decisions belong in `DECISIONS.md`. This section states status only.
- **M1 COMPLETE** — 22/22 canonical Ring-0 entities, plus post-M1 `Model`
(ADR 0076 / D-077) and the ADR 0078 / D-081 `model_ref` slice.
- **Versions:** ontology **v1.34.0** · registry **v0.4.37** · charter **v1.6.0** ·
ADRs **0001–0078** (0026 absent, reserved — see `adr/0025` §Future amendments) ·
decisions through **D-085** (next-free **D-086**).
ADRs **0001–0079** (0026 absent, reserved — see `adr/0025` §Future amendments) ·
decisions through **D-086** (next-free **D-087**).
- **M2 residue:** the ADR 0034 boundary-evidence consumption matrix
(`Decision`/`ApprovalGrant` × {stale, missing, contradictory}) is the one
acceptance bullet still open. PolicyRule schema ref (D-078), freshness windows
Expand Down
Loading
Loading