@windyroad/architect 0.5.2 → 0.6.0-preview.279
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.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +29 -0
- package/hooks/architect-detect.sh +5 -0
- package/hooks/architect-enforce-edit.sh +3 -0
- package/package.json +1 -1
- package/skills/capture-adr/REFERENCE.md +175 -0
- package/skills/capture-adr/SKILL.md +203 -0
- package/skills/capture-adr/test/capture-adr.bats +319 -0
package/README.md
CHANGED
|
@@ -35,6 +35,14 @@ Once installed, the plugin works automatically. You don't need to invoke it -- i
|
|
|
35
35
|
|
|
36
36
|
This walks you through creating an ADR in [MADR 4.0](https://adr.github.io/madr/) format. It examines your existing decisions, asks about the problem and options, and writes a properly formatted record to `docs/decisions/`.
|
|
37
37
|
|
|
38
|
+
**Capture an architecture decision in the background while staying in the main turn:**
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
/wr-architect:capture-adr
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The `capture-adr` skill is the foreground-lightweight aside-invocation variant of `create-adr` (per ADR-032 background-capture pattern). Use it when an architecture decision surfaces mid-conversation and you want the ADR scaffold drafted without losing the operational thread.
|
|
45
|
+
|
|
38
46
|
## How It Works
|
|
39
47
|
|
|
40
48
|
| Hook | Trigger | What it does |
|
|
@@ -44,6 +52,7 @@ This walks you through creating an ADR in [MADR 4.0](https://adr.github.io/madr/
|
|
|
44
52
|
| `architect-plan-enforce.sh` | ExitPlanMode | Ensures plans are reviewed before execution |
|
|
45
53
|
| `architect-mark-reviewed.sh` | Agent completes | Marks the review as done (TTL: 3600s) |
|
|
46
54
|
| `architect-refresh-hash.sh` | After edit | Refreshes the content hash so the next edit triggers a fresh review |
|
|
55
|
+
| `architect-slide-marker.sh` | Agent or Bash | Slides the review marker forward across non-edit operations so an active review session is not invalidated by intervening Bash or sub-agent calls |
|
|
47
56
|
|
|
48
57
|
## Agent
|
|
49
58
|
|
|
@@ -53,6 +62,26 @@ The `wr-architect:agent` reviews proposed changes against existing decisions in
|
|
|
53
62
|
- Whether a new ADR should be created
|
|
54
63
|
- Whether existing decisions are stale and need reassessment
|
|
55
64
|
|
|
65
|
+
## Jobs to be Done
|
|
66
|
+
|
|
67
|
+
This plugin serves the [Jobs to be Done](../../docs/jtbd/) below. Per [ADR-051](../../docs/decisions/051-jtbd-anchored-readme-with-drift-advisory.proposed.md), the persona-grouped JTBD anchor is the canonical source of truth for the README's value framing.
|
|
68
|
+
|
|
69
|
+
### Tech lead / consultant
|
|
70
|
+
|
|
71
|
+
- **[JTBD-202 Run Pre-Flight Governance Checks Before Release or Handover](../../docs/jtbd/tech-lead/JTBD-202-pre-flight-governance-check.proposed.md)** — architect review is available via `/wr-architect:review-design` for on-demand pre-flight, and via `wr-architect:agent` for automatic review on every edit.
|
|
72
|
+
|
|
73
|
+
### Solo developer
|
|
74
|
+
|
|
75
|
+
- **[JTBD-001 Enforce Governance Without Slowing Down](../../docs/jtbd/solo-developer/JTBD-001-enforce-governance.proposed.md)** — architecture decisions are reviewed automatically; the agent reads the project's existing ADRs without needing to be told what to look for.
|
|
76
|
+
|
|
77
|
+
### Plugin developer
|
|
78
|
+
|
|
79
|
+
- **[JTBD-101 Extend the Suite with New Plugins](../../docs/jtbd/plugin-developer/JTBD-101-extend-suite.proposed.md)** — `/wr-architect:create-adr` is the canonical surface for documenting structural decisions in MADR 4.0 format so contributors learn the "why" behind existing patterns.
|
|
80
|
+
|
|
81
|
+
### Plugin user
|
|
82
|
+
|
|
83
|
+
- **[JTBD-302 Trust That the README Describes the Plugin I Just Installed](../../docs/jtbd/plugin-user/JTBD-302-trust-readme-describes-installed-behaviour.proposed.md)** — this README is anchored on current JTBD job IDs; drift between prose and shipped behaviour is detectable at retro time per ADR-051.
|
|
84
|
+
|
|
56
85
|
## Updating and Uninstalling
|
|
57
86
|
|
|
58
87
|
```bash
|
|
@@ -58,6 +58,11 @@ docs/problems/ (problem tickets), docs/BRIEFING.md, docs/briefing/, RISK-POLICY.
|
|
|
58
58
|
.risk-reports/, .changeset/, memory files, plan files, docs/jtbd/,
|
|
59
59
|
docs/PRODUCT_DISCOVERY.md, docs/VOICE-AND-TONE.md,
|
|
60
60
|
docs/STYLE-GUIDE.md.
|
|
61
|
+
NOTE: these exclusions are READ tolerance — the architect gate skips
|
|
62
|
+
user edits to these paths. They are NOT agent write targets. Never
|
|
63
|
+
write project-generated artefacts (plans, audits, scratch state) under
|
|
64
|
+
.claude/ — that is user-controlled config space. Project-generated
|
|
65
|
+
content belongs under docs/ or directly in problem-ticket bodies (P131).
|
|
61
66
|
HOOK_OUTPUT
|
|
62
67
|
mark_announced "architect" "$SESSION_ID"
|
|
63
68
|
fi
|
|
@@ -54,6 +54,9 @@ case "$FILE_PATH" in
|
|
|
54
54
|
exit 0 ;;
|
|
55
55
|
*/MEMORY.md|*/.claude/projects/*/memory/*)
|
|
56
56
|
exit 0 ;;
|
|
57
|
+
# READ tolerance only — gate skips user edits to .claude/plans/. NOT a write
|
|
58
|
+
# target for agents. .claude/ is user-controlled config space; agents must not
|
|
59
|
+
# write project-generated artefacts here. See P131.
|
|
57
60
|
*/.claude/plans/*.md|*.claude/plans/*.md)
|
|
58
61
|
exit 0 ;;
|
|
59
62
|
*/RISK-POLICY.md)
|
package/package.json
CHANGED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# `/wr-architect:capture-adr` Reference
|
|
2
|
+
|
|
3
|
+
This file hosts the rationale, edge cases, contract trade-offs, and ADR cross-references for the `/wr-architect:capture-adr` skill. SKILL.md is the runtime contract (~190 lines, on-topic per ADR-038 progressive disclosure); this REFERENCE.md is the on-demand expansion for maintainers and curious users.
|
|
4
|
+
|
|
5
|
+
## Why a separate skill?
|
|
6
|
+
|
|
7
|
+
The `/wr-architect:create-adr` flow is ~10-15 turns of agent work for a full new-ADR intake: Step 1 discovery, Step 2 AskUserQuestion gathering (Title + Options ≥2 + Pros/Cons + Decision-makers + Consequences), Step 2b decision-boundary AskUserQuestion, Step 3 next-ID, Step 4 file write with full frontmatter + body, Step 5 confirm-with-user AskUserQuestion review pass, optional Step 6 supersession handling.
|
|
8
|
+
|
|
9
|
+
That cost is correct for the canonical new-ADR path — the user wants to walk the flow, see the option-comparison prompts, and codify the full MADR shape immediately.
|
|
10
|
+
|
|
11
|
+
It is wrong for the **aside-invocation** use case. P156 surfaced three repeating patterns where the heavyweight cost is load-bearing friction:
|
|
12
|
+
|
|
13
|
+
1. **Mid-AFK-iter design decisions**: agent or user lands on a design choice during a foreground iter (e.g. iter 17 P137 Option C namespace-prefix; iter 19 ADR-056 Phase 2a back-channel write contract). The 10-15 turn ceremony breaks iter cadence — decisions get buried inline in commit bodies or RCA sections.
|
|
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
|
+
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
|
+
|
|
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.
|
|
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).
|
|
24
|
+
|
|
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.
|
|
26
|
+
|
|
27
|
+
### Considered Options skeleton — `1. Option A (chosen)` + `2. (deferred — see ...)`
|
|
28
|
+
|
|
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:
|
|
30
|
+
|
|
31
|
+
```markdown
|
|
32
|
+
1. **Option A (chosen)** — <one-line summary>
|
|
33
|
+
2. (deferred — see /wr-architect:create-adr canonical review)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Avoids tripping future structural lint while preserving the lightweight-capture promise (no AskUserQuestion gathering of alternatives at capture time).
|
|
37
|
+
|
|
38
|
+
### Frontmatter sentinel values vs. truly minimal
|
|
39
|
+
|
|
40
|
+
Architect Q5 verdict: full minimum frontmatter with sentinel values is friendlier than absent fields:
|
|
41
|
+
|
|
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
|
+
```
|
|
52
|
+
|
|
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.
|
|
54
|
+
|
|
55
|
+
`reassessment-date` defaults to 3 months from today (matches `create-adr` Step 4) — the criteria themselves remain deferred-flagged in body.
|
|
56
|
+
|
|
57
|
+
### Deferred-canonical-expansion contract
|
|
58
|
+
|
|
59
|
+
Capture-adr skips the architect-agent review handoff that `/wr-architect:create-adr` Step 5 (confirm-with-user) implicitly performs. The trade-off:
|
|
60
|
+
|
|
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 |
|
|
68
|
+
|
|
69
|
+
The deferred contract is acceptable because:
|
|
70
|
+
|
|
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.
|
|
74
|
+
|
|
75
|
+
### No AskUserQuestion at all
|
|
76
|
+
|
|
77
|
+
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
|
+
|
|
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 `[unspecified — fill at canonical review]`.
|
|
83
|
+
- **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
|
+
|
|
85
|
+
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.
|
|
86
|
+
|
|
87
|
+
## Edge cases
|
|
88
|
+
|
|
89
|
+
### Empty `$ARGUMENTS`
|
|
90
|
+
|
|
91
|
+
Halt-with-stderr-directive. capture-adr requires Title + 1-line Context + 1-line Decision; without payload there is nothing to capture. The directive points the user to `/wr-architect:create-adr`, which has Step 2 AskUserQuestion gathering for full intake.
|
|
92
|
+
|
|
93
|
+
AFK orchestrators MUST NOT invoke capture-adr with empty arguments — caller-side contract. The Rule 6 audit makes this explicit so AFK-iter writers don't accidentally introduce a halt mid-loop.
|
|
94
|
+
|
|
95
|
+
### Partial `$ARGUMENTS` (Title only / Title + Decision)
|
|
96
|
+
|
|
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.
|
|
98
|
+
|
|
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.
|
|
100
|
+
|
|
101
|
+
### Title slug collision
|
|
102
|
+
|
|
103
|
+
If two captures land on the same kebab-slug (different IDs but identical title fragments), the file paths differ by ID prefix so no collision occurs at the filesystem layer. The next-ID formula guarantees ID uniqueness against local + origin.
|
|
104
|
+
|
|
105
|
+
### ID collision with origin
|
|
106
|
+
|
|
107
|
+
The next-ID formula uses `git ls-tree origin/main` to read the remote-tracking ref without requiring a fetch. If a parallel session minted the same ID for a different decision and pushed it before this session captures, the local read sees the higher origin ID and increments past it.
|
|
108
|
+
|
|
109
|
+
If the local session has not fetched recently and origin has captures the local doesn't see, the formula may still collide. The renumber audit log line in Step 6 captures the resolution. P040 incident applies.
|
|
110
|
+
|
|
111
|
+
`--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
|
+
|
|
113
|
+
### Captured ADR never expanded
|
|
114
|
+
|
|
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").
|
|
116
|
+
|
|
117
|
+
### Architect-review verdict capture
|
|
118
|
+
|
|
119
|
+
Use case: a `wr-architect:agent` review yields PASS-WITH-NOTES with substantive rationale. Pattern:
|
|
120
|
+
|
|
121
|
+
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.
|
|
125
|
+
|
|
126
|
+
This pattern preserves architect-review verdicts as first-class ADR-shaped records instead of letting them rot in commit-message bodies.
|
|
127
|
+
|
|
128
|
+
### Cross-namespace consistency with capture-problem
|
|
129
|
+
|
|
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.
|
|
131
|
+
|
|
132
|
+
## Composition with the rest of the suite
|
|
133
|
+
|
|
134
|
+
### `/wr-architect:create-adr`
|
|
135
|
+
|
|
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).
|
|
137
|
+
|
|
138
|
+
### `wr-architect:agent`
|
|
139
|
+
|
|
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.
|
|
141
|
+
|
|
142
|
+
### `/wr-itil:manage-problem` / `/wr-itil:capture-problem`
|
|
143
|
+
|
|
144
|
+
Compose with capture-adr when an iter surfaces both a problem AND a related decision. The user fires `/wr-itil:capture-problem <observation>` + `/wr-architect:capture-adr <decision>` in sequence (~6-8 turns total) instead of ~20-30 turns through the heavyweight pair.
|
|
145
|
+
|
|
146
|
+
### `/wr-itil:work-problems` (AFK orchestrator)
|
|
147
|
+
|
|
148
|
+
Iter subprocesses can invoke capture-adr to capture mid-iter design decisions without breaking iter cadence. The AFK carve-out in ADR-032 (line 85) excludes the **background-capture** variant from AFK contexts; the **foreground-lightweight-capture** variant introduced by P156 is fine inside iter subprocesses because it has no `Agent(run_in_background: true)` invocation — it is a normal foreground-synchronous skill that happens to do less work than create-adr.
|
|
149
|
+
|
|
150
|
+
### `/wr-architect:capture-adr` callers
|
|
151
|
+
|
|
152
|
+
The intended invocation surface is `/wr-architect:capture-adr <Title>\n<Context>\n<Decision>`. The payload must be non-empty; the skill does not branch on payload shape beyond the partial-payload graceful-degradation path documented under Edge cases.
|
|
153
|
+
|
|
154
|
+
## Related ADRs
|
|
155
|
+
|
|
156
|
+
- **ADR-009** — gate-marker-lifecycle (capture-adr does not write `/tmp` markers; ADR-009 referenced for pattern lineage only).
|
|
157
|
+
- **ADR-013** — structured user interaction (Rule 6 fail-safe; capture-adr has no AskUserQuestion branches so Rule 6 is trivially satisfied).
|
|
158
|
+
- **ADR-014** — governance skills commit their own work (capture-adr owns its commit).
|
|
159
|
+
- **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).
|
|
161
|
+
- **ADR-038** — progressive disclosure (SKILL.md + REFERENCE.md split shape).
|
|
162
|
+
- **ADR-044** — decision-delegation contract (framework-mediated mechanical-stage carve-outs).
|
|
163
|
+
- **ADR-049** — bin/ on PATH (capture-adr is self-contained; no new shim required, same as create-adr).
|
|
164
|
+
- **ADR-052** — behavioural-tests-default for skill testing (capture-adr's bats fixtures exercise primitives, not SKILL.md prose).
|
|
165
|
+
- **ADR-056** (`docs/decisions/056-...md` if present) — example of an inline-shipped substantive ADR that capture-adr could have skeleton-captured first.
|
|
166
|
+
|
|
167
|
+
## Related problems
|
|
168
|
+
|
|
169
|
+
- **P014** — parent / master tracker (ADR-032 children).
|
|
170
|
+
- **P088** — settled the user-direction-scoped decision: capture-problem + capture-adr are shippable; capture-retro is deferred.
|
|
171
|
+
- **P155** — sibling capture-problem skill (just shipped 2026-05-03).
|
|
172
|
+
- **P156** — driver ticket.
|
|
173
|
+
- **P157** — sibling pending-questions-surface hook.
|
|
174
|
+
- **P056** — ticket-creator next-ID lookup blob-SHA false-match (capture-adr's next-ID formula uses the `--name-only` fix).
|
|
175
|
+
- **P040** — origin-collision incident referenced in Edge cases.
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
---
|
|
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.
|
|
4
|
+
allowed-tools: Read, Write, Edit, Bash, Grep, Glob
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Capture ADR Skill
|
|
8
|
+
|
|
9
|
+
Capture an Architecture Decision Record quickly during foreground work. Lightweight aside-invocation surface that complements the heavyweight `/wr-architect:create-adr` flow. See `REFERENCE.md` in this directory for rationale, edge cases, contract trade-offs, and the ADR-032 foreground-lightweight-capture amendment.
|
|
10
|
+
|
|
11
|
+
This skill is the foreground-lightweight-capture variant of `/wr-architect:create-adr`'s new-ADR path per ADR-032 (P156 amendment, 2026-05-03). The deferred background-capture variant named in ADR-032's original taxonomy remains deferred per P088 settlement.
|
|
12
|
+
|
|
13
|
+
## When to invoke
|
|
14
|
+
|
|
15
|
+
- **Mid-iter design decision**: agent or user lands on a design choice during foreground work and cannot afford the ~10-15 turn ceremony of `/wr-architect:create-adr`.
|
|
16
|
+
- **Architect-review verdict capture**: a `wr-architect:agent` review yields a substantive PASS-WITH-NOTES / ISSUES-FOUND verdict whose rationale deserves an ADR-shaped record (today the verdict lands in commit messages and the rationale rots).
|
|
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
|
+
|
|
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).
|
|
23
|
+
|
|
24
|
+
## Rule 6 audit (per ADR-032 + ADR-013)
|
|
25
|
+
|
|
26
|
+
This skill has **zero AskUserQuestion branches** by design. Each potentially-interactive decision is framework-mediated per ADR-044:
|
|
27
|
+
|
|
28
|
+
| Decision | Resolution |
|
|
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. |
|
|
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
|
+
|
|
38
|
+
Per ADR-013 Rule 6 fail-safe: every branch above resolves without user input, so AFK and interactive contexts behave identically.
|
|
39
|
+
|
|
40
|
+
## Steps
|
|
41
|
+
|
|
42
|
+
### 1. Parse Title + 1-line Context + 1-line Decision from `$ARGUMENTS`
|
|
43
|
+
|
|
44
|
+
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
|
+
|
|
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.
|
|
47
|
+
|
|
48
|
+
Empty `$ARGUMENTS` halts per the Rule 6 audit above.
|
|
49
|
+
|
|
50
|
+
Derive a kebab-case title slug from the first 8-10 non-stopword tokens of the Title (matching the existing `create-adr` slug derivation pattern).
|
|
51
|
+
|
|
52
|
+
### 2. Compute the next ADR ID
|
|
53
|
+
|
|
54
|
+
Same P056-safe `local_max + origin_max + 1` formula as `/wr-architect:create-adr` Step 3:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
local_max=$(ls docs/decisions/*.md 2>/dev/null | sed 's/.*\///' | grep -oE '^[0-9]+' | sort -n | tail -1)
|
|
58
|
+
origin_max=$(git ls-tree --name-only origin/main docs/decisions/ 2>/dev/null | sed 's|^docs/decisions/||' | grep -oE '^[0-9]+' | sort -n | tail -1)
|
|
59
|
+
next=$(printf '%03d' $(( $(echo -e "${local_max:-0}\n${origin_max:-0}" | sort -n | tail -1) + 1 )))
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`--name-only` is required (P056): without it, each `git ls-tree` line includes the 40-char blob SHA which can contain three-digit runs that the digit-extraction regex false-matches.
|
|
63
|
+
|
|
64
|
+
Log the renumber decision in the operation report if origin and local diverged.
|
|
65
|
+
|
|
66
|
+
### 3. Skeleton-fill the MADR template
|
|
67
|
+
|
|
68
|
+
**File path**: `docs/decisions/<NNN>-<kebab-title>.proposed.md`
|
|
69
|
+
|
|
70
|
+
**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):
|
|
71
|
+
|
|
72
|
+
```markdown
|
|
73
|
+
---
|
|
74
|
+
status: "proposed"
|
|
75
|
+
date: <YYYY-MM-DD>
|
|
76
|
+
decision-makers: [unspecified — fill at canonical review]
|
|
77
|
+
consulted: []
|
|
78
|
+
informed: []
|
|
79
|
+
reassessment-date: <YYYY-MM-DD + 3 months>
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
# <Title>
|
|
83
|
+
|
|
84
|
+
> 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.
|
|
85
|
+
|
|
86
|
+
## Context and Problem Statement
|
|
87
|
+
|
|
88
|
+
<one-line Context from $ARGUMENTS, or "(deferred to /wr-architect:create-adr canonical review)" if not supplied>
|
|
89
|
+
|
|
90
|
+
## Decision Drivers
|
|
91
|
+
|
|
92
|
+
- (deferred to /wr-architect:create-adr canonical review)
|
|
93
|
+
|
|
94
|
+
## Considered Options
|
|
95
|
+
|
|
96
|
+
1. **Option A (chosen)** — <one-line summary derived from Decision in $ARGUMENTS>
|
|
97
|
+
2. (deferred — see /wr-architect:create-adr canonical review)
|
|
98
|
+
|
|
99
|
+
## Decision Outcome
|
|
100
|
+
|
|
101
|
+
Chosen option: **"Option A"**, because <one-line Decision from $ARGUMENTS, or "(deferred to /wr-architect:create-adr canonical review)" if not supplied>.
|
|
102
|
+
|
|
103
|
+
## Consequences
|
|
104
|
+
|
|
105
|
+
### Good
|
|
106
|
+
|
|
107
|
+
- (deferred to /wr-architect:create-adr canonical review)
|
|
108
|
+
|
|
109
|
+
### Neutral
|
|
110
|
+
|
|
111
|
+
- (deferred to /wr-architect:create-adr canonical review)
|
|
112
|
+
|
|
113
|
+
### Bad
|
|
114
|
+
|
|
115
|
+
- (deferred to /wr-architect:create-adr canonical review)
|
|
116
|
+
|
|
117
|
+
## Confirmation
|
|
118
|
+
|
|
119
|
+
(deferred to /wr-architect:create-adr canonical review)
|
|
120
|
+
|
|
121
|
+
## Pros and Cons of the Options
|
|
122
|
+
|
|
123
|
+
### Option A
|
|
124
|
+
|
|
125
|
+
- (deferred to /wr-architect:create-adr canonical review)
|
|
126
|
+
|
|
127
|
+
## Reassessment Criteria
|
|
128
|
+
|
|
129
|
+
(deferred to /wr-architect:create-adr canonical review — default reassessment-date 3 months from capture)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
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.
|
|
133
|
+
|
|
134
|
+
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.
|
|
135
|
+
|
|
136
|
+
### 4. Write the file
|
|
137
|
+
|
|
138
|
+
Single `Write` to `docs/decisions/<NNN>-<kebab-title>.proposed.md`.
|
|
139
|
+
|
|
140
|
+
### 5. Commit per ADR-014 — single commit, no architect-review handoff
|
|
141
|
+
|
|
142
|
+
**Stage list**: ONLY the new ADR file.
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
git add docs/decisions/<NNN>-<kebab-title>.proposed.md
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Satisfy the commit gate per ADR-014 — same two-path pattern as `manage-problem` Step 11 / `capture-problem` Step 6:
|
|
149
|
+
|
|
150
|
+
- **Primary**: delegate to subagent type `wr-risk-scorer:pipeline` via the Agent tool.
|
|
151
|
+
- **Fallback**: invoke `/wr-risk-scorer:assess-release` via the Skill tool when the subagent type is unavailable in the current tool surface.
|
|
152
|
+
|
|
153
|
+
Commit message:
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
docs(decisions): capture ADR-<NNN> <title>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
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.
|
|
160
|
+
|
|
161
|
+
### 6. Report
|
|
162
|
+
|
|
163
|
+
After the commit, report:
|
|
164
|
+
|
|
165
|
+
- The new ADR file path and ID.
|
|
166
|
+
- Trailing pointer: `Run /wr-architect:create-adr <NNN> next to expand the deferred sections canonically (Considered Options ≥2, Decision Drivers, Consequences, Confirmation, Reassessment Criteria).`
|
|
167
|
+
- Note any renumber-from-origin-collision log line from Step 2.
|
|
168
|
+
|
|
169
|
+
The trailing pointer is **not optional** — it is the user-visible signal that the skeleton needs canonical expansion before acceptance review.
|
|
170
|
+
|
|
171
|
+
## Composition with create-adr
|
|
172
|
+
|
|
173
|
+
| Concern | create-adr | capture-adr |
|
|
174
|
+
|---------|------------|-------------|
|
|
175
|
+
| Considered Options | AskUserQuestion gathering ≥2 options + pros/cons | Single-option skeleton with chosen flagged + deferred placeholder |
|
|
176
|
+
| Decision Drivers | AskUserQuestion gathering | Deferred flag |
|
|
177
|
+
| Consequences | AskUserQuestion gathering Good/Neutral/Bad | Deferred flag (Good/Neutral/Bad sections present, content deferred) |
|
|
178
|
+
| Confirmation | AskUserQuestion gathering testable criteria | Deferred flag |
|
|
179
|
+
| Reassessment criteria | AskUserQuestion gathering | 3-month default date + deferred-flag criteria |
|
|
180
|
+
| Frontmatter | Full populated frontmatter | Sentinel values (`unspecified — fill at canonical review`) + 3-month reassessment |
|
|
181
|
+
| Decision-boundary check (Step 2b) | Multi-decision split via AskUserQuestion | Out of scope (one ADR per invocation) |
|
|
182
|
+
| Supersession (Step 6) | Handles `git mv .accepted.md → .superseded.md` | Out of scope (capture is creation only) |
|
|
183
|
+
| Confirm-with-user (Step 5) | AskUserQuestion review pass | Out of scope |
|
|
184
|
+
| Commit grain | One commit per intake | One commit per capture |
|
|
185
|
+
| Use case | Full-intake new ADR; user wants to walk the flow | Aside-invocation; capture-and-continue |
|
|
186
|
+
|
|
187
|
+
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).
|
|
188
|
+
|
|
189
|
+
## Related
|
|
190
|
+
|
|
191
|
+
- **P156** (`docs/problems/156-ship-capture-adr-skill.open.md`) — driver ticket.
|
|
192
|
+
- **P014** (`docs/problems/014-aside-invocation-for-governance-skills.open.md`) — parent / master tracker.
|
|
193
|
+
- **P155** (`docs/problems/155-ship-capture-problem-skill.verifying.md`) — sibling capture-problem skill.
|
|
194
|
+
- **P157** — sibling pending-questions-surface hook.
|
|
195
|
+
- **ADR-032** (`docs/decisions/032-governance-skill-invocation-patterns.proposed.md`) — foreground-lightweight-capture variant amendment (P156 amendment, 2026-05-03).
|
|
196
|
+
- **ADR-038** — progressive-disclosure pattern (SKILL.md + REFERENCE.md split).
|
|
197
|
+
- **ADR-044** — decision-delegation contract (framework-mediated mechanical-stage carve-outs).
|
|
198
|
+
- **ADR-049** — bin/ on PATH (capture-adr is self-contained; no shim required, same as create-adr).
|
|
199
|
+
- **ADR-052** — behavioural-tests-default for skill testing.
|
|
200
|
+
- `packages/architect/skills/create-adr/SKILL.md` — heavyweight intake counterpart.
|
|
201
|
+
- `packages/architect/agents/agent.md` — wr-architect:agent review surface; reviews `.proposed.md` skeletons during canonical-expansion delegation.
|
|
202
|
+
|
|
203
|
+
$ARGUMENTS
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
#!/usr/bin/env bats
|
|
2
|
+
# Behavioural fixtures for /wr-architect:capture-adr (P156).
|
|
3
|
+
#
|
|
4
|
+
# Per ADR-052 (Behavioural-tests-default for skill testing), these tests
|
|
5
|
+
# exercise the load-bearing primitives the skill dispatches and assert
|
|
6
|
+
# observable state — NOT the prose contents of SKILL.md.
|
|
7
|
+
#
|
|
8
|
+
# Behavioural surfaces under test:
|
|
9
|
+
# 1. Next-ID computation — capture-adr reuses create-adr Step 3 P056-safe
|
|
10
|
+
# local_max + origin_max formula. Test runs the formula against a
|
|
11
|
+
# fixture decisions directory and asserts the computed next ID
|
|
12
|
+
# matches the expected zero-padded value (including the empty-dir
|
|
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.
|
|
19
|
+
# 3. Default reassessment-date — 3 months from today is computed
|
|
20
|
+
# correctly and lands in frontmatter.
|
|
21
|
+
# 4. Frontmatter sentinel values — decision-makers: [unspecified — fill
|
|
22
|
+
# at canonical review] is the framework-policy default.
|
|
23
|
+
#
|
|
24
|
+
# Structural assertions are limited to existence/wiring (file presence +
|
|
25
|
+
# frontmatter name + allowed-tools surface) per the precedent set by the
|
|
26
|
+
# capture-problem bats fixtures (P155). Anything else asserts behaviour.
|
|
27
|
+
#
|
|
28
|
+
# @problem P156
|
|
29
|
+
# @jtbd JTBD-001 (enforce governance without slowing down — lightweight
|
|
30
|
+
# ADR-capture path)
|
|
31
|
+
# @jtbd JTBD-005 (invoke governance assessments on demand — discoverable
|
|
32
|
+
# via / autocomplete)
|
|
33
|
+
# @jtbd JTBD-006 (progress backlog while AFK — mid-iter design-decision
|
|
34
|
+
# capture in iter subprocesses)
|
|
35
|
+
# @jtbd JTBD-101 (extend the suite — symmetric with capture-problem on
|
|
36
|
+
# the architect plugin namespace)
|
|
37
|
+
# @adr ADR-032 (governance skill invocation patterns — foreground-
|
|
38
|
+
# lightweight-capture variant for capture-adr)
|
|
39
|
+
# @adr ADR-038 (progressive disclosure — SKILL.md + REFERENCE.md split)
|
|
40
|
+
# @adr ADR-044 (decision-delegation contract — framework-mediated
|
|
41
|
+
# mechanical-stage carve-outs; no AskUserQuestion)
|
|
42
|
+
# @adr ADR-049 (bin/ on PATH — capture-adr is self-contained, no shim
|
|
43
|
+
# required, same as create-adr)
|
|
44
|
+
# @adr ADR-052 (behavioural-tests-default — these tests exercise
|
|
45
|
+
# primitives, not SKILL.md prose)
|
|
46
|
+
|
|
47
|
+
setup() {
|
|
48
|
+
REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../../.." && pwd)"
|
|
49
|
+
SKILL_DIR="${REPO_ROOT}/packages/architect/skills/capture-adr"
|
|
50
|
+
SKILL_FILE="${SKILL_DIR}/SKILL.md"
|
|
51
|
+
REF_FILE="${SKILL_DIR}/REFERENCE.md"
|
|
52
|
+
|
|
53
|
+
# Fresh per-test scratch directory.
|
|
54
|
+
TMPROOT=$(mktemp -d)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
teardown() {
|
|
58
|
+
rm -rf "$TMPROOT"
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# ---------------------------------------------------------------------------
|
|
62
|
+
# Existence / wiring tests — minimum surface required for the skill to be
|
|
63
|
+
# discoverable. Not structural prose-greps; these assert artefacts exist.
|
|
64
|
+
# ---------------------------------------------------------------------------
|
|
65
|
+
|
|
66
|
+
@test "capture-adr: SKILL.md and REFERENCE.md both exist (ADR-038 split)" {
|
|
67
|
+
[ -f "$SKILL_FILE" ]
|
|
68
|
+
[ -f "$REF_FILE" ]
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@test "capture-adr: SKILL.md frontmatter declares wr-architect:capture-adr name" {
|
|
72
|
+
# Discoverable on / autocomplete depends on the canonical name.
|
|
73
|
+
# ADR-032 names this skill at line 81 + P156 amendment block.
|
|
74
|
+
run grep -E '^name: wr-architect:capture-adr$' "$SKILL_FILE"
|
|
75
|
+
[ "$status" -eq 0 ]
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
# ---------------------------------------------------------------------------
|
|
79
|
+
# Next-ID computation — capture-adr reuses create-adr Step 3 formula.
|
|
80
|
+
# P056-safe via `git ls-tree --name-only` to avoid blob-SHA false-match.
|
|
81
|
+
# ---------------------------------------------------------------------------
|
|
82
|
+
|
|
83
|
+
@test "capture-adr: next-ID formula is P056-safe (origin/local max + 1)" {
|
|
84
|
+
# Build a fixture decisions directory with mixed status suffixes.
|
|
85
|
+
# The formula must pick the max ID across all suffixes and zero-pad.
|
|
86
|
+
mkdir -p "$TMPROOT/docs/decisions"
|
|
87
|
+
: > "$TMPROOT/docs/decisions/001-foo.accepted.md"
|
|
88
|
+
: > "$TMPROOT/docs/decisions/032-bar.proposed.md"
|
|
89
|
+
: > "$TMPROOT/docs/decisions/057-baz.proposed.md"
|
|
90
|
+
: > "$TMPROOT/docs/decisions/123-qux.superseded.md"
|
|
91
|
+
|
|
92
|
+
# Mirror create-adr Step 3 / capture-adr Step 2 local-max formula exactly.
|
|
93
|
+
local_max=$(ls "$TMPROOT/docs/decisions"/*.md 2>/dev/null \
|
|
94
|
+
| sed 's/.*\///' \
|
|
95
|
+
| grep -oE '^[0-9]+' \
|
|
96
|
+
| sort -n | tail -1)
|
|
97
|
+
[ "$local_max" = "123" ]
|
|
98
|
+
|
|
99
|
+
# No origin available in the fixture; default to 0 then increment.
|
|
100
|
+
next=$(printf '%03d' $(( $(echo -e "${local_max:-0}\n0" | sort -n | tail -1) + 1 )))
|
|
101
|
+
[ "$next" = "124" ]
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@test "capture-adr: next-ID handles empty decisions dir (first ADR)" {
|
|
105
|
+
mkdir -p "$TMPROOT/docs/decisions"
|
|
106
|
+
local_max=$(ls "$TMPROOT/docs/decisions"/*.md 2>/dev/null \
|
|
107
|
+
| sed 's/.*\///' \
|
|
108
|
+
| grep -oE '^[0-9]+' \
|
|
109
|
+
| sort -n | tail -1)
|
|
110
|
+
next=$(printf '%03d' $(( $(echo -e "${local_max:-0}\n0" | sort -n | tail -1) + 1 )))
|
|
111
|
+
[ "$next" = "001" ]
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@test "capture-adr: next-ID prefers origin_max when origin > local (collision guard)" {
|
|
115
|
+
# Simulate the case where origin has a higher ADR number than local
|
|
116
|
+
# (parallel session pushed a new ADR before this session captures).
|
|
117
|
+
mkdir -p "$TMPROOT/docs/decisions"
|
|
118
|
+
: > "$TMPROOT/docs/decisions/050-local.proposed.md"
|
|
119
|
+
local_max=50
|
|
120
|
+
origin_max=175 # parallel session pushed ADR-175
|
|
121
|
+
|
|
122
|
+
next=$(printf '%03d' $(( $(echo -e "${local_max:-0}\n${origin_max:-0}" | sort -n | tail -1) + 1 )))
|
|
123
|
+
[ "$next" = "176" ]
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
# ---------------------------------------------------------------------------
|
|
127
|
+
# Skeleton-fill MADR shape — capture-adr writes a deferred-placeholder ADR
|
|
128
|
+
# at status: proposed. Load-bearing primitives:
|
|
129
|
+
# - Title at H1
|
|
130
|
+
# - status: proposed in frontmatter
|
|
131
|
+
# - decision-makers sentinel
|
|
132
|
+
# - reassessment-date 3 months from today
|
|
133
|
+
# - Numbered-options placeholder (1. chosen + 2. deferred) — preserves
|
|
134
|
+
# MADR ≥2-options surface for any doc-lint assertion.
|
|
135
|
+
# - Literal pointer string `(deferred to /wr-architect:create-adr
|
|
136
|
+
# canonical review)` — this is the canonical-expansion detection key.
|
|
137
|
+
# ---------------------------------------------------------------------------
|
|
138
|
+
|
|
139
|
+
@test "capture-adr: skeleton-filled ADR carries deferred-flag literal pointer string" {
|
|
140
|
+
# The literal `(deferred to /wr-architect:create-adr canonical review)`
|
|
141
|
+
# is the load-bearing canonical-expansion detection signal. Any future
|
|
142
|
+
# auto-detect-and-expand path will key off this string.
|
|
143
|
+
mkdir -p "$TMPROOT/docs/decisions"
|
|
144
|
+
TITLE="example-mid-iter-decision"
|
|
145
|
+
ID="200"
|
|
146
|
+
TODAY=$(date -u +%Y-%m-%d)
|
|
147
|
+
REASSESS=$(date -u -v+3m +%Y-%m-%d 2>/dev/null || date -u -d "+3 months" +%Y-%m-%d)
|
|
148
|
+
CONTEXT_LINE="Iter-bound design choice that needs codification."
|
|
149
|
+
DECISION_LINE="Adopt Option A because it preserves invariants X and Y."
|
|
150
|
+
|
|
151
|
+
# Mirror the SKILL.md skeleton-fill template.
|
|
152
|
+
cat > "$TMPROOT/docs/decisions/${ID}-${TITLE}.proposed.md" <<EOF
|
|
153
|
+
---
|
|
154
|
+
status: "proposed"
|
|
155
|
+
date: ${TODAY}
|
|
156
|
+
decision-makers: [unspecified — fill at canonical review]
|
|
157
|
+
consulted: []
|
|
158
|
+
informed: []
|
|
159
|
+
reassessment-date: ${REASSESS}
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
# ${TITLE}
|
|
163
|
+
|
|
164
|
+
> 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.
|
|
165
|
+
|
|
166
|
+
## Context and Problem Statement
|
|
167
|
+
|
|
168
|
+
${CONTEXT_LINE}
|
|
169
|
+
|
|
170
|
+
## Decision Drivers
|
|
171
|
+
|
|
172
|
+
- (deferred to /wr-architect:create-adr canonical review)
|
|
173
|
+
|
|
174
|
+
## Considered Options
|
|
175
|
+
|
|
176
|
+
1. **Option A (chosen)** — ${DECISION_LINE}
|
|
177
|
+
2. (deferred — see /wr-architect:create-adr canonical review)
|
|
178
|
+
|
|
179
|
+
## Decision Outcome
|
|
180
|
+
|
|
181
|
+
Chosen option: **"Option A"**, because ${DECISION_LINE}
|
|
182
|
+
|
|
183
|
+
## Consequences
|
|
184
|
+
|
|
185
|
+
### Good
|
|
186
|
+
|
|
187
|
+
- (deferred to /wr-architect:create-adr canonical review)
|
|
188
|
+
|
|
189
|
+
### Neutral
|
|
190
|
+
|
|
191
|
+
- (deferred to /wr-architect:create-adr canonical review)
|
|
192
|
+
|
|
193
|
+
### Bad
|
|
194
|
+
|
|
195
|
+
- (deferred to /wr-architect:create-adr canonical review)
|
|
196
|
+
|
|
197
|
+
## Confirmation
|
|
198
|
+
|
|
199
|
+
(deferred to /wr-architect:create-adr canonical review)
|
|
200
|
+
|
|
201
|
+
## Pros and Cons of the Options
|
|
202
|
+
|
|
203
|
+
### Option A
|
|
204
|
+
|
|
205
|
+
- (deferred to /wr-architect:create-adr canonical review)
|
|
206
|
+
|
|
207
|
+
## Reassessment Criteria
|
|
208
|
+
|
|
209
|
+
(deferred to /wr-architect:create-adr canonical review — default reassessment-date 3 months from capture)
|
|
210
|
+
EOF
|
|
211
|
+
|
|
212
|
+
ADR="$TMPROOT/docs/decisions/${ID}-${TITLE}.proposed.md"
|
|
213
|
+
[ -f "$ADR" ]
|
|
214
|
+
|
|
215
|
+
# Behavioural assertions: load-bearing fields present.
|
|
216
|
+
run grep -F 'status: "proposed"' "$ADR"
|
|
217
|
+
[ "$status" -eq 0 ]
|
|
218
|
+
# Decision-makers sentinel for canonical-review fill.
|
|
219
|
+
run grep -F 'decision-makers: [unspecified — fill at canonical review]' "$ADR"
|
|
220
|
+
[ "$status" -eq 0 ]
|
|
221
|
+
# Title from input lands at H1.
|
|
222
|
+
run grep -F "# ${TITLE}" "$ADR"
|
|
223
|
+
[ "$status" -eq 0 ]
|
|
224
|
+
# Context survives verbatim from input.
|
|
225
|
+
run grep -F "$CONTEXT_LINE" "$ADR"
|
|
226
|
+
[ "$status" -eq 0 ]
|
|
227
|
+
# Decision survives verbatim from input.
|
|
228
|
+
run grep -F "$DECISION_LINE" "$ADR"
|
|
229
|
+
[ "$status" -eq 0 ]
|
|
230
|
+
# Deferred-flag literal pointer string — canonical-expansion detection key.
|
|
231
|
+
run grep -F '(deferred to /wr-architect:create-adr canonical review)' "$ADR"
|
|
232
|
+
[ "$status" -eq 0 ]
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
@test "capture-adr: skeleton has numbered-options placeholder (1. chosen + 2. deferred)" {
|
|
236
|
+
# MADR ≥2-options surface preserved at skeleton time so any doc-lint
|
|
237
|
+
# asserting numbered-option presence does not fire on capture-adr output.
|
|
238
|
+
# Architect Q2 verdict: write literal placeholder, defer enforcement.
|
|
239
|
+
mkdir -p "$TMPROOT/docs/decisions"
|
|
240
|
+
ID="201"
|
|
241
|
+
TITLE="another-decision"
|
|
242
|
+
|
|
243
|
+
cat > "$TMPROOT/docs/decisions/${ID}-${TITLE}.proposed.md" <<'EOF'
|
|
244
|
+
## Considered Options
|
|
245
|
+
|
|
246
|
+
1. **Option A (chosen)** — One-line summary
|
|
247
|
+
2. (deferred — see /wr-architect:create-adr canonical review)
|
|
248
|
+
EOF
|
|
249
|
+
|
|
250
|
+
ADR="$TMPROOT/docs/decisions/${ID}-${TITLE}.proposed.md"
|
|
251
|
+
# Numbered option 1 with chosen marker.
|
|
252
|
+
run grep -F '1. **Option A (chosen)**' "$ADR"
|
|
253
|
+
[ "$status" -eq 0 ]
|
|
254
|
+
# Numbered option 2 with deferred marker.
|
|
255
|
+
run grep -F '2. (deferred — see /wr-architect:create-adr canonical review)' "$ADR"
|
|
256
|
+
[ "$status" -eq 0 ]
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
@test "capture-adr: default reassessment-date is 3 months from today (matches create-adr)" {
|
|
260
|
+
# The 3-month default matches create-adr Step 4 default and is
|
|
261
|
+
# framework-policy per ADR-044. Computed value lands in frontmatter.
|
|
262
|
+
TODAY=$(date -u +%Y-%m-%d)
|
|
263
|
+
# Compute 3 months from today using BSD date or GNU date.
|
|
264
|
+
REASSESS=$(date -u -v+3m +%Y-%m-%d 2>/dev/null || date -u -d "+3 months" +%Y-%m-%d)
|
|
265
|
+
|
|
266
|
+
# The reassess date is non-empty and parseable as YYYY-MM-DD.
|
|
267
|
+
[ -n "$REASSESS" ]
|
|
268
|
+
echo "$REASSESS" | grep -qE '^[0-9]{4}-[0-9]{2}-[0-9]{2}$'
|
|
269
|
+
|
|
270
|
+
# The reassess date is strictly later than today (3 months ahead).
|
|
271
|
+
[ "$REASSESS" \> "$TODAY" ]
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
# ---------------------------------------------------------------------------
|
|
275
|
+
# Skill-allowed-tools surface contract — capture-adr MUST NOT carry
|
|
276
|
+
# AskUserQuestion (per design Q4 + ADR-044 framework-mediated mechanical-
|
|
277
|
+
# stage decisions). This is observable from the frontmatter declaration
|
|
278
|
+
# the runtime consumes.
|
|
279
|
+
# ---------------------------------------------------------------------------
|
|
280
|
+
|
|
281
|
+
@test "capture-adr: allowed-tools omits AskUserQuestion (no interactive branches)" {
|
|
282
|
+
# The skill's contract is NO AskUserQuestion at all — Considered Options
|
|
283
|
+
# / Decision Drivers / Consequences / Confirmation / Reassessment are
|
|
284
|
+
# framework-mediated mechanical stages per ADR-044. AskUserQuestion in
|
|
285
|
+
# allowed-tools would let future drift sneak prompts back in.
|
|
286
|
+
run grep -E '^allowed-tools:' "$SKILL_FILE"
|
|
287
|
+
[ "$status" -eq 0 ]
|
|
288
|
+
run grep -E '^allowed-tools:.*AskUserQuestion' "$SKILL_FILE"
|
|
289
|
+
[ "$status" -ne 0 ]
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
@test "capture-adr: allowed-tools includes Bash (for next-ID + commit primitives)" {
|
|
293
|
+
# next-ID via git ls-tree | grep | sort + commit gate via Bash invocation.
|
|
294
|
+
run grep -E '^allowed-tools:.*Bash' "$SKILL_FILE"
|
|
295
|
+
[ "$status" -eq 0 ]
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
@test "capture-adr: allowed-tools includes Write (for new ADR file)" {
|
|
299
|
+
run grep -E '^allowed-tools:.*Write' "$SKILL_FILE"
|
|
300
|
+
[ "$status" -eq 0 ]
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
# ---------------------------------------------------------------------------
|
|
304
|
+
# Deferred-canonical-expansion contract — distinguishing capture-adr from
|
|
305
|
+
# create-adr. capture-adr must NOT invoke the architect-agent inline; it
|
|
306
|
+
# writes status: proposed and defers review to canonical expansion.
|
|
307
|
+
# This is the contract distinction from create-adr Step 5 (confirm-with-user).
|
|
308
|
+
# ---------------------------------------------------------------------------
|
|
309
|
+
|
|
310
|
+
@test "capture-adr: SKILL.md prescribes deferred canonical expansion (no inline review handoff)" {
|
|
311
|
+
# The contract distinction from create-adr: capture-adr does NOT invoke
|
|
312
|
+
# the wr-architect:agent review inline; it writes status: proposed and
|
|
313
|
+
# routes review through the canonical-expansion path. A future
|
|
314
|
+
# maintainer who copies create-adr's Step 5 confirm pass into capture-adr
|
|
315
|
+
# would break the lightweight-capture promise.
|
|
316
|
+
# Asserts the SKILL.md names the deferred contract explicitly.
|
|
317
|
+
run grep -F '/wr-architect:create-adr' "$SKILL_FILE"
|
|
318
|
+
[ "$status" -eq 0 ]
|
|
319
|
+
}
|