@windyroad/architect 0.18.6 → 0.19.0-preview.927

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.
@@ -123,5 +123,5 @@
123
123
  }
124
124
  },
125
125
  "name": "wr-architect",
126
- "version": "0.18.6"
126
+ "version": "0.19.0"
127
127
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wr-architect",
3
- "version": "0.18.6",
3
+ "version": "0.19.0",
4
4
  "description": "Architecture decision enforcement for AI coding agents",
5
5
  "author": {
6
6
  "name": "Windy Road Technology",
package/hooks/hooks.json CHANGED
@@ -8,6 +8,10 @@
8
8
  { "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/staleness-check.sh" }] }
9
9
  ],
10
10
  "PreToolUse": [
11
+ {
12
+ "matcher": "Bash|Write|Edit|Read|Glob|Grep|Task|WebFetch|WebSearch",
13
+ "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/quota-pace-throttle.sh" }]
14
+ },
11
15
  { "matcher": "Edit|Write", "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/architect-enforce-edit.sh" }] },
12
16
  { "matcher": "Edit|Write", "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/architect-oversight-marker-discipline.sh" }] },
13
17
  { "matcher": "ExitPlanMode", "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/architect-plan-enforce.sh" }] },
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env bash
2
+ # quota-pace-throttle.sh — PreToolUse hook (P160 / ADR-093 / RFC-046).
3
+ #
4
+ # Fires before every tool call across ALL work (interactive + AFK). Mechanically
5
+ # paces token burn so it never sprints into a mid-flight quota hard-stop: it
6
+ # compares cumulative window usage% against elapsed% and, when AHEAD of pace,
7
+ # sleeps the calculated catch-up time (capped per firing). When behind/on pace
8
+ # it is a fast no-op. It NEVER blocks, NEVER asks, and fails OPEN on every
9
+ # abnormal path — a broken throttle must not break the session.
10
+ #
11
+ # Data source: ~/.claude/quota-state.json, written by the statusline (the only
12
+ # surface Claude Code passes `.rate_limits` to). Fields:
13
+ # { "five_used_pct": N, "five_resets_at": <unix>,
14
+ # "week_used_pct": N, "week_resets_at": <unix> }
15
+ # If the cache is missing/stale/malformed, the hook no-ops (fail-open) — the
16
+ # statusline-writer install is a separate, user-consented step.
17
+ #
18
+ # ponytail: pure arithmetic + one sleep; the 60s/firing cap + fail-open keep the
19
+ # blast radius to "at worst a slightly-slower tool call", never a stall or block.
20
+
21
+ set +e
22
+ CACHE="${WR_QUOTA_CACHE:-${HOME}/.claude/quota-state.json}"
23
+ MARKER="${WR_QUOTA_MARKER:-${TMPDIR:-/tmp}/wr-quota-throttle-last}"
24
+ FIVE_WINDOW=18000 # 5h in seconds
25
+ WEEK_WINDOW=604800 # 7d in seconds
26
+ WEEK_HEADROOM_PP=5 # leave 5pp weekly headroom for non-Claude-Code surfaces
27
+ CAP_SECONDS=60 # max sleep per firing
28
+
29
+ emit_ok() { exit 0; } # PreToolUse: silent allow, never a permissionDecision deny
30
+
31
+ # Fail-open preconditions.
32
+ command -v jq >/dev/null 2>&1 || emit_ok
33
+ [ -r "$CACHE" ] || emit_ok
34
+
35
+ now=$(date +%s 2>/dev/null) || emit_ok
36
+ case "$now" in ''|*[!0-9]*) emit_ok;; esac
37
+
38
+ # Recent-check no-op: if we checked <5s ago, skip recompute (keeps per-call
39
+ # latency negligible when we're firing on every tool call).
40
+ if [ -f "$MARKER" ]; then
41
+ last=$(cat "$MARKER" 2>/dev/null)
42
+ case "$last" in
43
+ ''|*[!0-9]*) : ;;
44
+ *) [ $(( now - last )) -lt 5 ] && emit_ok ;;
45
+ esac
46
+ fi
47
+ printf '%s' "$now" > "$MARKER" 2>/dev/null
48
+
49
+ # Read the cache; fail-open on any parse miss.
50
+ read -r five_used five_reset week_used week_reset < <(
51
+ jq -r '[.five_used_pct, .five_resets_at, .week_used_pct, .week_resets_at]
52
+ | map(tostring) | join(" ")' "$CACHE" 2>/dev/null
53
+ ) || emit_ok
54
+ for v in "$five_used" "$five_reset" "$week_used" "$week_reset"; do
55
+ case "$v" in ''|null|*[!0-9.]*) emit_ok;; esac
56
+ done
57
+
58
+ # elapsed% of a window = (window - remaining) / window * 100, clamped [0,100].
59
+ elapsed_pct() { # resets_at window_secs
60
+ local remaining=$(( $1 - now )) win="$2" e
61
+ [ "$remaining" -lt 0 ] && remaining=0
62
+ [ "$remaining" -gt "$win" ] && remaining="$win"
63
+ e=$(( (win - remaining) * 100 / win ))
64
+ printf '%s' "$e"
65
+ }
66
+
67
+ # integer-truncate the used% (cache may carry a decimal)
68
+ five_used_i=${five_used%%.*}; week_used_i=${week_used%%.*}
69
+ five_elapsed=$(elapsed_pct "$five_reset" "$FIVE_WINDOW")
70
+ week_elapsed=$(elapsed_pct "$week_reset" "$WEEK_WINDOW")
71
+
72
+ # pace gap per window (positive = ahead of pace = burning too fast).
73
+ # weekly target leaves headroom, so effective gap = used - (elapsed - headroom).
74
+ gap5=$(( five_used_i - five_elapsed ))
75
+ gap7=$(( week_used_i - (week_elapsed - WEEK_HEADROOM_PP) ))
76
+
77
+ # Take the tighter (larger-gap) window and its window length.
78
+ if [ "$gap5" -ge "$gap7" ]; then gap="$gap5"; win="$FIVE_WINDOW"; else gap="$gap7"; win="$WEEK_WINDOW"; fi
79
+ [ "$gap" -le 0 ] && emit_ok # behind/on pace → fast no-op
80
+
81
+ # Catch-up sleep: elapsed% rises at 100/win per second, so closing `gap` pp of
82
+ # lead needs gap/100 * win seconds. Cap per firing so no single call stalls long.
83
+ sleep_secs=$(( gap * win / 100 ))
84
+ [ "$sleep_secs" -gt "$CAP_SECONDS" ] && sleep_secs="$CAP_SECONDS"
85
+ [ "$sleep_secs" -le 0 ] && emit_ok
86
+
87
+ sleep "$sleep_secs" 2>/dev/null
88
+ emit_ok
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/architect",
3
- "version": "0.18.6",
3
+ "version": "0.19.0-preview.927",
4
4
  "description": "Architecture decision enforcement for AI coding agents",
