@arbiterforge/ca-pi 0.15.2 → 0.15.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +2 -2
  2. package/package.json +1 -1
  3. package/plugins/ca-pi/CHANGELOG.md +62 -0
  4. package/plugins/ca-pi/COMMANDS.md +3 -9
  5. package/plugins/ca-pi/SKILLS.md +16 -22
  6. package/plugins/ca-pi/agents/coverage-auditor.md +16 -2
  7. package/plugins/ca-pi/generated/command-catalog.json +13 -22
  8. package/plugins/ca-pi/helpers/artifacts/ca-artifact-darwin-amd64 +0 -0
  9. package/plugins/ca-pi/helpers/artifacts/ca-artifact-darwin-arm64 +0 -0
  10. package/plugins/ca-pi/helpers/artifacts/ca-artifact-linux-amd64 +0 -0
  11. package/plugins/ca-pi/helpers/artifacts/ca-artifact-linux-arm64 +0 -0
  12. package/plugins/ca-pi/helpers/artifacts/ca-artifact-windows-amd64.exe +0 -0
  13. package/plugins/ca-pi/helpers/artifacts/ca-artifact-windows-arm64.exe +0 -0
  14. package/plugins/ca-pi/helpers/artifacts/release.json +6 -6
  15. package/plugins/ca-pi/hooks/_artifactauthoritylib.py +383 -32
  16. package/plugins/ca-pi/hooks/_artifactlib.py +3 -1
  17. package/plugins/ca-pi/hooks/_host.py +1 -1
  18. package/plugins/ca-pi/hooks/artifact-authority-hook.py +4 -21
  19. package/plugins/ca-pi/hooks/artifact-authority.py +11 -0
  20. package/plugins/ca-pi/hooks/hostapi.py +1 -1
  21. package/plugins/ca-pi/includes/command-compatibility.md +31 -0
  22. package/plugins/ca-pi/includes/farm.md +187 -36
  23. package/plugins/ca-pi/includes/maturity-coverage.md +57 -17
  24. package/plugins/ca-pi/includes/routing-table.md +10 -11
  25. package/plugins/ca-pi/includes/safety-core.md +2 -2
  26. package/plugins/ca-pi/package.json +1 -1
  27. package/plugins/ca-pi/routines/INDEX.md +12 -11
  28. package/plugins/ca-pi/routines/context-check/SKILL.md +17 -1
  29. package/plugins/ca-pi/routines/context-creation/SKILL.md +8 -1
  30. package/plugins/ca-pi/routines/debug/SKILL.md +18 -2
  31. package/plugins/ca-pi/routines/decision-lifecycle/SKILL.md +72 -118
  32. package/plugins/ca-pi/routines/decision-lifecycle/references/authoring.md +152 -0
  33. package/plugins/ca-pi/routines/decision-variance/SKILL.md +107 -133
  34. package/plugins/ca-pi/routines/decision-variance/references/analysis.md +136 -0
  35. package/plugins/ca-pi/routines/decompose/SKILL.md +8 -1
  36. package/plugins/ca-pi/routines/finishing-a-development-branch/SKILL.md +85 -7
  37. package/plugins/ca-pi/routines/post-merge-cleanup/SKILL.md +19 -2
  38. package/plugins/ca-pi/routines/refactor/SKILL.md +27 -8
  39. package/plugins/ca-pi/routines/release/SKILL.md +2 -1
  40. package/plugins/ca-pi/routines/security-architecture/SKILL.md +14 -3
  41. package/plugins/ca-pi/routines/tdd/SKILL.md +9 -5
  42. package/plugins/ca-pi/routines/tribunal/SKILL.md +28 -14
  43. package/plugins/ca-pi/skills/ca-adr/SKILL.md +103 -18
  44. package/plugins/ca-pi/skills/ca-adr-status/SKILL.md +6 -24
  45. package/plugins/ca-pi/skills/ca-cleanup/SKILL.md +241 -52
  46. package/plugins/ca-pi/skills/ca-context-check/SKILL.md +87 -24
  47. package/plugins/ca-pi/skills/ca-create-context/SKILL.md +159 -19
  48. package/plugins/ca-pi/skills/ca-debug/SKILL.md +100 -27
  49. package/plugins/ca-pi/skills/ca-decompose/SKILL.md +156 -17
  50. package/plugins/ca-pi/skills/ca-pr/SKILL.md +161 -26
  51. package/plugins/ca-pi/skills/ca-reconcile/SKILL.md +108 -30
  52. package/plugins/ca-pi/skills/ca-refactor/SKILL.md +96 -30
  53. package/plugins/ca-pi/skills/ca-release/SKILL.md +614 -39
  54. package/plugins/ca-pi/skills/ca-status/SKILL.md +1 -1
  55. package/plugins/ca-pi/skills/ca-threat-model/SKILL.md +56 -27
  56. package/plugins/ca-pi/skills/ca-tribunal/SKILL.md +105 -26
  57. package/plugins/ca-pi/routines/skill-author/SKILL.md +0 -129
  58. package/plugins/ca-pi/routines/skill-author/references/skill-template.md +0 -58
  59. package/plugins/ca-pi/skills/ca-new-skill/SKILL.md +0 -129
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: context-check
3
- description: Optional manual drift audit — report stale provenance-tracked docs (via _provenancelib drift detection across .codearbiter/.provenance/), then per stale doc offer re-scout / re-baseline / defer. Not the daily loop; commit-gate auto-heal owns routine maintenance.
3
+ description: "Audit stale provenance-tracked docs on request. Report first; re-scout or re-baseline only for selected docs."
4
+ argument-hint: "(none)"
4
5
  ---