5
5
  "bin": {
6
6
  "windyroad-architect": "./bin/install.mjs"
@@ -14,72 +14,55 @@ It is wrong for the **aside-invocation** use case. P156 surfaced three repeating
14
14
  2. **Architect-review verdict capture**: a `wr-architect:agent` review yields a substantive verdict (PASS-WITH-NOTES / ISSUES-FOUND) whose rationale deserves an ADR-shaped record. Today the verdict + rationale lands in commit messages and rots — future readers grep history but lose the structured trace.
15
15
  3. **User-driven design conversations**: user resolves options (a)/(b)/(c) during conversational work; the settlement currently lives in a problem-ticket RCA section instead of a discoverable ADR.
16
16
 
17
- `/wr-architect:capture-adr` is the source-side fix: a lightweight skill with a deferred-placeholder pattern that captures the decision in ~3-4 turns and routes the deferred canonical expansion through `/wr-architect:create-adr` at a time of the user's choosing.
17
+ `/wr-architect:capture-adr` is the source-side fix: a lightweight skill that captures the decision in ~5-6 turns with full derived substance. "Lightweight" means zero-interaction + single-commit not skimpy content.
18
18
 
19
- ## Contract trade-offs
20
-
21
- ### Skeleton-MADR validity at status `proposed`
22
-
23
- Architect Q1 verdict (P156 review): the architect-agent's review prompt tolerates skeleton ADRs at `status: proposed`. It checks "does the proposed change conflict with the decision's outcome?" not "does every section have prose?" The deferred-flag pattern is the load-bearing signal that downstream tooling and any future canonical-expansion auto-detect path keys off (mirrors capture-problem's `(deferred — re-rate at next /wr-itil:review-problems)` literal).
19
+ ## Derived-substance amendment (RFC-045 / P375, 2026-07-06)
24
20
 
25
- Status `proposed` (not `accepted`) is the right cover for skeleton state. The architect-agent enforces the MADR ≥2-options requirement at **acceptance review**, not at `proposed.md` skeleton time. Each deferred section carries the literal pointer string `(deferred to /wr-architect:create-adr canonical review)` so canonical-expansion tooling can detect and expand mechanically.
21
+ The skill originally shipped (P156, 2026-05-03) with a **deferred-placeholder pattern**: every section the capture didn't fill carried the literal pointer string `(deferred to /wr-architect:create-adr canonical review)`, on the theory that a later canonical-expansion pass would fill them. That pattern failed the P375 rot test — a named re-entry point is not a self-firing cadence; nothing ever triggered the canonical review, the anticipated auto-detect-and-expand tooling was never built, and the sections rotted. User direction 2026-07-05: "It should capture it properly."
26
22
 
27
- ### Considered Options skeleton`1. Option A (chosen)` + `2. (deferred see ...)`
23
+ The amended contract (ADR-032 derived-substance amendment; same correction class as ADR-067's silent derivation of capture-problem ratings): **every MADR section is derived for real at capture time** genuine Decision Drivers, ≥2 real Considered Options (chosen + actually-rejected alternatives), real Good/Neutral/Bad Consequences, testable Confirmation criteria, real Reassessment Criteria, derived decision-makers. No placeholder, pointer, or sentinel strings of any kind. The capturing agent has more decision context in-session than any later pass would; capture is the cheapest moment to write the substance down.
28
24
 
29
- Architect Q2 verdict: write a literal numbered placeholder so the file parses cleanly under any doc-lint asserting ≥2 numbered options. The placeholder pattern:
25
+ The derived substance is provisional. `human-oversight: unconfirmed` states that honestly, and the SessionStart oversight nudge `/wr-architect:review-decisions` drain is the **self-firing** surface where a human ratifies or amends it (ADR-066). That is the only deferral the skill retains.
30
26
 
31
- ```markdown
32
- 1. **Option A (chosen)** — <one-line summary>
33
- 2. (deferred — see /wr-architect:create-adr canonical review)
34
- ```
27
+ The architect Q-verdict subsections below record the original P156 trade-off analysis for history; where they describe placeholder/sentinel mechanics they are superseded by this amendment.
35
28
 
36
- Avoids tripping future structural lint while preserving the lightweight-capture promise (no AskUserQuestion gathering of alternatives at capture time).
29
+ ## Contract trade-offs
37
30
 
38
- ### Frontmatter sentinel values vs. truly minimal
31
+ ### Skeleton-MADR validity at status `proposed`
39
32
 
40
- Architect Q5 verdict: full minimum frontmatter with sentinel values is friendlier than absent fields:
33
+ Architect Q1 verdict (P156 review, superseded 2026-07-06): the review prompt tolerates not-yet-accepted ADRs at `status: proposed` — it checks "does the proposed change conflict with the decision's outcome?". Under the derived-substance amendment the MADR ≥2-options requirement is satisfied at capture (real options are derived), so there is no skeleton state to cover; `status: proposed` now signals only "derived substance awaiting human ratification + acceptance review".
41
34
 
42
- ```yaml
43
- ---
44
- status: "proposed"
45
- date: <YYYY-MM-DD>
46
- decision-makers: [unspecified — fill at canonical review]
47
- consulted: []
48
- informed: []
49
- reassessment-date: <YYYY-MM-DD + 3 months>
50
- ---
51
- ```
35
+ ### Considered Options — real alternatives, derived
52
36
 
53
- The architect-agent flags missing required frontmatter fields; sentinel-with-flag carries the deferral signal explicitly, which is more discoverable than absence at canonical-expansion time.
37
+ Architect Q2 verdict (P156, superseded 2026-07-06): the original numbered-placeholder sibling (`2. (deferred — see ...)`) existed only to satisfy ≥2-options lint. Under the derived-substance amendment the capture writes the chosen option PLUS every alternative actually weighed and rejected in the decision context — real options with one-line summaries. If the context genuinely weighed only one option, the capture derives the strongest status-quo/do-nothing alternative and says why it lost. Lint is satisfied by substance, not by a placeholder. Still no AskUserQuestion.
54
38
 
55
- `reassessment-date` defaults to 3 months from today (matches `create-adr` Step 4) — the criteria themselves remain deferred-flagged in body.
39
+ ### Frontmatter sentinel values vs. truly minimal
56
40
 
57
- ### Deferred-canonical-expansion contract
41
+ Architect Q5 verdict (P156, superseded 2026-07-06): the original sentinel `decision-makers: [unspecified — fill at canonical review]` was another deferral marker. Under the derived-substance amendment frontmatter is derived: `decision-makers: [<git config user.name>]` plus any decision-owner named in `$ARGUMENTS`; `consulted`/`informed` from context or `[]`. `reassessment-date` defaults to 3 months from today (matches `create-adr` Step 4); the Reassessment Criteria body section carries real reopen conditions derived at capture.
58
42
 
59
- Capture-adr skips the architect-agent review handoff that `/wr-architect:create-adr` Step 5 (confirm-with-user) implicitly performs. The trade-off:
43
+ ### Deferred-ratification contract (was: deferred-canonical-expansion)
60
44
 
61
- | Surface | Inline canonical (create-adr) | Deferred canonical (capture-adr) |
62
- |---------|-------------------------------|----------------------------------|
63
- | Architect-agent review at write-time | Yes (Step 5 confirm pass) | No (deferred to canonical expansion) |
64
- | Capture-time turn cost | ~10-15 turns | ~3-4 turns |
65
- | MADR conformance at write-time | Full | Skeleton (status: proposed covers) |
66
- | Audit trail (commit) | One commit covers full ADR | One commit covers skeleton |
67
- | Acceptance window | Same session | Bounded by next canonical-expansion invocation |
45
+ Capture-adr skips the interactive confirm-with-user pass that `/wr-architect:create-adr` Step 5 performs. The trade-off under the derived-substance amendment:
68
46
 
69
- The deferred contract is acceptable because:
47
+ | Surface | Inline intake (create-adr) | Capture (capture-adr) |
48
+ |---------|----------------------------|------------------------|
49
+ | Section substance at write-time | User-authored via AskUserQuestion | Agent-derived from decision context |
50
+ | Human ratification | Step 5 confirm pass, same session | `/wr-architect:review-decisions` drain, next interactive session |
51
+ | Ratification trigger | In-flow | Self-firing SessionStart oversight nudge (`human-oversight: unconfirmed`) |
52
+ | Capture-time turn cost | ~10-15 turns | ~5-6 turns |
53
+ | MADR conformance at write-time | Full | Full (derived) |
54
+ | Audit trail (commit) | One commit covers full ADR | One commit covers full derived ADR |
70
55
 
71
- 1. **Status `proposed` is the explicit covering signal** that the ADR is not accepted yet. The architect-agent reviews `.proposed.md` files and can flag deferred-skeleton state for expansion before any downstream consumer treats it as accepted.
72
- 2. **The trailing pointer in Step 6 is the user-visible signal** that canonical expansion is needed. The user has explicit instructions for how to reconcile.
73
- 3. **Auto-detect-and-expand is a follow-up** (Q3 verdict — out of scope for P156). When `/wr-architect:create-adr` is later invoked on a captured `<NNN>`, it can detect the existing skeleton and expand the deferred sections rather than writing a new ADR. P156 does not ship this auto-detect path; the manual workflow is `/wr-architect:create-adr` invoked with the captured ID + body context.
56
+ The contract passes the P375 rot test because the ratification path starts from a self-firing trigger (the SessionStart nudge), not a named on-demand skill. The pre-amendment version failed that test: expansion depended on someone remembering to run `/wr-architect:create-adr <NNN>`, and nothing ever fired it.
74
57
 
75
58
  ### No AskUserQuestion at all
76
59
 
77
60
  Architect Q4 + JTBD review confirmed: capture-adr is a **mechanical-stage skill** per ADR-044's framework-resolution boundary. Every potentially-interactive decision is framework-mediated:
78
61
 
79
- - **Considered Options**: skeleton placeholder; defer ≥2-options requirement to canonical review.
80
- - **Decision Drivers / Consequences / Confirmation**: framework-policy deferred flag; canonical review fills.
81
- - **Reassessment date**: framework-policy default 3 months from today.
82
- - **Decision-makers / consulted / informed**: framework-policy sentinel `[unspecifiedfill at canonical review]`.
62
+ - **Considered Options**: silent derivation of chosen + actually-rejected alternatives (≥2 real options at capture).
63
+ - **Decision Drivers / Consequences / Confirmation**: silent derivation of real content from the decision context.
64
+ - **Reassessment date**: framework-policy default 3 months from today; criteria derived.
65
+ - **Decision-makers / consulted / informed**: derived from git `user.name` + context never a sentinel.
83
66
  - **Multi-decision split**: out of scope. The user invoking capture-adr with a multi-decision payload gets one ADR with the full payload; they re-route to `/wr-architect:create-adr` for the structured Step 2b decision-boundary split.
84
67
 
85
68
  This mirrors the mechanical-stage carve-out pattern documented in CLAUDE.md (P132 / inverse-P078 trap): when a SKILL contract names a stage as mechanical, do not ask. Per-action consent gates re-ask decisions the user already made and silently undo the load-bearing UX investment.
@@ -94,9 +77,9 @@ AFK orchestrators MUST NOT invoke capture-adr with empty arguments — caller-si
94
77
 
95
78
  ### Partial `$ARGUMENTS` (Title only / Title + Decision)
96
79
 
97
- If only Title is supplied, write the skeleton with deferred placeholders in Context + Decision Outcome. If Title + Decision (no Context), defer Context only. The deferred-flag literal pointer string preserves the canonical-expansion signal.
80
+ If only Title is supplied, derive Context + Decision from the invoking session's decision context. If Title + Decision (no Context), derive Context. Derivation is real prose from the context at hand — never a placeholder (RFC-045).
98
81
 
99
- This is a graceful-degradation case — real captures carry Title + Context + Decision — but the partial-payload path prevents a halt when only some context is available.
82
+ This is a graceful-degradation case — real captures carry Title + Context + Decision — but the partial-payload path prevents a halt when only some of the payload is spelled out.
100
83
 
101
84
  ### Title slug collision
102
85
 
@@ -110,34 +93,34 @@ If the local session has not fetched recently and origin has captures the local
110
93
 
111
94
  `--name-only` is required (P056): without it, default `git ls-tree` output carries the 40-char blob SHA which can contain three-digit runs that the digit-extraction regex false-matches. Same fix as create-adr Step 3 / manage-problem Step 3.
112
95
 
113
- ### Captured ADR never expanded
96
+ ### Captured ADR never ratified
114
97
 
115
- If the user captures and never invokes canonical expansion, the `.proposed.md` skeleton remains with deferred-flagged sections. Acceptable failure mode: the architect-agent flags `.proposed.md` files during compliance review and surfaces stale skeletons for expansion. The skeleton is more useful than no record at all (P156 line 19 driver: "decisions not captured drift; future iters reinvent the same design space").
98
+ If the user captures and never ratifies, the `.proposed.md` ADR remains `human-oversight: unconfirmed` and the SessionStart oversight nudge re-surfaces it every session until the `/wr-architect:review-decisions` drain handles it. Unlike the pre-RFC-045 never-expanded failure mode, this state cannot rot silently: the nudge is self-firing, and the sections already carry real (if unratified) substance.
116
99
 
117
100
  ### Architect-review verdict capture
118
101
 
119
102
  Use case: a `wr-architect:agent` review yields PASS-WITH-NOTES with substantive rationale. Pattern:
120
103
 
121
104
  1. User invokes capture-adr with `$ARGUMENTS = "Title from review topic\nContext: review of <change>\nDecision: <one-line verdict + rationale>"`.
122
- 2. Skeleton lands at `docs/decisions/<NNN>-<kebab-title>.proposed.md` with status `proposed`.
123
- 3. Trailing pointer reminds user to canonical-expand.
124
- 4. Canonical expansion via `/wr-architect:create-adr <NNN>` fleshes out Considered Options (the alternatives the architect weighed) + Consequences + Confirmation + Reassessment.
105
+ 2. The ADR lands at `docs/decisions/<NNN>-<kebab-title>.proposed.md` with status `proposed`, all sections derived — Considered Options carries the alternatives the architect actually weighed, Consequences the trade-offs from the verdict rationale.
106
+ 3. Trailing pointer notes the ADR awaits ratification at the oversight drain.
107
+ 4. The SessionStart nudge surfaces it; the user ratifies or amends at `/wr-architect:review-decisions`.
125
108
 
126
109
  This pattern preserves architect-review verdicts as first-class ADR-shaped records instead of letting them rot in commit-message bodies.
127
110
 
128
111
  ### Cross-namespace consistency with capture-problem
129
112
 
130
- The `capture-` verb is consistent across `/wr-itil:capture-problem` and `/wr-architect:capture-adr`. Same dispatch shape (~3-4 turns), same deferred-placeholder pattern, same single-commit-per-capture grain, same trailing-pointer signal. Users learn one mental model that spans both. ADR-032 amendment names this symmetry.
113
+ The `capture-` verb is consistent across `/wr-itil:capture-problem` and `/wr-architect:capture-adr`. Same dispatch shape, same derive-real-values-at-capture discipline (ADR-067 for capture-problem ratings; RFC-045 for capture-adr sections), same single-commit-per-capture grain, same trailing-pointer signal. Users learn one mental model that spans both. ADR-032 amendment names this symmetry.
131
114
 
132
115
  ## Composition with the rest of the suite
133
116
 
134
117
  ### `/wr-architect:create-adr`
135
118
 
136
- Heavyweight intake counterpart. The two skills share the `docs/decisions/*.proposed.md` directory and the next-ID formula. Cross-skill ordering: capture-adr writes a skeleton at `<NNN>`; later `/wr-architect:create-adr <NNN>` (or direct Edit) expands the deferred sections in place. The auto-detect-and-expand path (where `/wr-architect:create-adr` mechanically detects a captured skeleton at the requested ID and expands rather than writes) is a follow-up ticket (architect Q3 verdict — out of scope for P156).
119
+ Heavyweight intake counterpart. The two skills share the `docs/decisions/*.proposed.md` directory and the next-ID formula. Cross-skill ordering: capture-adr writes a fully-derived ADR at `<NNN>`; `/wr-architect:create-adr <NNN>` (or `/wr-architect:review-decisions`) is the human-ratification/acceptance surface, not an expansion surface there are no deferred sections to expand post-RFC-045.
137
120
 
138
121
  ### `wr-architect:agent`
139
122
 
140
- The review surface that processes ADR review delegations. capture-adr does not invoke the architect-agent inline; the deferred-canonical-expansion contract routes review through `/wr-architect:create-adr`'s Step 5 confirm pass. The architect-agent reviewing a `.proposed.md` skeleton sees `status: proposed` + deferred-flag literals and treats it as a not-yet-accepted ADR; reviews focus on whether the captured Decision conflicts with existing accepted ADRs.
123
+ The review surface that processes ADR review delegations. capture-adr does not invoke the architect-agent inline; review fires at acceptance (via `/wr-architect:create-adr`'s Step 5 confirm pass or direct delegation). The architect-agent reviewing a captured `.proposed.md` sees `status: proposed` + `human-oversight: unconfirmed` and treats it as a not-yet-accepted, not-yet-ratified ADR; reviews focus on whether the captured Decision conflicts with existing accepted ADRs.
141
124
 
142
125
  ### `/wr-itil:manage-problem` / `/wr-itil:capture-problem`
143
126
 
@@ -157,7 +140,7 @@ The intended invocation surface is `/wr-architect:capture-adr <Title>\n<Context>
157
140
  - **ADR-013** — structured user interaction (Rule 6 fail-safe; capture-adr has no AskUserQuestion branches so Rule 6 is trivially satisfied).
158
141
  - **ADR-014** — governance skills commit their own work (capture-adr owns its commit).
159
142
  - **ADR-019** — AFK orchestrator preflight (next-ID formula uses origin-tracking ref per ADR-019 confirmation criterion 2).
160
- - **ADR-032** — governance skill invocation patterns (this skill's parent ADR; foreground-lightweight-capture variant amendment 2026-05-03 for capture-adr).
143
+ - **ADR-032** — governance skill invocation patterns (this skill's parent ADR; foreground-lightweight-capture variant amendment 2026-05-03; derived-substance amendment 2026-07-06 per RFC-045).
161
144
  - **ADR-038** — progressive disclosure (SKILL.md + REFERENCE.md split shape).
162
145
  - **ADR-044** — decision-delegation contract (framework-mediated mechanical-stage carve-outs).
163
146
  - **ADR-049** — bin/ on PATH (capture-adr is self-contained; no new shim required, same as create-adr).
@@ -173,3 +156,4 @@ The intended invocation surface is `/wr-architect:capture-adr <Title>\n<Context>
173
156
  - **P157** — sibling pending-questions-surface hook.
174
157
  - **P056** — ticket-creator next-ID lookup blob-SHA false-match (capture-adr's next-ID formula uses the `--name-only` fix).
175
158
  - **P040** — origin-collision incident referenced in Edge cases.
159
+ - **P375** — named re-entry point is not a self-firing cadence; drove the RFC-045 derived-substance amendment.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: wr-architect:capture-adr
3
- description: Lightweight ADR-capture skill for aside-invocation during foreground work — single-option skeleton, deferred-flagged sections (Considered Options / Decision Drivers / Consequences / Confirmation / Reassessment), single commit, no inline architect-review handoff. Defers full canonical expansion to /wr-architect:create-adr. Use this when the user (or agent mid-iter) wants to record a decision quickly without the ~10-15 turn ceremony of /wr-architect:create-adr. For full-intake new ADR creation with options + drivers + consequences + confirmation, use /wr-architect:create-adr.
3
+ description: Lightweight ADR-capture skill for aside-invocation during foreground work — derives full MADR substance (Considered Options / Decision Drivers / Consequences / Confirmation / Reassessment) silently from the in-session decision context, single commit, no inline architect-review handoff, no AskUserQuestion. Lightweight means zero-interaction + single-commit, not skimpy content (RFC-045). Use this when the user (or agent mid-iter) wants to record a decision quickly without the ~10-15 turn ceremony of /wr-architect:create-adr. For interactive full-intake new ADR creation where the user authors the options + drivers + consequences + confirmation, use /wr-architect:create-adr.
4
4
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob
5
5
  ---
6
6
 
@@ -17,9 +17,9 @@ This skill is the foreground-lightweight-capture variant of `/wr-architect:creat
17
17
  - **User-driven design conversations**: user resolves options (a)/(b)/(c) during conversational work; today the settlement gets buried in a problem-ticket RCA section instead of codified.
18
18
 
19
19
  **Use `/wr-architect:create-adr` instead** when:
20
- - The user wants to walk the full intake flow (Considered Options ≥2, Decision Drivers, full Consequences, Confirmation criteria, Pros/Cons of Options).
21
- - The decision is large enough that the deferred-placeholder pattern is unhelpful (the user already has the canonical-shape content).
22
- - The decision needs immediate architect review + acceptance (capture-adr writes `.proposed.md`; canonical acceptance is a follow-up via `/wr-architect:create-adr` or direct architect-agent review).
20
+ - The user wants to walk the full interactive intake flow and author the sections themselves (Considered Options ≥2, Decision Drivers, full Consequences, Confirmation criteria, Pros/Cons of Options via AskUserQuestion).
21
+ - The decision is contested or under-specified in-session silent derivation needs a real decision context to derive FROM; if the options were never actually weighed, create-adr's interactive intake is the honest surface.
22
+ - The decision needs immediate architect review + acceptance (capture-adr writes `.proposed.md`; acceptance review is a follow-up via `/wr-architect:create-adr` or direct architect-agent review).
23
23
 
24
24
  ## Rule 6 audit (per ADR-032 + ADR-013)
25
25
 
@@ -27,14 +27,16 @@ This skill has **zero AskUserQuestion branches** by design. Each potentially-int
27
27
 
28
28
  | Decision | Resolution |
29
29
  |----------|-----------|
30
- | Considered Options ≥2 | Mechanical: skeleton writes `1. Option A (chosen) <one-line>` + `2. (deferred see /wr-architect:create-adr canonical review)`. The MADR ≥2-options requirement is enforced at acceptance, not at skeleton time; status `proposed` covers skeleton state. |
31
- | Decision drivers | Framework-policy: flag `(deferred to /wr-architect:create-adr canonical review)`. Drivers are typically discovered during canonical expansion. |
32
- | Consequences | Framework-policy: flag `(deferred to /wr-architect:create-adr canonical review)`. Consequences require trade-off analysis the lightweight path does not perform. |
33
- | Confirmation criteria | Framework-policy: flag `(deferred to /wr-architect:create-adr canonical review)`. Testable confirmation is a canonical-review concern. |
34
- | Reassessment criteria | Framework-policy default: 3 months from today (matches `create-adr` Step 4 default); flag `(deferred — refine at canonical review)` for the criteria themselves. |
35
- | Decision-makers / consulted / informed | Framework-policy: write `[unspecified fill at canonical review]` sentinel + flag at canonical review. |
30
+ | Considered Options ≥2 | Silent derivation (ADR-044 category-4): write the chosen option PLUS every alternative that was actually weighed and rejected in the decision context (`$ARGUMENTS` + the invoking session). Real options with one-line summariesnever a placeholder sibling. If the context genuinely weighed only one option, derive the strongest do-nothing / status-quo alternative and say why it lost. |
31
+ | Decision drivers | Silent derivation: extract the forces that actually drove the decision from the context (the problem's symptoms, the constraint that ruled options out, the user's stated priorities). |
32
+ | Consequences | Silent derivation: real Good/Neutral/Bad trade-off analysis of the chosen option. The invoking agent performs the analysis at capture it has more decision context in-session than any later expansion pass would. |
33
+ | Confirmation criteria | Silent derivation: testable criteria (a command, an observable behaviour, a hook that fires) confirming the decision is implemented and holding. |
34
+ | Reassessment criteria | Silent derivation: real conditions that would reopen the decision, plus `reassessment-date` default 3 months from today (matches `create-adr` Step 4 default). |
35
+ | Decision-makers / consulted / informed | Silent derivation: `decision-makers: [<git config user.name>]` plus any decision-owner named in `$ARGUMENTS`; `consulted`/`informed` from context or `[]`. Never a sentinel string. |
36
36
  | Empty `$ARGUMENTS` | Halt-with-stderr-directive: print "capture-adr requires Title + 1-line Context + 1-line Decision in $ARGUMENTS — invoke /wr-architect:create-adr instead for the full intake flow" and exit. AFK orchestrators MUST NOT invoke capture-adr with empty arguments — caller-side contract. |
37
37
 
38
+ **No placeholder, pointer, or sentinel strings of any kind** (RFC-045 / P375, derived-substance amendment to ADR-032 2026-07-06). The previous deferred-placeholder pattern (`(deferred to /wr-architect:create-adr canonical review)`) named a re-entry point nothing self-firing ever triggered — the sections rotted. Same correction class as ADR-067's silent derivation of capture-problem ratings: derive a real value, always. The derived substance is provisional — that is what `human-oversight: unconfirmed` states honestly, and the SessionStart oversight nudge → `/wr-architect:review-decisions` drain is the self-firing surface where a human ratifies or amends it (ADR-066).
39
+
38
40
  Per ADR-013 Rule 6 fail-safe: every branch above resolves without user input, so AFK and interactive contexts behave identically.
39
41
 
40
42
  ## Steps
@@ -43,7 +45,7 @@ Per ADR-013 Rule 6 fail-safe: every branch above resolves without user input, so
43
45
 
44
46
  The expected `$ARGUMENTS` shape is free-text describing **(a) Title**, **(b) one-line Context** (the problem being solved), and **(c) one-line Decision** (the chosen option in one sentence).
45
47
 
46
- Parsing heuristic: split on the first newline (Title) and second newline (Context); the rest is Decision. If only one line is supplied, treat it as Title and use deferred-flag placeholders for Context + Decision. If two lines, treat as Title + Decision and defer Context.
48
+ Parsing heuristic: split on the first newline (Title) and second newline (Context); the rest is Decision. If only one line is supplied, treat it as Title and derive Context + Decision from the invoking session's decision context. If two lines, treat as Title + Decision and derive Context. Derivation is real prose from the context at hand — never a placeholder.
47
49
 
48
50
  Empty `$ARGUMENTS` halts per the Rule 6 audit above.
49
51
 
@@ -60,10 +62,10 @@ ADR titles must name the **decision outcome** as a short noun phrase, not the qu
60
62
  In `capture-adr` the chosen Decision is pinned in `$ARGUMENTS` at invocation, so the caller SHOULD supply a Title already in outcome shape — the framework does not retitle here (the canonical-outcome short-name is the caller's to author, not the framework's to derive). If the parsed Title slug matches a question-shape pattern (`-vs-`, `should-`, `whether-`, `-or-`), emit an advisory in the I2-isomorphic shape via the shared `emit_stderr_advisory` helper:
61
63
 
62
64
  ```
63
- capture-adr: derived title='<slug>' from $ARGUMENTS — slug appears question-shaped (matched <pattern>); the Decision is pinned in $ARGUMENTS so an outcome-shaped Title is recommended; re-invoke with an outcome-shaped Title or rename the file at canonical expansion.
65
+ capture-adr: derived title='<slug>' from $ARGUMENTS — slug appears question-shaped (matched <pattern>); the Decision is pinned in $ARGUMENTS so an outcome-shaped Title is recommended; re-invoke with an outcome-shaped Title or rename the file before acceptance review.
64
66
  ```
65
67
 
66
- The advisory is **advisory-only** (no halt, no retitle). The caller may proceed with the question-shaped slug if they choose; the subsequent `/wr-architect:create-adr <NNN>` canonical-expansion pass picks up the retitle in its Step 5a mechanical retitle-after-decision check.
68
+ The advisory is **advisory-only** (no halt, no retitle). The caller may proceed with the question-shaped slug if they choose; a subsequent `/wr-architect:create-adr <NNN>` acceptance pass picks up the retitle in its Step 5a mechanical retitle-after-decision check.
67
69
 
68
70
  (Serves JTBD-001 — skimmable titles on the on-disk record; ADR-044 category-4 silent-framework — advisory, not ask.)
69
71
 
@@ -81,76 +83,81 @@ next=$(printf '%03d' $(( 10#$(echo -e "${local_max:-0}\n${origin_max:-0}" | sort
81
83
 
82
84
  Log the renumber decision in the operation report if origin and local diverged.
83
85
 
84
- ### 3. Skeleton-fill the MADR template
86
+ ### 3. Derive-fill the MADR template
85
87
 
86
88
  **File path**: `docs/decisions/<NNN>-<kebab-title>.proposed.md`
87
89
 
88
- **Template** (deferred-placeholder pattern — flag every section the capture didn't fill, with the literal pointer string `(deferred to /wr-architect:create-adr canonical review)` so canonical-expansion tooling can detect and expand mechanically):
90
+ **Template** (derived-substance pattern per RFC-045 — every section carries real content derived from `$ARGUMENTS` + the invoking session's decision context; no placeholder, pointer, or sentinel strings of any kind):
89
91
 
90
92
  ```markdown
91
93
  ---
92
94
  status: "proposed"
93
95
  date: <YYYY-MM-DD>
94
96
  human-oversight: unconfirmed
95
- decision-makers: [unspecified fill at canonical review]
96
- consulted: []
97
- informed: []
97
+ decision-makers: [<git config user.name>, <any decision-owner named in $ARGUMENTS>]
98
+ consulted: [<from context, or empty>]
99
+ informed: [<from context, or empty>]
98
100
  reassessment-date: <YYYY-MM-DD + 3 months>
99
101
  ---
100
102
 
101
103
  # <Title>
102
104
 
103
- > Captured via /wr-architect:capture-adr (foreground-lightweight aside-invocation per ADR-032 P156 amendment). Run /wr-architect:create-adr on this ID to expand the deferred sections canonically.
105
+ > Captured via /wr-architect:capture-adr (foreground-lightweight aside-invocation per ADR-032, derived-substance amendment 2026-07-06 / RFC-045). Section content was derived by the capturing agent from the in-session decision context; human-oversight: unconfirmed until ratified at the /wr-architect:review-decisions drain.
104
106
 
105
107
  ## Context and Problem Statement
106
108
 
107
- <one-line Context from $ARGUMENTS, or "(deferred to /wr-architect:create-adr canonical review)" if not supplied>
109
+ <Context from $ARGUMENTS, expanded with the problem the session was actually solving when the decision arose>
108
110
 
109
111
  ## Decision Drivers
110
112
 
111
- - (deferred to /wr-architect:create-adr canonical review)
113
+ - <the real forces that drove the decision: symptoms, constraints, stated priorities — one bullet each>
112
114
 
113
115
  ## Considered Options
114
116
 
115
- 1. **Option A (chosen)** — <one-line summary derived from Decision in $ARGUMENTS>
116
- 2. (deferredsee /wr-architect:create-adr canonical review)
117
+ 1. **<Chosen option> (chosen)** — <one-line summary>
118
+ 2. **<Rejected alternative actually weighed in context>** <one-line summary>
119
+ <further alternatives if the context weighed them; if only one option was ever on the table, the status-quo/do-nothing alternative and why it lost>
117
120
 
118
121
  ## Decision Outcome
119
122
 
120
- Chosen option: **"Option A"**, because <one-line Decision from $ARGUMENTS, or "(deferred to /wr-architect:create-adr canonical review)" if not supplied>.
123
+ Chosen option: **"<Chosen option>"**, because <the real reason from $ARGUMENTS/context>.
121
124
 
122
125
  ## Consequences
123
126
 
124
127
  ### Good
125
128
 
126
- - (deferred to /wr-architect:create-adr canonical review)
129
+ - <real benefits of the chosen option>
127
130
 
128
131
  ### Neutral
129
132
 
130
- - (deferred to /wr-architect:create-adr canonical review)
133
+ - <real neutral effects, or omit bullets that would be filler>
131
134
 
132
135
  ### Bad
133
136
 
134
- - (deferred to /wr-architect:create-adr canonical review)
137
+ - <real costs/risks accepted by choosing this option>
135
138
 
136
139
  ## Confirmation
137
140
 
138
- (deferred to /wr-architect:create-adr canonical review)
141
+ <testable criteria: a command, an observable behaviour, a gate that fires — how a future reader verifies the decision is implemented and holding>
139
142
 
140
143
  ## Pros and Cons of the Options
141
144
 
142
- ### Option A
145
+ ### <Chosen option>
146
+
147
+ - Good, because <...>
148
+ - Bad, because <...>
143
149
 
144
- - (deferred to /wr-architect:create-adr canonical review)
150
+ ### <Rejected alternative>
151
+
152
+ - Good, because <...>
153
+ - Bad, because <...>
145
154
 
146
155
  ## Reassessment Criteria
147
156
 
148
- (deferred to /wr-architect:create-adr canonical reviewdefault reassessment-date 3 months from capture)
157
+ <real conditions that would reopen this decision e.g. the constraint that forced it lifts, the chosen mechanism's false-positive rate exceeds tolerance>
149
158
  ```
150
159
 
151
- The deferred-placeholder pattern is load-bearing `/wr-architect:create-adr` (and any future canonical-expansion auto-detect path) keys off the literal pointer string `(deferred to /wr-architect:create-adr canonical review)` to surface captured ADRs for expansion.
152
-
153
- The numbered-options placeholder (`1. Option A (chosen) ...` + `2. (deferred ...)`) preserves the MADR ≥2-options surface for any doc-lint that asserts numbered-option presence; status `proposed` covers the skeleton state for canonical-acceptance review.
160
+ Content-quality bar: each section must be true to the decision context at hand, not boilerplate. A section the context genuinely gives nothing for gets the honest one-liner saying so in real prose (e.g. "No neutral consequences identified at capture") never a deferral marker. The capturing agent has more decision context in-session than any later pass will; capture is the cheapest moment to write the substance down.
154
161
 
155
162
  ### 4. Write the file
156
163
 
@@ -158,7 +165,7 @@ Single `Write` to `docs/decisions/<NNN>-<kebab-title>.proposed.md`.
158
165
 
159
166
  ### 4.5. Refresh the decisions compendium (ADR-077)
160
167
 
161
- After the ADR skeleton lands, regenerate `docs/decisions/README.md` so the architect-agent routine load surface includes the new entry:
168
+ After the ADR lands, regenerate `docs/decisions/README.md` so the architect-agent routine load surface includes the new entry:
162
169
 
163
170
  ```bash
164
171
  wr-architect-generate-decisions-compendium
@@ -185,39 +192,39 @@ Commit message:
185
192
  docs(decisions): capture ADR-<NNN> <title>
186
193
  ```
187
194
 
188
- The `capture` verb is the audit signal that this ADR landed via the lightweight aside path (vs. `add` / `accept` for canonical create-adr's full intake). The status remains `proposed` until canonical review accepts it.
195
+ The `capture` verb is the audit signal that this ADR landed via the lightweight aside path (vs. `add` / `accept` for canonical create-adr's full intake). The status remains `proposed` until acceptance review (with human substance-ratification per ADR-064) promotes it.
189
196
 
190
197
  ### 6. Report
191
198
 
192
199
  After the commit, report:
193
200
 
194
201
  - The new ADR file path and ID.
195
- - Trailing pointer: `Run /wr-architect:create-adr <NNN> next to expand the deferred sections canonically (Considered Options ≥2, Decision Drivers, Consequences, Confirmation, Reassessment Criteria).`
202
+ - Trailing pointer: `ADR-<NNN> was captured with derived substance and is human-oversight: unconfirmed the SessionStart oversight nudge will surface it for ratification at /wr-architect:review-decisions (or ratify now if interactive).`
196
203
  - Note any renumber-from-origin-collision log line from Step 2.
197
204
 
198
- The trailing pointer is **not optional** — it is the user-visible signal that the skeleton needs canonical expansion before acceptance review.
205
+ The trailing pointer is **not optional** — it is the user-visible signal that the derived substance awaits human ratification. Unlike the pre-RFC-045 contract there is no expansion step: the sections are already real; the drain confirms or amends them.
199
206
 
200
- **Confirm-every-ADR gate (ADR-064):** a capture-adr skeleton is recorded `proposed` with a pre-pinned decision but WITHOUT human review of the options. It must NOT be promoted to `accepted` until it has been through a `/wr-architect:create-adr` (or equivalent) `AskUserQuestion` review-and-confirm pass. Capture records the decision quickly; the confirm — not the capture — is what gives it human oversight. This is prong 1 of P283 (lift auto-/quick-recorded decisions to human-confirmed before they stand).
207
+ **Confirm-every-ADR gate (ADR-064):** a capture-adr ADR is recorded `proposed` with derived substance but WITHOUT human review of that substance. It must NOT be promoted to `accepted` until a human has ratified the derived content via `/wr-architect:review-decisions` (or a `/wr-architect:create-adr` review-and-confirm pass). Capture records the decision quickly; the ratification — not the capture — is what gives it human oversight. This is prong 1 of P283 (lift auto-/quick-recorded decisions to human-confirmed before they stand).
201
208
 
202
- **Oversight marker discipline (ADR-066 amendment 2026-06-02 / P348).** A capture-adr skeleton MUST be born `human-oversight: unconfirmed` — NOT `confirmed`. Capture is the AFK-friendly aside surface; there is no substance-confirm `AskUserQuestion` pass in this flow, so `confirmed` would be a hollow marker (the P348 bug class). The `architect-oversight-marker-discipline.sh` PreToolUse hook will DENY any Edit/Write that introduces `human-oversight: confirmed` without a matching session-scoped evidence marker. The frontmatter skeleton (Step 3 above) MUST include `human-oversight: unconfirmed` so the ADR enters the world honestly self-identified as needing user confirmation. The drain (`/wr-architect:review-decisions`) and the canonical-expansion path (`/wr-architect:create-adr <NNN>`) are the surfaces that legitimately promote it to `confirmed` via `wr-architect-mark-oversight-confirmed` + the gated marker write.
209
+ **Oversight marker discipline (ADR-066 amendment 2026-06-02 / P348).** A capture-adr ADR MUST be born `human-oversight: unconfirmed` — NOT `confirmed`. Capture is the AFK-friendly aside surface; there is no substance-confirm `AskUserQuestion` pass in this flow, so `confirmed` would be a hollow marker (the P348 bug class). The `architect-oversight-marker-discipline.sh` PreToolUse hook will DENY any Edit/Write that introduces `human-oversight: confirmed` without a matching session-scoped evidence marker. The frontmatter (Step 3 above) MUST include `human-oversight: unconfirmed` so the ADR enters the world honestly self-identified as needing user confirmation. The drain (`/wr-architect:review-decisions`) and a `/wr-architect:create-adr <NNN>` review pass are the surfaces that legitimately promote it to `confirmed` via `wr-architect-mark-oversight-confirmed` + the gated marker write.
203
210
 
204
211
  ## Composition with create-adr
205
212
 
206
213
  | Concern | create-adr | capture-adr |
207
214
  |---------|------------|-------------|
208
- | Considered Options | AskUserQuestion gathering ≥2 options + pros/cons | Single-option skeleton with chosen flagged + deferred placeholder |
209
- | Decision Drivers | AskUserQuestion gathering | Deferred flag |
210
- | Consequences | AskUserQuestion gathering Good/Neutral/Bad | Deferred flag (Good/Neutral/Bad sections present, content deferred) |
211
- | Confirmation | AskUserQuestion gathering testable criteria | Deferred flag |
212
- | Reassessment criteria | AskUserQuestion gathering | 3-month default date + deferred-flag criteria |
213
- | Frontmatter | Full populated frontmatter | Sentinel values (`unspecified fill at canonical review`) + 3-month reassessment |
215
+ | Considered Options | AskUserQuestion gathering ≥2 options + pros/cons (user authors) | Silent derivation of chosen + actually-rejected alternatives (agent authors, human ratifies at drain) |
216
+ | Decision Drivers | AskUserQuestion gathering | Silent derivation from decision context |
217
+ | Consequences | AskUserQuestion gathering Good/Neutral/Bad | Silent derivation — real Good/Neutral/Bad trade-off analysis at capture |
218
+ | Confirmation | AskUserQuestion gathering testable criteria | Silent derivation of testable criteria |
219
+ | Reassessment criteria | AskUserQuestion gathering | Silent derivation + 3-month default date |
220
+ | Frontmatter | Full populated frontmatter | Derived values (git user.name etc.) no sentinels |
214
221
  | Decision-boundary check (Step 2b) | Multi-decision split via AskUserQuestion | Out of scope (one ADR per invocation) |
215
222
  | Supersession (Step 6) | Handles `git mv .accepted.md → .superseded.md` | Out of scope (capture is creation only) |
216
- | Confirm-with-user (Step 5) | AskUserQuestion review pass | Out of scope |
223
+ | Confirm-with-user (Step 5) | AskUserQuestion review pass at intake | Deferred to the self-firing oversight drain (`human-oversight: unconfirmed` → SessionStart nudge → `/wr-architect:review-decisions`) |
217
224
  | Commit grain | One commit per intake | One commit per capture |
218
- | Use case | Full-intake new ADR; user wants to walk the flow | Aside-invocation; capture-and-continue |
225
+ | Use case | Full-intake new ADR; user wants to author the flow interactively | Aside-invocation; capture-and-continue |
219
226
 
220
- The two skills share the `docs/decisions/*.proposed.md` directory and the next-ID formula. Cross-skill ordering: capture-adr writes a skeleton at `<NNN>`; later `/wr-architect:create-adr <NNN>` (or direct Edit) expands the deferred sections in place. Auto-detect-and-expand path is a follow-up (see "Composition" in REFERENCE.md).
227
+ The two skills share the `docs/decisions/*.proposed.md` directory and the next-ID formula. Category-1 reconciliation (per the ADR-032 derived-substance amendment): create-adr's Step 2 dispatch table classifies Drivers/Options/Consequences/Confirmation as category-1 "only the user knows" that governs the interactive intake surface. On the capture surface the same fields are derived-provisional substance under `human-oversight: unconfirmed`, ratified at the ADR-066 drain (the ADR-067 lift-auto-decisions-to-human pattern). Capture derives-then-ratifies; create-adr asks-then-records.
221
228
 
222
229
  ## Related
223
230
 
@@ -231,6 +238,6 @@ The two skills share the `docs/decisions/*.proposed.md` directory and the next-I
231
238
  - **ADR-049** — bin/ on PATH (capture-adr is self-contained; no shim required, same as create-adr).
232
239
  - **ADR-052** — behavioural-tests-default for skill testing.
233
240
  - `packages/architect/skills/create-adr/SKILL.md` — heavyweight intake counterpart.
234
- - `packages/architect/agents/agent.md` — wr-architect:agent review surface; reviews `.proposed.md` skeletons during canonical-expansion delegation.
241
+ - `packages/architect/agents/agent.md` — wr-architect:agent review surface; reviews `.proposed.md` ADRs at acceptance delegation.
235
242
 
236
243
  $ARGUMENTS
@@ -11,15 +11,16 @@
11
11
  # fixture decisions directory and asserts the computed next ID
12
12
  # matches the expected zero-padded value (including the empty-dir
13
13
  # first-ADR base case).
14
- # 2. Skeleton-fill MADR shape captured ADR has Title + status proposed
15
- # + deferred-flag literal pointer string + numbered-options
16
- # placeholder (1. chosen + 2. deferred). Tests execute the
17
- # skeleton-fill template against fixture inputs and assert the
18
- # resulting file's load-bearing fields.
14
+ # 2. Derive-fill MADR shape (RFC-045 derived-substance amendment)
15
+ # captured ADR has Title + status proposed + human-oversight:
16
+ # unconfirmed + real derived content in every section, and matches
17
+ # NOTHING in the shared deferral-marker vocabulary
18
+ # (DEFERRAL_MARKER_RE, packages/retrospective/hooks/lib/
19
+ # deferral-markers.sh) — no placeholder/pointer/sentinel of any kind.
19
20
  # 3. Default reassessment-date — 3 months from today is computed
20
21
  # correctly and lands in frontmatter.
21
- # 4. Frontmatter sentinel values — decision-makers: [unspecified fill
22
- # at canonical review] is the framework-policy default.
22
+ # 4. Frontmatter derived values — decision-makers carries a real name
23
+ # (git user.name), never a sentinel.
23
24
  #
24
25
  # Structural assertions are limited to existence/wiring (file presence +
25
26
  # frontmatter name + allowed-tools surface) per the precedent set by the
@@ -143,22 +144,28 @@ teardown() {
143
144
  }
144
145
 
145
146
  # ---------------------------------------------------------------------------
146
- # Skeleton-fill MADR shape — capture-adr writes a deferred-placeholder ADR
147
- # at status: proposed. Load-bearing primitives:
147
+ # Derive-fill MADR shape (RFC-045 / P375) — capture-adr writes a fully-
148
+ # derived ADR at status: proposed. Load-bearing primitives:
148
149
  # - Title at H1
149
- # - status: proposed in frontmatter
150
- # - decision-makers sentinel
150
+ # - status: proposed + human-oversight: unconfirmed in frontmatter
151
+ # - decision-makers derived (real name, no sentinel)
151
152
  # - reassessment-date 3 months from today
152
- # - Numbered-options placeholder (1. chosen + 2. deferred) — preserves
153
- # MADR ≥2-options surface for any doc-lint assertion.
154
- # - Literal pointer string `(deferred to /wr-architect:create-adr
155
- # canonical review)` — this is the canonical-expansion detection key.
153
+ # - >=2 REAL numbered options (chosen + actually-rejected alternative)
154
+ # - Every section carries real derived prose; the file matches NOTHING
155
+ # in the shared deferral-marker vocabulary (DEFERRAL_MARKER_RE).
156
156
  # ---------------------------------------------------------------------------
157
157
 
158
- @test "capture-adr: skeleton-filled ADR carries deferred-flag literal pointer string" {
159
- # The literal `(deferred to /wr-architect:create-adr canonical review)`
160
- # is the load-bearing canonical-expansion detection signal. Any future
161
- # auto-detect-and-expand path will key off this string.
158
+ @test "capture-adr: derived-substance ADR matches nothing in the deferral-marker vocabulary" {
159
+ # RFC-045: no placeholder, pointer, or sentinel strings of any kind.
160
+ # Asserted against the single source of truth for the deferred-work
161
+ # vocabulary (P375 census) so "no placeholder of any kind" is the
162
+ # behavioural contract, not just "not the one old literal string".
163
+ MARKERS_LIB="${REPO_ROOT}/packages/retrospective/hooks/lib/deferral-markers.sh"
164
+ [ -f "$MARKERS_LIB" ]
165
+ # shellcheck disable=SC1090
166
+ source "$MARKERS_LIB"
167
+ [ -n "$DEFERRAL_MARKER_RE" ]
168
+
162
169
  mkdir -p "$TMPROOT/docs/decisions"
163
170
  TITLE="example-mid-iter-decision"
164
171
  ID="200"
@@ -167,12 +174,13 @@ teardown() {
167
174
  CONTEXT_LINE="Iter-bound design choice that needs codification."
168
175
  DECISION_LINE="Adopt Option A because it preserves invariants X and Y."
169
176
 
170
- # Mirror the SKILL.md skeleton-fill template.
177
+ # Mirror the SKILL.md derive-fill template with real derived content.
171
178
  cat > "$TMPROOT/docs/decisions/${ID}-${TITLE}.proposed.md" <<EOF
172
179
  ---
173
180
  status: "proposed"
174
181
  date: ${TODAY}
175
- decision-makers: [unspecified — fill at canonical review]
182
+ human-oversight: unconfirmed
183
+ decision-makers: [Test User]
176
184
  consulted: []
177
185
  informed: []
178
186
  reassessment-date: ${REASSESS}
@@ -180,7 +188,7 @@ reassessment-date: ${REASSESS}
180
188
 
181
189
  # ${TITLE}
182
190
 
183
- > Captured via /wr-architect:capture-adr (foreground-lightweight aside-invocation per ADR-032 P156 amendment). Run /wr-architect:create-adr on this ID to expand the deferred sections canonically.
191
+ > Captured via /wr-architect:capture-adr (foreground-lightweight aside-invocation per ADR-032, derived-substance amendment 2026-07-06 / RFC-045). Section content was derived by the capturing agent from the in-session decision context; human-oversight: unconfirmed until ratified at the /wr-architect:review-decisions drain.
184
192
 
185
193
  ## Context and Problem Statement
186
194
 
@@ -188,12 +196,13 @@ ${CONTEXT_LINE}
188
196
 
189
197
  ## Decision Drivers
190
198
 
191
- - (deferred to /wr-architect:create-adr canonical review)
199
+ - Invariant X must survive iter restarts.
200
+ - Option B would couple the loop to session state.
192
201
 
193
202
  ## Considered Options
194
203
 
195
204
  1. **Option A (chosen)** — ${DECISION_LINE}
196
- 2. (deferredsee /wr-architect:create-adr canonical review)
205
+ 2. **Option B (session-state coupling)** rejected: couples the loop to session state.
197
206
 
198
207
  ## Decision Outcome
199
208
 
@@ -203,58 +212,69 @@ Chosen option: **"Option A"**, because ${DECISION_LINE}
203
212
 
204
213
  ### Good
205
214
 
206
- - (deferred to /wr-architect:create-adr canonical review)
215
+ - Invariants X and Y hold across iters.
207
216
 
208
217
  ### Neutral
209
218
 
210
- - (deferred to /wr-architect:create-adr canonical review)
219
+ - No neutral consequences identified at capture.
211
220
 
212
221
  ### Bad
213
222
 
214
- - (deferred to /wr-architect:create-adr canonical review)
223
+ - One extra lookup per iter.
215
224
 
216
225
  ## Confirmation
217
226
 
218
- (deferred to /wr-architect:create-adr canonical review)
227
+ Run the iter loop twice; invariant X holds on the second run.
219
228
 
220
229
  ## Pros and Cons of the Options
221
230
 
222
231
  ### Option A
223
232
 
224
- - (deferred to /wr-architect:create-adr canonical review)
233
+ - Good, because invariants survive restarts.
234
+ - Bad, because of the extra lookup.
235
+
236
+ ### Option B
237
+
238
+ - Good, because no extra lookup.
239
+ - Bad, because session-state coupling breaks AFK iters.
225
240
 
226
241
  ## Reassessment Criteria
227
242
 
228
- (deferred to /wr-architect:create-adr canonical review default reassessment-date 3 months from capture)
243
+ Reopen if the extra-lookup cost exceeds one turn per iter.
229
244
  EOF
230
245
 
231
246
  ADR="$TMPROOT/docs/decisions/${ID}-${TITLE}.proposed.md"
232
247
  [ -f "$ADR" ]
233
248
 
234
- # Behavioural assertions: load-bearing fields present.
249
+ # Load-bearing fields present.
235
250
  run grep -F 'status: "proposed"' "$ADR"
236
251
  [ "$status" -eq 0 ]
237
- # Decision-makers sentinel for canonical-review fill.
238
- run grep -F 'decision-makers: [unspecified — fill at canonical review]' "$ADR"
252
+ run grep -F 'human-oversight: unconfirmed' "$ADR"
253
+ [ "$status" -eq 0 ]
254
+ # Decision-makers carries a real name — no sentinel.
255
+ run grep -F 'decision-makers: [Test User]' "$ADR"
239
256
  [ "$status" -eq 0 ]
240
257
  # Title from input lands at H1.
241
258
  run grep -F "# ${TITLE}" "$ADR"
242
259
  [ "$status" -eq 0 ]
243
- # Context survives verbatim from input.
260
+ # Context + Decision survive verbatim from input.
244
261
  run grep -F "$CONTEXT_LINE" "$ADR"
245
262
  [ "$status" -eq 0 ]
246
- # Decision survives verbatim from input.
247
263
  run grep -F "$DECISION_LINE" "$ADR"
248
264
  [ "$status" -eq 0 ]
249
- # Deferred-flag literal pointer string — canonical-expansion detection key.
250
- run grep -F '(deferred to /wr-architect:create-adr canonical review)' "$ADR"
251
- [ "$status" -eq 0 ]
265
+
266
+ # THE contract: nothing in the file matches the deferral vocabulary.
267
+ run grep -Eic "$DEFERRAL_MARKER_RE" "$ADR"
268
+ [ "$output" = "0" ]
269
+ # And the legacy sentinel shape is gone too.
270
+ run grep -F 'unspecified — fill at canonical review' "$ADR"
271
+ [ "$status" -ne 0 ]
252
272
  }
253
273
 
254
- @test "capture-adr: skeleton has numbered-options placeholder (1. chosen + 2. deferred)" {
255
- # MADR 2-options surface preserved at skeleton time so any doc-lint
256
- # asserting numbered-option presence does not fire on capture-adr output.
257
- # Architect Q2 verdict: write literal placeholder, defer enforcement.
274
+ @test "capture-adr: derived ADR carries >=2 REAL numbered options (no placeholder sibling)" {
275
+ # RFC-045: MADR >=2-options is satisfied by substance the chosen
276
+ # option plus an actually-weighed alternative never by a numbered
277
+ # placeholder.
258
278
  mkdir -p "$TMPROOT/docs/decisions"
259
279
  ID="201"
260
280
  TITLE="another-decision"
@@ -263,16 +283,18 @@ EOF
263
283
  ## Considered Options
264
284
 
265
285
  1. **Option A (chosen)** — One-line summary
266
- 2. (deferredsee /wr-architect:create-adr canonical review)
286
+ 2. **Status quo (do nothing)** rejected: the symptom recurs every session
267
287
  EOF
268
288
 
269
289
  ADR="$TMPROOT/docs/decisions/${ID}-${TITLE}.proposed.md"
270
290
  # Numbered option 1 with chosen marker.
271
291
  run grep -F '1. **Option A (chosen)**' "$ADR"
272
292
  [ "$status" -eq 0 ]
273
- # Numbered option 2 with deferred marker.
274
- run grep -F '2. (deferred — see /wr-architect:create-adr canonical review)' "$ADR"
293
+ # Numbered option 2 is real content, not a deferral.
294
+ run grep -E '^2\. \*\*' "$ADR"
275
295
  [ "$status" -eq 0 ]
296
+ run grep -F '(deferred' "$ADR"
297
+ [ "$status" -ne 0 ]
276
298
  }
277
299
 
278
300
  @test "capture-adr: default reassessment-date is 3 months from today (matches create-adr)" {
@@ -320,19 +342,21 @@ EOF
320
342
  }
321
343
 
322
344
  # ---------------------------------------------------------------------------
323
- # Deferred-canonical-expansion contract — distinguishing capture-adr from
345
+ # Deferred-ratification contract — distinguishing capture-adr from
324
346
  # create-adr. capture-adr must NOT invoke the architect-agent inline; it
325
- # writes status: proposed and defers review to canonical expansion.
326
- # This is the contract distinction from create-adr Step 5 (confirm-with-user).
347
+ # writes status: proposed + human-oversight: unconfirmed and defers human
348
+ # ratification to the self-firing oversight drain (RFC-045).
327
349
  # ---------------------------------------------------------------------------
328
350
 
329
- @test "capture-adr: SKILL.md prescribes deferred canonical expansion (no inline review handoff)" {
351
+ @test "capture-adr: SKILL.md routes ratification to the review-decisions drain (no inline review handoff)" {
330
352
  # The contract distinction from create-adr: capture-adr does NOT invoke
331
- # the wr-architect:agent review inline; it writes status: proposed and
332
- # routes review through the canonical-expansion path. A future
333
- # maintainer who copies create-adr's Step 5 confirm pass into capture-adr
334
- # would break the lightweight-capture promise.
335
- # Asserts the SKILL.md names the deferred contract explicitly.
336
- run grep -F '/wr-architect:create-adr' "$SKILL_FILE"
353
+ # the wr-architect:agent review inline; the derived substance is
354
+ # ratified at the /wr-architect:review-decisions drain surfaced by the
355
+ # SessionStart oversight nudge. A future maintainer who copies
356
+ # create-adr's Step 5 confirm pass into capture-adr would break the
357
+ # zero-interaction promise.
358
+ run grep -F '/wr-architect:review-decisions' "$SKILL_FILE"
359
+ [ "$status" -eq 0 ]
360
+ run grep -F 'human-oversight: unconfirmed' "$SKILL_FILE"
337
361
  [ "$status" -eq 0 ]
338
362
  }
@@ -10,7 +10,7 @@ Create a new ADR in `docs/decisions/` following MADR 4.0 format. The wr-architec
10
10
 
11
11
  ## Needs-Direction handoff + confirm-every-ADR (ADR-064)
12
12
 
13
- When a `wr-architect:agent` review returns a **NEEDS DIRECTION** verdict (a new decision with 2+ viable options and no pinned direction, per ADR-064), the option choice is the user's, not the agent's — this skill is the translation surface. The architect's named question + options become the Step 2 cat-1 `AskUserQuestion` calls (Considered Options / Decision Outcome), and the Step 5 confirm is the load-bearing **review-and-confirm-every-ADR** gate: an ADR must not stand as a human-oversighted decision (reach `accepted`) without that confirm pass. A `/wr-architect:capture-adr` skeleton — zero-ask precisely because its decision was pre-pinned in `$ARGUMENTS` — must be run through this skill's confirm before promotion to `accepted`. When direction IS already pinned (same-turn / same-session / accepted ADR / RISK-POLICY.md / CLAUDE.md mandatory rule), act on it — do not re-ask (P132 inverse-P078 guard).
13
+ When a `wr-architect:agent` review returns a **NEEDS DIRECTION** verdict (a new decision with 2+ viable options and no pinned direction, per ADR-064), the option choice is the user's, not the agent's — this skill is the translation surface. The architect's named question + options become the Step 2 cat-1 `AskUserQuestion` calls (Considered Options / Decision Outcome), and the Step 5 confirm is the load-bearing **review-and-confirm-every-ADR** gate: an ADR must not stand as a human-oversighted decision (reach `accepted`) without that confirm pass. A `/wr-architect:capture-adr` ADR — zero-ask, with its decision pre-pinned in `$ARGUMENTS` and its remaining sections silently DERIVED at capture per the ADR-032 derived-substance amendment (RFC-045) — must still have its derived substance human-ratified (via `/wr-architect:review-decisions` or this skill's confirm) before promotion to `accepted`. When direction IS already pinned (same-turn / same-session / accepted ADR / RISK-POLICY.md / CLAUDE.md mandatory rule), act on it — do not re-ask (P132 inverse-P078 guard).
14
14
 
15
15
  ## Steps
16
16
 
@@ -61,7 +61,7 @@ The advisory text shape is I2-isomorphic — same sentence structure across all
61
61
 
62
62
  **ADR-026 cost-source grounding**: each derived field cites its source in the advisory (problem-statement token sequence for Title; today's date for date / reassessment-date; default convention for status). The `re-invoke or update if mis-rated` clause carries the reversibility marker ADR-026 mandates for ungrounded outputs.
63
63
 
64
- **AFK fail-safe (ADR-013 Rule 6)**: under AFK orchestration, derivable fields (Title / status / date / reassessment-date / Context-when-prose-present) resolve without interactive input. The 6 retained cat-1 AskUserQuestion surfaces (decision-makers / Decision Drivers / Considered Options / Decision Outcome / Consequences / Confirmation) WILL halt AFK execution — that is **correct behaviour** because ADR creation is genuinely user-judgment-bound (the user authors the decision; the framework cannot). JTBD-006 protection: AFK orchestrators that need ADR creation should call `/wr-architect:capture-adr` (the lightweight aside surface) for the skeleton + Title derivation, then defer the cat-1 field collection to the user's next interactive session via the capture-adr deferred-flagged-sections mechanism.
64
+ **AFK fail-safe (ADR-013 Rule 6)**: under AFK orchestration, derivable fields (Title / status / date / reassessment-date / Context-when-prose-present) resolve without interactive input. The 6 retained cat-1 AskUserQuestion surfaces (decision-makers / Decision Drivers / Considered Options / Decision Outcome / Consequences / Confirmation) WILL halt AFK execution — that is **correct behaviour** because ADR creation is genuinely user-judgment-bound (the user authors the decision; the framework cannot). JTBD-006 protection: AFK orchestrators that need ADR creation should call `/wr-architect:capture-adr` (the lightweight aside surface), which derives ALL section content silently at capture (ADR-032 derived-substance amendment, RFC-045) and records it `human-oversight: unconfirmed`; the user ratifies or amends the derived substance at the next interactive `/wr-architect:review-decisions` drain (surfaced by the self-firing SessionStart oversight nudge). The cat-1 classification above governs THIS interactive intake surface — on the capture surface the same fields are derived-provisional-then-ratified, not asked (the ADR-067 pattern); the two surfaces do not conflict.
65
65
 
66
66
  **Cross-skill consistency note**: this is the **fourth declaration-skill surface** to ship the derive-first dispatch (after `/wr-itil:capture-problem` Step 1.5, `/wr-itil:manage-incident` Step 4, and `/wr-itil:manage-problem` Step 4 in commits b7cc645 / 43255d2 / 30fd22b). Phase 2a-iii-B (2026-05-16) closes Phase 2a's full 4-surface scope — the I2-isomorphic stderr advisory format is now locked-in across `capture-problem`, `manage-incident`, `manage-problem`, AND `create-adr` via the shared helper at `packages/shared/derive-first-dispatch.sh` with synced per-package lib/ copies. Per ADR-017, drift between copies is caught by `npm run check:derive-first-dispatch` in CI.
67
67