5
6
 
6
7
  # context-check
@@ -15,6 +16,21 @@ This skill is NOT in the daily loop. Commit-gate auto-heal (Phase 5.5,
15
16
  was introduced outside a commit (e.g. a direct push, a merge you did not
16
17
  author, a manual file edit).
17
18
 
19
+ <!-- catalog-compatibility-notice:start -->
20
+ > Compatibility route. Prefer `/ca-status drift` for new explicit usage. The retained entry
21
+ > and natural-language intent use this owner under
22
+ > <plugin-root>/includes/command-compatibility.md.
23
+ <!-- catalog-compatibility-notice:end -->
24
+
25
+ ## Entry boundaries
26
+
27
+ Use this owner for a requested provenance drift audit, `/ca-status drift`, or
28
+ the explicit `/ca-context-check` compatibility entry. Explanation-only questions
29
+ and ordinary status snapshots remain read-only answers, not repair requests.
30
+ Report first. Write only after the user selects re-scout or re-baseline for that
31
+ document; never change an unselected derived document. This owner neither stages
32
+ nor commits. Routine commit-gate auto-heal is unchanged.
33
+
18
34
  ## Pre-flight
19
35
 
20
36
  Read these before computing drift:
@@ -1,10 +1,17 @@
1
1
  ---
2
2
  name: context-creation
3
- description: The brownfield back-fill. Routed to by /create-context, and by startup when .codearbiter/CONTEXT.md lacks the <!--INITIALIZED--> body marker but source code exists. Six gated phases — pre-flight, scout dispatch, synthesis, gap interview, write, lock. Reads the existing codebase through parallel scouts, drafts every surviving project-state doc, resolves gaps with the user, and locks the project as initialized.
3
+ description: Build project context from an existing codebase through isolated scouts, resolve gaps, and preserve initialization gates.
4
+ argument-hint: (none)
4
5
  ---
5
6
 
6
7
  # context-creation
7
8
 
9
+ <!-- catalog-compatibility-notice:start -->
10
+ > Compatibility route. Prefer `/ca-init --brownfield` for new usage. This installed route remains
11
+ > functional under the command-route compatibility policy at <plugin-root>/includes/command-compatibility.md;
12
+ > continue with the unchanged brownfield workflow below.
13
+ <!-- catalog-compatibility-notice:end -->
14
+
8
15
  Wrap an existing codebase in project state, without guessing. Routed to by `/create-context`, and by startup when `.codearbiter/CONTEXT.md` exists but carries no `<!--INITIALIZED-->` body marker and meaningful source code is present. When no meaningful source exists, this is the wrong skill — route to `decompose` instead.
9
16
 
10
17
  This back-fills from existing source. It complements `/ca-init`, which scaffolds an empty `.codearbiter/` for a fresh project; here the docs are derived from what is already on disk.
@@ -1,11 +1,27 @@
1
1
  ---
2
2
  name: debug
3
- description: "Investigate-then-decide root-cause analysis for a defect whose cause is unknown (distinct from /fix, which assumes a known bug). Five gated phases: capture, hypothesize, gather, decide, hand off. Investigation only, no code changes; exits to /fix, /adr, or a no-action close."
3
+ description: "Investigate an unexplained defect or unexpected behavior without changing application code. Use for root-cause diagnosis and an evidence-backed handoff. A no-action close records a board note. Not for implementing a known fix, new features, or explanation-only questions."
4
+ argument-hint: "<observed symptom>"
4
5
  ---
5
6
 
6
7
  # debug
7
8
 
8
- Find the cause first, fix it never. `debug` investigates and routes; it does not touch code. It drives one closed loop — **reproduce** (Phase 1) → confirm by cited evidence (Phases 2–3) → hand `/fix` a regression test that re-runs the repro and must pass (**verify**). The minimal repro is the anchor that closes the loop; code changes belong to `/fix`.
9
+ Select this owning procedure for a root-cause investigation, whether requested in
10
+ plain language or through `/debug`. The command spelling is not a prerequisite.
11
+ Investigation and implementation remain separate: this procedure never changes code.
12
+ It closes the reproduce, evidence, and regression-test handoff loop through `/fix`.
13
+
14
+ ## Entry boundaries
15
+
16
+ - A known bug with a named regression test belongs to `/fix` directly.
17
+ - A design discussion without failing behavior belongs to `/adr`; attribution is
18
+ still required before authoring an ADR. New behavior belongs to `/feature`.
19
+ - An explanation-only question stays in the non-mutating question-answer path;
20
+ it does not require a debug invocation or a command spelled by the user.
21
+ - Do not re-enter from an active `/fix` or `/adr` invocation. Complete that
22
+ invocation before a separate investigation; do not create a routing cycle.
23
+ - The phase gates below own symptom precision, evidence, and the one named exit.
24
+ A no-action close uses the board helper in Phase 5, never a direct file append.
9
25
 
10
26
  ## Pre-flight
11
27
 
@@ -1,116 +1,61 @@
1
1
  ---
2
2
  name: decision-lifecycle
3
- description: Author and track Architecture Decision Records. Routed to when the user invokes /adr to record a new decision or /adr-status to list ADR health. Authors numbered, dated, user-attributed ADRs under .codearbiter/decisions/, maintains supersede chains, and reports status read-only. Never authors an ADR as its own judgment — every ADR carries explicit user attribution.
3
+ description: "Record user-decided ADRs or inspect their health read-only. Preserve attribution and acceptance evidence."
4
+ argument-hint: "<decision title>"
4
5
  ---
5
6
 
6
7
  # decision-lifecycle
7
8
 
8
- Author and track ADRs. Routed to when the user invokes `/adr "<title>"` (author a new ADR) or `/adr-status [--adr N]` (list ADR health, read-only). Every ADR is user-attributed — this skill never records a decision the user did not explicitly make.
9
-
10
- The append-only decision-log format (entry fields, supersession protocol) lives in `<plugin-root>/includes/smarts/decision-log-format.md`. Read it before writing a log line; do not restate it here.
11
-
12
- **Boundary with `decision-variance`.** This skill owns ADR *authoring* and *status* (`/adr`, `/adr-status`) — recording a decision the user has already made, and reporting ADR health. `decision-variance` owns *arbitration* — detecting variances between artifacts and the scaffold, scoring options via SMARTS, and the decision log itself. The two share the canonical SMARTS reference under `<plugin-root>/includes/smarts/` (`core.md` for scoring, `decision-log-format.md` for the log) and one ADR template (`references/adr-template.md`); they are one domain split by responsibility, not duplicated. When a decision needs *making* (competing options), route to `decision-variance`; when it needs *recording* (already decided), stay here.
13
-
14
- ## Pre-flight
15
-
16
- Read these, or STOP and surface the gap — never guess a path:
17
-
18
- - `<project-root>/.codearbiter/decisions/` — the ADR directory and existing records. Create it on first `/adr` if absent.
19
- - For `/adr`: confirm the user explicitly authorized this decision and supplied (or confirmed) its content. An ADR is never authored as the disposition of a routine finding.
20
-
21
- ## Phase 1 — Index · gate: BLOCK
22
-
23
- Scan `<project-root>/.codearbiter/decisions/` for existing `NNNN-*.md` ADR files. Record each by **filename stem** (`0014-githook-shim-dropin-fail-closed`), title, and status. Determine the next sequential number (no gaps) for `/adr`; for `/adr-status` this is the working set.
24
-
25
- **The stem is the identifier; the number is only a sort key.** Two ADRs may already share a number — this repository holds two numbered 0014 — so a bare number can name more than one document. Index by stem, and never assume `NNNN` resolves to one file until you have checked.
26
-
27
- Gate: the existing ADRs are indexed by stem and, for `/adr`, the next number is fixed and **unused** — a number already taken by an existing stem is not available, even for an unrelated decision.
28
-
29
- ## Phase 2 — Author (/adr) · gate: STOP
30
-
31
- Confirm the decision content with the user — context, the decision itself, alternatives, consequences. MUST NOT fill these from inference. Surface any unknown as an inline `[CONFIRM-NN]` placeholder; do not resolve it by guessing.
32
-
33
- **Drop the authoring marker first.** The `pre-write`/`pre-edit` hooks block any write to `.codearbiter/decisions/NNNN-*.md` unless a fresh authoring marker is present — that block is the mechanism enforcing "ADRs only via `/adr`" (arbiter.md §3), so the sanctioned path must arm it itself. Immediately before writing, create the marker at the path the hooks check (project root = git top level):
34
-
35
- ```bash
36
- mkdir -p "$(git rev-parse --show-toplevel)/.codearbiter/.markers"
37
- touch "$(git rev-parse --show-toplevel)/.codearbiter/.markers/adr-authoring-active"
38
- ```
39
-
40
- The marker is honored for 30 minutes. Then write `<project-root>/.codearbiter/decisions/NNNN-<slug>.md` using the canonical ADR template — `<plugin-root>/routines/decision-lifecycle/references/adr-template.md` (the single source of truth for the ADR shape, shared with `decompose`). Author it with `status: proposed`. If this decision supersedes an existing one, set `supersedes:` to that ADR's **full filename stem** — `supersedes: 0014-githook-shim-dropin-fail-closed`, never `supersedes: 0014` — and leave the prior ADR's file untouched (forward-only chain — do not edit it to add a back-reference).
41
-
42
- If the new ADR supersedes only *part* of the prior decision, say which part in the body. `supersedes:` names a document, not a clause, so a chain may legitimately fork — two ADRs can each supersede different clauses of one predecessor. That fork is correct and must not be "repaired"; only the prose can carry the scope.
43
-
44
- After writing the ADR, append a corresponding entry to the decision log per the format in `<plugin-root>/includes/smarts/decision-log-format.md` — `Decided by:` names the user. Status transitions (`proposed → accepted → superseded | rejected`) require explicit user instruction; never advance status on this skill's own judgment.
45
-
46
- **`governs:` makes the decision live.** When an ADR names path globs in `governs:`, the post-write
47
- hook surfaces a one-line notice on any Write/Edit touching a matching file — "this file is governed
48
- by ADR-NNNN" — so a recorded decision pushes back at edit time instead of waiting for a checkpoint
49
- sweep. Offer the field whenever a decision constrains identifiable files; omit it for decisions
50
- without a file footprint. Globs are fnmatch-style against repo-relative forward-slash paths.
51
-
52
- Once the ADR file and its log entry are written (and any user-instructed status edit is applied), remove the marker — it exists only for one authoring pass:
53
-
54
- ```bash
55
- rm -f "$(git rev-parse --show-toplevel)/.codearbiter/.markers/adr-authoring-active"
56
- ```
57
-
58
- Gate: the ADR file is written with a real `decided-by` user attribution, numbered without a gap, and its log entry is appended. An ADR with no user attribution, or authored as the disposition of a finding, does not pass — STOP.
59
-
60
- ### Accepted/Planned binding
61
-
62
- `accepted` means **Accepted/Planned**. It records the user's governance decision; it does not claim
63
- that any obligation is Implemented or Verified. When the user explicitly authorizes acceptance:
64
-
65
- 1. Change only the ADR's status fields to accepted. Derive stable, stem-scoped obligations from every
66
- normative clause in its immutable record, bind each obligation to exact ADR
67
- text, and obtain independent review that the sealed obligation set is complete.
68
- 2. Route through `commit-gate` to commit the accepted ADR and decision-log append. Do not add the
69
- acceptance binding to that commit: its `source_commit` cannot truthfully name a commit that does
70
- not exist yet.
71
- 3. From that exact commit, hash the committed Git blob bytes and the separately canonicalized
72
- immutable record: strict UTF-8 with LF-normalized line endings, containing the complete ADR while
73
- replacing only the recognized status value in the strictly parsed frontmatter `status:` field and
74
- `## Status` section with fixed sentinels. The two values must agree. All remaining Status prose,
75
- including approval attribution, stays bound alongside title, date, `decided-by`, supersession,
76
- governed paths, H1, and every other section. Malformed or duplicate frontmatter, status, or
77
- headings fail closed. Append one
78
- `acceptance` event to
79
- `<project-root>/.codearbiter/decisions/adr-lifecycle.jsonl`, then persist that acceptance binding
80
- in a subsequent commit. The event uses schema `adr-lifecycle/v1` and records `adr` (full stem),
81
- `recorded_at`, `source_commit`, `blob_sha256`, `body_sha256`, `obligations`,
82
- `obligations_sha256`, and `obligations_sealed: true`. A second acceptance or baseline binding for
83
- the same stem is invalid.
84
- 4. Preserve **ADR source ancestry** through delivery. Before opening the PR and again before
85
- its merge offer, follow the finishing skill's `--merge-method` preflight on the exact base/head.
86
- A source not already in base ancestry requires a true merge commit with `--match-head-commit`;
87
- squash or rebase would orphan its identity. Missing source ancestry blocks delivery. Never
88
- rewrite the acceptance binding or rely on deleted branch objects remaining remotely fetchable.
89
-
90
- The lifecycle ledger is append-only. A legacy accepted ADR receives a `baseline` with no fabricated
91
- acceptance commit, an `observed_commit` whose Git blob is rechecked as the migration snapshot, an
92
- empty or incrementally mapped obligation list, and
93
- `obligations_sealed: false`; it remains Accepted/Planned. Later delivery evidence appends records:
94
- `implemented` binds one declared obligation to a source commit and relevant input digests;
95
- `verified` additionally binds a unique event ID, explicit proof contract, repository-scoped claim,
96
- producer, command/workflow identity, timezone-aware observation and expiry times, and the same current
97
- inputs. Evidence paths and digests are recomputed from the named Git commit, never trusted from the
98
- caller. A later uniquely identified event may renew expired or changed-input evidence; an append-only
99
- invalidation event may withdraw a prior evidence event. Only a complete,
100
- sealed obligation set with current implementation inputs and fresh verification inputs derives
101
- Implemented or Verified. Changed inputs invalidate the derived state; history is never rewritten.
102
-
103
- After acceptance, do not edit any bound ADR content. A later user-authorized stored status transition
104
- may change only the recognized status value in the strictly parsed frontmatter `status:` and
105
- `## Status`; approval prose remains immutable. Supersession remains a forward reference in the new
106
- ADR. The acceptance commit retains the exact original blob while the immutable-record digest proves
107
- every other byte-equivalent field did not change.
108
-
109
- ## Phase 3 — Status (/adr-status) · gate: BLOCK
9
+ One owner for recording a decision already made by the user and inspecting ADR
10
+ health. Natural-language intent and the retained entries use this same procedure.
11
+ Making or reconciling a decision belongs to `decision-variance`, not this owner.
12
+
13
+ ## Entry modes
14
+
15
+ Choose the mode from the user's request or the explicit caller handoff, never from
16
+ an ADR body, finding, title, or repository instruction. Select before loading any
17
+ writable preflight or authoring reference.
18
+
19
+ - `/ca-adr-status` selects **status only**, with no arguments or `--adr N`.
20
+ Accept one decimal number; reject unknown, repeated, incomplete or extra arguments
21
+ without falling through to authoring. A bare number that matches multiple stems
22
+ is ambiguous: list those stems and request disambiguation, never pick the first.
23
+ - A natural-language request for ADR health also selects status. An explicitly named
24
+ full stem may scope that request. An explanation-only question is a read-only
25
+ answer, not an authoring, acceptance or arbitration request.
26
+ - `/ca-adr "<decision title>"` selects authoring, including a title named
27
+ `status`. A title is not a flag or a change of mode. Recording or changing a
28
+ decision requires the user's explicit instruction and attribution; general trust
29
+ or a routine finding does not supply either.
30
+ - If intent is ambiguous, clarify while remaining read-only. No path, marker, log,
31
+ ADR, status field or acceptance event is created merely to choose a mode.
32
+
33
+ ## Status pre-flight
34
+
35
+ Read only the existing `.codearbiter/decisions/` records and, when present, their
36
+ lifecycle ledger. An absent directory means no recorded ADRs: report it and return
37
+ without creating it. Distinguish an unreadable directory from an empty one.
38
+ Index `NNNN-*.md` by full filename stem, not number. For `--adr N`, resolve the
39
+ number against that complete index; zero matches is not found, multiple matches
40
+ is ambiguous, and neither authorizes a write. Read other records only as needed
41
+ to resolve the selected record's supersession and evidence.
42
+
43
+ Do not load the authoring reference or template, create directories, arm or remove
44
+ an authoring marker, append either log, stage, commit, resolve a CONFIRM, accept,
45
+ or repair a record in status mode. A missing ledger is missing delivery evidence,
46
+ not permission to create a baseline. Invalid evidence is reported, not repaired.
47
+ Report recorded age and challenge evidence; flag aged/unchallenged decisions using
48
+ available project criteria and dates, not an invented age cutoff or inferred review.
49
+ A missing challenge record is unknown, not proof that no challenge ever happened.
50
+ Optional `decision-challenger` dispatch inherits read-only scope and returns findings;
51
+ missing prerequisites for that optional dispatch never authorize initialization.
52
+
53
+ ## Status mode — read-only report
110
54
 
111
55
  Read-only. For each ADR (or the `--adr N` target), report: stem, title, stored governance status,
112
56
  derived delivery state, date, and supersession state. Read `adr-lifecycle.jsonl` when present. Display
113
- stored `accepted` as **Accepted/Planned**. Display Implemented or Verified only when every obligation
57
+ stored `accepted` as **Accepted/Planned**. Draft or proposed records without an
58
+ acceptance binding remain unaccepted; report no accepted binding, never promote them. Display Implemented or Verified only when every obligation
114
59
  in a sealed binding has the required current, input-bound evidence; otherwise name the narrow reason
115
60
  (unsealed, incomplete, stale, expired, or mismatched) and do not promote the ADR. Repository evidence
116
61
  never implies live-host, publication, support, legal, or other external truth. Find supersession by
@@ -122,7 +67,9 @@ Resolve a `supersedes:` value like this, and never guess:
122
67
  - The value is a **bare number** → collect every stem with that number. Exactly one → it names that ADR. More than one → **ambiguous: report it as an error and resolve nothing.** Zero → a dangling reference; report that too.
123
68
  - `none` (or empty) → no predecessor.
124
69
 
125
- `.github/scripts/check_adr_identity.py` enforces this same rule mechanically in CI; if it disagrees with this report, the report is wrong.
70
+ The CI-only checker `.github/scripts/check_adr_identity.py` enforces this rule
71
+ in the codeArbiter source repository. It is not shipped to consumer repositories;
72
+ do not invent or require an installed copy. Follow the same full-stem rule there.
126
73
 
127
74
  If a supersession candidate contradicts an `accepted` ADR with no clear direction, do not pick one — flag it for `/conflict`.
128
75
 
@@ -130,7 +77,7 @@ If a supersession candidate contradicts an `accepted` ADR with no clear directio
130
77
  ## ADR Status — YYYY-MM-DD
131
78
 
132
79
  ### Active
133
- - ADR-NNNN-<slug> — <title> — governance: <status>; delivery: <Accepted/Planned | Implemented | Verified> (<date>)
80
+ - ADR-NNNN-<slug> — <title> — governance: <status>; delivery: <no accepted binding | Accepted/Planned | Implemented | Verified> (<date>)
134
81
 
135
82
  ### Superseded
136
83
  - ADR-NNNN-<slug> — <title> — superseded by ADR-MMMM-<slug>
@@ -144,18 +91,25 @@ If a supersession candidate contradicts an `accepted` ADR with no clear directio
144
91
 
145
92
  Every ADR is named by its stem, so a shared number never collapses two rows into one. An empty section is marked "None" — not omitted. MAY dispatch `decision-challenger` (`<plugin-root>/agents/decision-challenger.md`) to stress-test an ADR; optional, never forced.
146
93
 
147
- Gate: every indexed ADR appears with its current status and supersession state; no `[CONFIRM-NN]` resolved; no file modified.
94
+ Gate: every selected ADR appears with its current status and supersession state; no `[CONFIRM-NN]` resolved; no file modified.
95
+
96
+ ## Authoring mode — on-demand procedure
97
+
98
+ Only after selecting explicitly authorized authoring or a stored status transition,
99
+ load `<plugin-root>/routines/decision-lifecycle/references/authoring.md` and follow
100
+ that procedure. It owns indexing for numbering, confirmed content, marker lifetime,
101
+ the shared ADR template, append-only logs and exact acceptance/delivery binding.
102
+ Do not return through a command wrapper or load it again. A status report returns
103
+ to its caller and never continues into this authoring path.
148
104
 
149
105
  ## Hard rules
150
106
 
151
- - MUST author an ADR only via `/adr` with explicit user attribution. MUST NOT author an ADR as the disposition of a routine finding — an out-of-scope finding gets an inline `[NEEDS-TRIAGE]` marker instead.
152
- - MUST NOT record a decision the user did not explicitly make. "Use your best judgment," "I trust you" are declined.
153
- - MUST NOT resolve a `[CONFIRM-NN]` placeholder by guessing. Surface it and stop.
154
- - MUST NOT advance an ADR's status without explicit user instruction.
155
- - MUST NOT report accepted as Implemented or Verified without complete, sealed, current lifecycle evidence.
156
- - MUST NOT rewrite or truncate a committed `adr-lifecycle.jsonl`, create a second binding, or fabricate legacy acceptance evidence.
157
- - MUST NOT edit a prior ADR or a prior decision-log entry to add a back-reference — supersession is a forward-only chain; append a new record whose `supersedes:` names the prior one.
158
- - **The never-edit rule protects decision CONTENT, not identifiers.** Rewriting what was decided corrupts the record; disambiguating *which document a pointer names* repairs it. Maintainer ruling, 2026-07-25: *"the never edit rule is meant to prevent this situation, not prevent this situation from being fixed."* So a correction that is provably identifier-only — a `supersedes:` value changed from a number to the stem it already meant — is permissible, and nothing else about the file is. Any such correction MUST be a single-line diff that alters not one word of any decision, MUST be visible in its own commit, and still requires the maintainer-armed `adr-authoring-active` marker. MUST NOT touch Context, Decision, Alternatives, Consequences, Risks, `status:`, `date:`, `decided-by:`, or `title:` under this allowance.
159
- - MUST NOT number an ADR with a gap, and MUST NOT reuse a number an existing stem already holds — a shared number makes every bare reference to it ambiguous.
160
- - MUST NOT modify any file under `/adr-status` — it is read-only.
161
- - MUST NOT force the `decision-challenger` agent — its dispatch is MAY only.
107
+ - Read-only status never modifies a file, index, marker or ledger, even to repair
108
+ evidence or resolve a `[CONFIRM-NN]`. Surface unresolved questions and stop.
109
+ - Every authored decision is explicitly user-attributed, never an inferred
110
+ disposition of a routine finding. Explicit status changes are separate authority.
111
+ - Stored `accepted` means **Accepted/Planned**, not Implemented or Verified.
112
+ Delivery claims need complete, sealed, current input-bound lifecycle evidence.
113
+ - Preserve full-stem identity and forward-only supersession. Report ambiguous or
114
+ dangling references; never collapse records sharing a number or repair a fork.
115
+ - Optional challenge is MAY, not another mandatory approval or authoring step.
@@ -0,0 +1,152 @@
1
+ # ADR authoring and acceptance
2
+
3
+ Load only after `decision-lifecycle` selects an explicitly authorized authoring or
4
+ status-transition action. Do not load this procedure for read-only ADR health.
5
+ Read `<plugin-root>/includes/smarts/decision-log-format.md` before any log append.
6
+ A confirmed decision need not be confirmed again unchanged; missing content and
7
+ new status transitions still require their existing explicit user authorization.
8
+
9
+ ## Existing-record transitions
10
+
11
+ For a user-requested stored status change, resolve the exact existing stem first.
12
+ Do not create a missing directory, allocate a new number, or author a replacement
13
+ Proposed record for that request. Apply only the explicitly authorized transition
14
+ under the marker and immutable-record rules below. Acceptance uses the exact
15
+ Accepted/Planned binding sequence; a stored status update alone is not evidence.
16
+ A health scan never enters this procedure. New-record authoring follows the phases below.
17
+
18
+ ## Pre-flight
19
+
20
+ Read existing storage before changing it; never guess a path:
21
+
22
+ - `<project-root>/.codearbiter/decisions/` — if present, read the directory and
23
+ its existing records. Unreadable existing storage is a STOP, not an empty index.
24
+ Only an explicitly authorized new-record request may create an absent directory.
25
+ Read-only status and changes to an existing record never create a missing directory.
26
+ - For `/adr`: confirm the user explicitly authorized this decision and supplied (or confirmed) its content. An ADR is never authored as the disposition of a routine finding.
27
+
28
+ ## Phase 1 — Index · gate: BLOCK
29
+
30
+ Scan `<project-root>/.codearbiter/decisions/` for existing `NNNN-*.md` ADR files. Record each by **filename stem** (`0014-githook-shim-dropin-fail-closed`), title, and status. Determine the next sequential number (no gaps) for `/adr`; for `/adr-status` this is the working set.
31
+
32
+ **The stem is the identifier; the number is only a sort key.** Two ADRs may already share a number — this repository holds two numbered 0014 — so a bare number can name more than one document. Index by stem, and never assume `NNNN` resolves to one file until you have checked.
33
+
34
+ Gate: the existing ADRs are indexed by stem and, for `/adr`, the next number is fixed and **unused** — a number already taken by an existing stem is not available, even for an unrelated decision.
35
+
36
+ ## Phase 2 — Author (/adr) · gate: STOP
37
+
38
+ Confirm the decision content with the user — context, the decision itself, alternatives, consequences. MUST NOT fill these from inference. Surface any unknown as an inline `[CONFIRM-NN]` placeholder; do not resolve it by guessing.
39
+
40
+ **Drop the authoring marker first.** The `pre-write`/`pre-edit` hooks block any write to `.codearbiter/decisions/NNNN-*.md` unless a fresh authoring marker is present — that block requires the authorized authoring workflow to arm its own marker. Direct owner routing executes the same `/adr` procedure, not a second authorization path. Immediately before writing, resolve the **same project root as the ADR guards**
41
+ using the installed `_hooklib.project_root()` in the current host/session context.
42
+ Those guards use `project_root()`, not the general security/migration `marker_root()`;
43
+ do not unconditionally climb to the main worktree or use a fresh Git toplevel guess.
44
+ Claude's project-directory signal can legitimately name the main checkout while
45
+ execution is in a linked checkout; Codex and Pi use their own host resolution.
46
+
47
+ Use the host's already resolved native Python 3 executable as `PY` in this Bash
48
+ form (equivalent native-shell filesystem operations are allowed). Pass the trusted
49
+ installed hooks directory, not a project module with the same name. Preserve the
50
+ resolved `ADR_MARKER_ROOT` and exact marker path in workflow context for cleanup,
51
+ including across separate shell calls. A resolver failure or empty result stops
52
+ before any marker write:
53
+
54
+ ```bash
55
+ ADR_MARKER_ROOT="$("$PY" -c 'import sys; from pathlib import Path; sys.path.insert(0, sys.argv[1]); from _hooklib import project_root; print(Path(project_root()).as_posix())' "<plugin-root>/hooks")" || exit 1
56
+ [ -n "$ADR_MARKER_ROOT" ] || exit 1
57
+ mkdir -p "$ADR_MARKER_ROOT/.codearbiter/.markers"
58
+ touch "$ADR_MARKER_ROOT/.codearbiter/.markers/adr-authoring-active"
59
+ ```
60
+
61
+ The marker is honored for 30 minutes. Then write `<project-root>/.codearbiter/decisions/NNNN-<slug>.md` using the canonical ADR template — `<plugin-root>/routines/decision-lifecycle/references/adr-template.md` (the single source of truth for the ADR shape, shared with `decompose`). Author it with `status: proposed`. If this decision supersedes an existing one, set `supersedes:` to that ADR's **full filename stem** — `supersedes: 0014-githook-shim-dropin-fail-closed`, never `supersedes: 0014` — and leave the prior ADR's file untouched (forward-only chain — do not edit it to add a back-reference).
62
+
63
+ If the new ADR supersedes only *part* of the prior decision, say which part in the body. `supersedes:` names a document, not a clause, so a chain may legitimately fork — two ADRs can each supersede different clauses of one predecessor. That fork is correct and must not be "repaired"; only the prose can carry the scope.
64
+
65
+ After writing the ADR, append a corresponding entry to the decision log per the format in `<plugin-root>/includes/smarts/decision-log-format.md` — `Decided by:` names the user. Status transitions (`proposed → accepted → superseded | rejected`) require explicit user instruction; never advance status on this skill's own judgment.
66
+
67
+ **`governs:` makes the decision live.** When an ADR names path globs in `governs:`, the post-write
68
+ hook surfaces a one-line notice on any Write/Edit touching a matching file — "this file is governed
69
+ by ADR-NNNN" — so a recorded decision pushes back at edit time instead of waiting for a checkpoint
70
+ sweep. Offer the field whenever a decision constrains identifiable files; omit it for decisions
71
+ without a file footprint. Globs are fnmatch-style against repo-relative forward-slash paths.
72
+
73
+ On every exit after arming it, remove the marker, including ADR-write,
74
+ decision-log-append and status-edit failures, cancellation, or a controlled pause.
75
+ Run cleanup before returning or stopping after marker creation. On success, remove
76
+ it after the ADR file, log entry and any authorized status edit are written. Use
77
+ the exact previously resolved path, even if cwd changed or shell calls are separate.
78
+ Do not resolve a different root during cleanup; it exists only for one authoring pass.
79
+ Do not install an exit trap on the marker-creation shell alone: that would remove
80
+ authority before subsequent host Write/Edit calls. On a cleanup failure, report
81
+ the exact remaining marker path and original failure; do not claim the pass closed
82
+ or continue ADR writes. This cooperative procedure is not crash-safe cleanup after
83
+ a forcibly terminated process; the existing freshness limit is not immediate cleanup.
84
+
85
+ ```bash
86
+ rm -f "$ADR_MARKER_ROOT/.codearbiter/.markers/adr-authoring-active"
87
+ ```
88
+
89
+ Gate: the ADR file is written with a real `decided-by` user attribution, numbered without a gap, and its log entry is appended. An ADR with no user attribution, or authored as the disposition of a finding, does not pass — STOP.
90
+
91
+ ### Accepted/Planned binding
92
+
93
+ `accepted` means **Accepted/Planned**. It records the user's governance decision; it does not claim
94
+ that any obligation is Implemented or Verified. When the user explicitly authorizes acceptance:
95
+
96
+ 1. Change only the ADR's status fields to accepted. Derive stable, stem-scoped obligations from every
97
+ normative clause in its immutable record, bind each obligation to exact ADR
98
+ text, and obtain independent review that the sealed obligation set is complete.
99
+ 2. Route through `commit-gate` to commit the accepted ADR and decision-log append. Do not add the
100
+ acceptance binding to that commit: its `source_commit` cannot truthfully name a commit that does
101
+ not exist yet.
102
+ 3. From that exact commit, hash the committed Git blob bytes and the separately canonicalized
103
+ immutable record: strict UTF-8 with LF-normalized line endings, containing the complete ADR while
104
+ replacing only the recognized status value in the strictly parsed frontmatter `status:` field and
105
+ `## Status` section with fixed sentinels. The two values must agree. All remaining Status prose,
106
+ including approval attribution, stays bound alongside title, date, `decided-by`, supersession,
107
+ governed paths, H1, and every other section. Malformed or duplicate frontmatter, status, or
108
+ headings fail closed. Append one
109
+ `acceptance` event to
110
+ `<project-root>/.codearbiter/decisions/adr-lifecycle.jsonl`, then persist that acceptance binding
111
+ in a subsequent commit. The event uses schema `adr-lifecycle/v1` and records `adr` (full stem),
112
+ `recorded_at`, `source_commit`, `blob_sha256`, `body_sha256`, `obligations`,
113
+ `obligations_sha256`, and `obligations_sealed: true`. A second acceptance or baseline binding for
114
+ the same stem is invalid.
115
+ 4. Preserve **ADR source ancestry** through delivery. Before opening the PR and again before
116
+ its merge offer, follow the finishing skill's `--merge-method` preflight on the exact base/head.
117
+ A source not already in base ancestry requires a true merge commit with `--match-head-commit`;
118
+ squash or rebase would orphan its identity. Missing source ancestry blocks delivery. Never
119
+ rewrite the acceptance binding or rely on deleted branch objects remaining remotely fetchable.
120
+
121
+ The lifecycle ledger is append-only. A legacy accepted ADR receives a `baseline` with no fabricated
122
+ acceptance commit, an `observed_commit` whose Git blob is rechecked as the migration snapshot, an
123
+ empty or incrementally mapped obligation list, and
124
+ `obligations_sealed: false`; it remains Accepted/Planned. Later delivery evidence appends records:
125
+ `implemented` binds one declared obligation to a source commit and relevant input digests;
126
+ `verified` additionally binds a unique event ID, explicit proof contract, repository-scoped claim,
127
+ producer, command/workflow identity, timezone-aware observation and expiry times, and the same current
128
+ inputs. Evidence paths and digests are recomputed from the named Git commit, never trusted from the
129
+ caller. A later uniquely identified event may renew expired or changed-input evidence; an append-only
130
+ invalidation event may withdraw a prior evidence event. Only a complete,
131
+ sealed obligation set with current implementation inputs and fresh verification inputs derives
132
+ Implemented or Verified. Changed inputs invalidate the derived state; history is never rewritten.
133
+
134
+ After acceptance, do not edit any bound ADR content. A later user-authorized stored status transition
135
+ may change only the recognized status value in the strictly parsed frontmatter `status:` and
136
+ `## Status`; approval prose remains immutable. Supersession remains a forward reference in the new
137
+ ADR. The acceptance commit retains the exact original blob while the immutable-record digest proves
138
+ every other byte-equivalent field did not change.
139
+
140
+ ## Hard rules
141
+
142
+ - MUST author an ADR only through this owner's authorized authoring mode with explicit user attribution. MUST NOT author an ADR as the disposition of a routine finding — an out-of-scope finding gets an inline `[NEEDS-TRIAGE]` marker instead.
143
+ - MUST NOT record a decision the user did not explicitly make. "Use your best judgment," "I trust you" are declined.
144
+ - MUST NOT resolve a `[CONFIRM-NN]` placeholder by guessing. Surface it and stop.
145
+ - MUST NOT advance an ADR's status without explicit user instruction.
146
+ - MUST NOT report accepted as Implemented or Verified without complete, sealed, current lifecycle evidence.
147
+ - MUST NOT rewrite or truncate a committed `adr-lifecycle.jsonl`, create a second binding, or fabricate legacy acceptance evidence.
148
+ - MUST NOT edit a prior ADR or a prior decision-log entry to add a back-reference — supersession is a forward-only chain; append a new record whose `supersedes:` names the prior one.
149
+ - **The never-edit rule protects decision CONTENT, not identifiers.** Rewriting what was decided corrupts the record; disambiguating *which document a pointer names* repairs it. Maintainer ruling, 2026-07-25: *"the never edit rule is meant to prevent this situation, not prevent this situation from being fixed."* So a correction that is provably identifier-only — a `supersedes:` value changed from a number to the stem it already meant — is permissible, and nothing else about the file is. Any such correction MUST be a single-line diff that alters not one word of any decision, MUST be visible in its own commit, and still requires the maintainer-armed `adr-authoring-active` marker. MUST NOT touch Context, Decision, Alternatives, Consequences, Risks, `status:`, `date:`, `decided-by:`, or `title:` under this allowance.
150
+ - MUST NOT number an ADR with a gap, and MUST NOT reuse a number an existing stem already holds — a shared number makes every bare reference to it ambiguous.
151
+ - MUST NOT modify any file under `/adr-status` — it is read-only.
152
+ - MUST NOT force the `decision-challenger` agent — its dispatch is MAY only.