@windyroad/architect 0.20.3 → 0.20.4-preview.1058

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/package.json +6 -2
  4. package/agents/test/architect-codex-eval-contract.bats +0 -33
  5. package/agents/test/architect-needs-direction-verdict.bats +0 -64
  6. package/agents/test/architect-output-formatting.bats +0 -26
  7. package/agents/test/architect-performance-review.bats +0 -76
  8. package/agents/test/architect-pre-edit-review-mode.bats +0 -50
  9. package/agents/test/architect-unratified-dependency-verdict.bats +0 -55
  10. package/hooks/test/architect-compendium-update-entry.bats +0 -299
  11. package/hooks/test/architect-detect-once-per-session.bats +0 -106
  12. package/hooks/test/architect-detect-scope.bats +0 -56
  13. package/hooks/test/architect-enforce-scope.bats +0 -124
  14. package/hooks/test/architect-gate.bats +0 -102
  15. package/hooks/test/architect-mark-reviewed-verdict-grep.bats +0 -113
  16. package/hooks/test/architect-mark-reviewed.bats +0 -26
  17. package/hooks/test/architect-marker-only-exempt.bats +0 -183
  18. package/hooks/test/architect-no-stop-hook.bats +0 -17
  19. package/hooks/test/architect-oversight-marker-discipline.bats +0 -245
  20. package/hooks/test/architect-oversight-nudge.bats +0 -75
  21. package/hooks/test/architect-project-root.bats +0 -81
  22. package/hooks/test/architect-readme-pairing-check.bats +0 -126
  23. package/hooks/test/architect-slide-marker.bats +0 -92
  24. package/hooks/test/codex-agent-completion.bats +0 -64
  25. package/hooks/test/slide-marker-on-subprocess-return.bats +0 -118
  26. package/hooks/test/substance-aware-drift.bats +0 -243
  27. package/scripts/test/check-amends-backreference.bats +0 -68
  28. package/scripts/test/codex-pack-and-agent.bats +0 -86
  29. package/scripts/test/detect-unoversighted.bats +0 -139
  30. package/scripts/test/generate-decisions-compendium.bats +0 -210
  31. package/scripts/test/is-decision-unconfirmed.bats +0 -143
  32. package/skills/capture-adr/test/capture-adr.bats +0 -362
  33. package/skills/create-adr/test/create-adr-adr-044-contract.bats +0 -185
  34. package/skills/create-adr/test/create-adr-codex-eval-contract.bats +0 -34
  35. package/skills/create-adr/test/create-adr-decision-boundary.bats +0 -49
  36. package/skills/create-adr/test/create-adr-id-collision-guard.bats +0 -35
  37. package/skills/create-adr/test/create-adr-next-id-origin-lookup.bats +0 -45
  38. package/skills/create-adr/test/create-adr-rename-restage-reminder.bats +0 -38
  39. package/skills/create-adr/test/create-adr-substance-confirm-pattern.bats +0 -169
  40. package/skills/review-design/test/review-design-codex-contract.bats +0 -22
@@ -1,362 +0,0 @@
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. 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.
20
- # 3. Default reassessment-date — 3 months from today is computed
21
- # correctly and lands in frontmatter.
22
- # 4. Frontmatter derived values — decision-makers carries a real name
23
- # (git user.name), never a sentinel.
24
- #
25
- # Structural assertions are limited to existence/wiring (file presence +
26
- # frontmatter name + allowed-tools surface) per the precedent set by the
27
- # capture-problem bats fixtures (P155). Anything else asserts behaviour.
28
- #
29
- # @problem P156
30
- # @jtbd JTBD-001 (enforce governance without slowing down — lightweight
31
- # ADR-capture path)
32
- # @jtbd JTBD-005 (invoke governance assessments on demand — discoverable
33
- # via / autocomplete)
34
- # @jtbd JTBD-006 (progress backlog while AFK — mid-iter design-decision
35
- # capture in iter subprocesses)
36
- # @jtbd JTBD-101 (extend the suite — symmetric with capture-problem on
37
- # the architect plugin namespace)
38
- # @adr ADR-032 (governance skill invocation patterns — foreground-
39
- # lightweight-capture variant for capture-adr)
40
- # @adr ADR-038 (progressive disclosure — SKILL.md + REFERENCE.md split)
41
- # @adr ADR-044 (decision-delegation contract — framework-mediated
42
- # mechanical-stage carve-outs; no AskUserQuestion)
43
- # @adr ADR-049 (bin/ on PATH — capture-adr is self-contained, no shim
44
- # required, same as create-adr)
45
- # @adr ADR-052 (behavioural-tests-default — these tests exercise
46
- # primitives, not SKILL.md prose)
47
-
48
- setup() {
49
- REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../../.." && pwd)"
50
- SKILL_DIR="${REPO_ROOT}/packages/architect/skills/capture-adr"
51
- SKILL_FILE="${SKILL_DIR}/SKILL.md"
52
- REF_FILE="${SKILL_DIR}/REFERENCE.md"
53
-
54
- # Fresh per-test scratch directory.
55
- TMPROOT=$(mktemp -d)
56
- }
57
-
58
- teardown() {
59
- rm -rf "$TMPROOT"
60
- }
61
-
62
- # ---------------------------------------------------------------------------
63
- # Existence / wiring tests — minimum surface required for the skill to be
64
- # discoverable. Not structural prose-greps; these assert artefacts exist.
65
- # ---------------------------------------------------------------------------
66
-
67
- @test "capture-adr: SKILL.md and REFERENCE.md both exist (ADR-038 split)" {
68
- [ -f "$SKILL_FILE" ]
69
- [ -f "$REF_FILE" ]
70
- }
71
-
72
- @test "capture-adr: SKILL.md frontmatter declares wr-architect:capture-adr name" {
73
- # Discoverable on / autocomplete depends on the canonical name.
74
- # ADR-032 names this skill at line 81 + P156 amendment block.
75
- run grep -E '^name: wr-architect:capture-adr$' "$SKILL_FILE"
76
- [ "$status" -eq 0 ]
77
- }
78
-
79
- # ---------------------------------------------------------------------------
80
- # Next-ID computation — capture-adr reuses create-adr Step 3 formula.
81
- # P056-safe via `git ls-tree --name-only` to avoid blob-SHA false-match.
82
- # ---------------------------------------------------------------------------
83
-
84
- @test "capture-adr: next-ID formula is P056-safe (origin/local max + 1)" {
85
- # Build a fixture decisions directory with mixed status suffixes.
86
- # The formula must pick the max ID across all suffixes and zero-pad.
87
- mkdir -p "$TMPROOT/docs/decisions"
88
- : > "$TMPROOT/docs/decisions/001-foo.accepted.md"
89
- : > "$TMPROOT/docs/decisions/032-bar.proposed.md"
90
- : > "$TMPROOT/docs/decisions/057-baz.proposed.md"
91
- : > "$TMPROOT/docs/decisions/123-qux.superseded.md"
92
-
93
- # Mirror create-adr Step 3 / capture-adr Step 2 local-max formula exactly.
94
- local_max=$(ls "$TMPROOT/docs/decisions"/*.md 2>/dev/null \
95
- | sed 's/.*\///' \
96
- | grep -oE '^[0-9]+' \
97
- | sort -n | tail -1)
98
- [ "$local_max" = "123" ]
99
-
100
- # No origin available in the fixture; default to 0 then increment.
101
- next=$(printf '%03d' $(( 10#$(echo -e "${local_max:-0}\n0" | sort -n | tail -1) + 1 )))
102
- [ "$next" = "124" ]
103
- }
104
-
105
- @test "capture-adr: next-ID handles empty decisions dir (first ADR)" {
106
- mkdir -p "$TMPROOT/docs/decisions"
107
- local_max=$(ls "$TMPROOT/docs/decisions"/*.md 2>/dev/null \
108
- | sed 's/.*\///' \
109
- | grep -oE '^[0-9]+' \
110
- | sort -n | tail -1)
111
- next=$(printf '%03d' $(( 10#$(echo -e "${local_max:-0}\n0" | sort -n | tail -1) + 1 )))
112
- [ "$next" = "001" ]
113
- }
114
-
115
- @test "capture-adr: next-ID prefers origin_max when origin > local (collision guard)" {
116
- # Simulate the case where origin has a higher ADR number than local
117
- # (parallel session pushed a new ADR before this session captures).
118
- mkdir -p "$TMPROOT/docs/decisions"
119
- : > "$TMPROOT/docs/decisions/050-local.proposed.md"
120
- local_max=50
121
- origin_max=175 # parallel session pushed ADR-175
122
-
123
- next=$(printf '%03d' $(( 10#$(echo -e "${local_max:-0}\n${origin_max:-0}" | sort -n | tail -1) + 1 )))
124
- [ "$next" = "176" ]
125
- }
126
-
127
- @test "capture-adr: next-ID handles 099 → 100 transition without octal-eval failure (P164)" {
128
- # P164 regression: bash $(( ... )) parses leading-zero numbers as octal.
129
- # `099` is invalid octal (digits >= 8). Without `10#` prefix, this fires:
130
- # bash: 099: value too great for base (error token is "099")
131
- # The fix is the standard `10#` base-10 prefix on the inner $(echo ... | tail -1).
132
- mkdir -p "$TMPROOT/docs/decisions"
133
- : > "$TMPROOT/docs/decisions/098-foo.proposed.md"
134
- : > "$TMPROOT/docs/decisions/099-bar.proposed.md"
135
-
136
- local_max=$(ls "$TMPROOT/docs/decisions"/*.md 2>/dev/null \
137
- | sed 's/.*\///' \
138
- | grep -oE '^[0-9]+' \
139
- | sort -n | tail -1)
140
- [ "$local_max" = "099" ]
141
-
142
- next=$(printf '%03d' $(( 10#$(echo -e "${local_max:-0}\n0" | sort -n | tail -1) + 1 )))
143
- [ "$next" = "100" ]
144
- }
145
-
146
- # ---------------------------------------------------------------------------
147
- # Derive-fill MADR shape (RFC-045 / P375) — capture-adr writes a fully-
148
- # derived ADR at status: proposed. Load-bearing primitives:
149
- # - Title at H1
150
- # - status: proposed + human-oversight: unconfirmed in frontmatter
151
- # - decision-makers derived (real name, no sentinel)
152
- # - reassessment-date 3 months from today
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
- # ---------------------------------------------------------------------------
157
-
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
-
169
- mkdir -p "$TMPROOT/docs/decisions"
170
- TITLE="example-mid-iter-decision"
171
- ID="200"
172
- TODAY=$(date -u +%Y-%m-%d)
173
- REASSESS=$(date -u -v+3m +%Y-%m-%d 2>/dev/null || date -u -d "+3 months" +%Y-%m-%d)
174
- CONTEXT_LINE="Iter-bound design choice that needs codification."
175
- DECISION_LINE="Adopt Option A because it preserves invariants X and Y."
176
-
177
- # Mirror the SKILL.md derive-fill template with real derived content.
178
- cat > "$TMPROOT/docs/decisions/${ID}-${TITLE}.proposed.md" <<EOF
179
- ---
180
- status: "proposed"
181
- date: ${TODAY}
182
- human-oversight: unconfirmed
183
- decision-makers: [Test User]
184
- consulted: []
185
- informed: []
186
- reassessment-date: ${REASSESS}
187
- ---
188
-
189
- # ${TITLE}
190
-
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.
192
-
193
- ## Context and Problem Statement
194
-
195
- ${CONTEXT_LINE}
196
-
197
- ## Decision Drivers
198
-
199
- - Invariant X must survive iter restarts.
200
- - Option B would couple the loop to session state.
201
-
202
- ## Considered Options
203
-
204
- 1. **Option A (chosen)** — ${DECISION_LINE}
205
- 2. **Option B (session-state coupling)** — rejected: couples the loop to session state.
206
-
207
- ## Decision Outcome
208
-
209
- Chosen option: **"Option A"**, because ${DECISION_LINE}
210
-
211
- ## Consequences
212
-
213
- ### Good
214
-
215
- - Invariants X and Y hold across iters.
216
-
217
- ### Neutral
218
-
219
- - No neutral consequences identified at capture.
220
-
221
- ### Bad
222
-
223
- - One extra lookup per iter.
224
-
225
- ## Confirmation
226
-
227
- Run the iter loop twice; invariant X holds on the second run.
228
-
229
- ## Pros and Cons of the Options
230
-
231
- ### Option A
232
-
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.
240
-
241
- ## Reassessment Criteria
242
-
243
- Reopen if the extra-lookup cost exceeds one turn per iter.
244
- EOF
245
-
246
- ADR="$TMPROOT/docs/decisions/${ID}-${TITLE}.proposed.md"
247
- [ -f "$ADR" ]
248
-
249
- # Load-bearing fields present.
250
- run grep -F 'status: "proposed"' "$ADR"
251
- [ "$status" -eq 0 ]
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"
256
- [ "$status" -eq 0 ]
257
- # Title from input lands at H1.
258
- run grep -F "# ${TITLE}" "$ADR"
259
- [ "$status" -eq 0 ]
260
- # Context + Decision survive verbatim from input.
261
- run grep -F "$CONTEXT_LINE" "$ADR"
262
- [ "$status" -eq 0 ]
263
- run grep -F "$DECISION_LINE" "$ADR"
264
- [ "$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 ]
272
- }
273
-
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.
278
- mkdir -p "$TMPROOT/docs/decisions"
279
- ID="201"
280
- TITLE="another-decision"
281
-
282
- cat > "$TMPROOT/docs/decisions/${ID}-${TITLE}.proposed.md" <<'EOF'
283
- ## Considered Options
284
-
285
- 1. **Option A (chosen)** — One-line summary
286
- 2. **Status quo (do nothing)** — rejected: the symptom recurs every session
287
- EOF
288
-
289
- ADR="$TMPROOT/docs/decisions/${ID}-${TITLE}.proposed.md"
290
- # Numbered option 1 with chosen marker.
291
- run grep -F '1. **Option A (chosen)**' "$ADR"
292
- [ "$status" -eq 0 ]
293
- # Numbered option 2 is real content, not a deferral.
294
- run grep -E '^2\. \*\*' "$ADR"
295
- [ "$status" -eq 0 ]
296
- run grep -F '(deferred' "$ADR"
297
- [ "$status" -ne 0 ]
298
- }
299
-
300
- @test "capture-adr: default reassessment-date is 3 months from today (matches create-adr)" {
301
- # The 3-month default matches create-adr Step 4 default and is
302
- # framework-policy per ADR-044. Computed value lands in frontmatter.
303
- TODAY=$(date -u +%Y-%m-%d)
304
- # Compute 3 months from today using BSD date or GNU date.
305
- REASSESS=$(date -u -v+3m +%Y-%m-%d 2>/dev/null || date -u -d "+3 months" +%Y-%m-%d)
306
-
307
- # The reassess date is non-empty and parseable as YYYY-MM-DD.
308
- [ -n "$REASSESS" ]
309
- echo "$REASSESS" | grep -qE '^[0-9]{4}-[0-9]{2}-[0-9]{2}$'
310
-
311
- # The reassess date is strictly later than today (3 months ahead).
312
- [ "$REASSESS" \> "$TODAY" ]
313
- }
314
-
315
- # ---------------------------------------------------------------------------
316
- # Skill-allowed-tools surface contract — capture-adr MUST NOT carry
317
- # AskUserQuestion (per design Q4 + ADR-044 framework-mediated mechanical-
318
- # stage decisions). This is observable from the frontmatter declaration
319
- # the runtime consumes.
320
- # ---------------------------------------------------------------------------
321
-
322
- @test "capture-adr: allowed-tools omits AskUserQuestion (no interactive branches)" {
323
- # The skill's contract is NO AskUserQuestion at all — Considered Options
324
- # / Decision Drivers / Consequences / Confirmation / Reassessment are
325
- # framework-mediated mechanical stages per ADR-044. AskUserQuestion in
326
- # allowed-tools would let future drift sneak prompts back in.
327
- run grep -E '^allowed-tools:' "$SKILL_FILE"
328
- [ "$status" -eq 0 ]
329
- run grep -E '^allowed-tools:.*AskUserQuestion' "$SKILL_FILE"
330
- [ "$status" -ne 0 ]
331
- }
332
-
333
- @test "capture-adr: allowed-tools includes Bash (for next-ID + commit primitives)" {
334
- # next-ID via git ls-tree | grep | sort + commit gate via Bash invocation.
335
- run grep -E '^allowed-tools:.*Bash' "$SKILL_FILE"
336
- [ "$status" -eq 0 ]
337
- }
338
-
339
- @test "capture-adr: allowed-tools includes Write (for new ADR file)" {
340
- run grep -E '^allowed-tools:.*Write' "$SKILL_FILE"
341
- [ "$status" -eq 0 ]
342
- }
343
-
344
- # ---------------------------------------------------------------------------
345
- # Deferred-ratification contract — distinguishing capture-adr from
346
- # create-adr. capture-adr must NOT invoke the architect-agent inline; it
347
- # writes status: proposed + human-oversight: unconfirmed and defers human
348
- # ratification to the self-firing oversight drain (RFC-045).
349
- # ---------------------------------------------------------------------------
350
-
351
- @test "capture-adr: SKILL.md routes ratification to the review-decisions drain (no inline review handoff)" {
352
- # The contract distinction from create-adr: capture-adr does NOT invoke
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"
361
- [ "$status" -eq 0 ]
362
- }
@@ -1,185 +0,0 @@
1
- #!/usr/bin/env bats
2
- # ADR-044 alignment contract assertions for create-adr SKILL.md Step 2
3
- # (P132 Phase 2a-iii-B derive-first refactor, 2026-05-16).
4
- #
5
- # tdd-review: structural-permitted (justification: SKILL.md prose contract
6
- # assertions; behavioural skill-runtime harness pending P012 + P081 Phase 2;
7
- # expected to migrate to behavioural form once the harness exists. Added
8
- # during P132 Phase 2a-iii-B per the inline plan's bridge-marker rule —
9
- # isomorphic precedent at manage-problem-adr-044-step4-derive-first.bats.)
10
- #
11
- # This file is the dedicated structural-grep-permitted home for the ADR-044
12
- # alignment contract during the bridge window. After P081 Phase 2 retrofits
13
- # the project's structural-grep tests to behavioural form, this file's
14
- # assertions migrate too.
15
- #
16
- # @problem P132 (agents over-ask in interactive sessions — Phase 2a-iii-B
17
- # create-adr argument-collection derive-first refactor as 4th adopter)
18
- # @problem P185 (capture-problem Step 1.5 worked-example precedent)
19
- # @problem P136 (ADR-044 alignment audit master)
20
- # @adr ADR-002 (Monorepo per-plugin packages)
21
- # @adr ADR-017 (Shared code duplicated into per-package lib/ kept in sync)
22
- # @adr ADR-044 (Decision-Delegation Contract)
23
- # @adr ADR-013 amended Rule 1 (structured user interaction)
24
- # @adr ADR-026 (cost-source grounding — stderr advisory shape)
25
- # @adr ADR-052 (behavioural-by-default with structural bridge window)
26
- # @jtbd JTBD-001 (enforce governance without slowing down — primary)
27
- # @jtbd JTBD-006 (work backlog AFK — queued for return, not guessed at)
28
- # @jtbd JTBD-101 (extend the suite with consistent patterns)
29
-
30
- setup() {
31
- SKILL_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
32
- SKILL_FILE="${SKILL_DIR}/SKILL.md"
33
- [ -f "$SKILL_FILE" ]
34
- }
35
-
36
- # ----------------------------------------------------------------------
37
- # Step 2 derive-first refactor (P132 Phase 2a-iii-B) — cat-4 silent-framework
38
- # on Title + frontmatter defaults + Context-and-Problem-Statement; cat-1
39
- # direction-setting on Decision Drivers / Considered Options / Decision
40
- # Outcome / Consequences / Confirmation / decision-makers.
41
- # ----------------------------------------------------------------------
42
-
43
- @test "SKILL.md Step 2 cross-references ADR-044 category-4 (silent-framework) for derivable fields (P132 derive-first)" {
44
- # P132 Phase 2a-iii-B: Title (kebab from prose), status (always proposed),
45
- # date (today), reassessment-date (today+3mo), context-and-problem-statement
46
- # (verbatim from $ARGUMENTS prose) resolve via silent-framework per
47
- # ADR-044 category 4.
48
- run awk '/^### 2\. /,/^### 2b\. /' "$SKILL_FILE"
49
- [ "$status" -eq 0 ]
50
- [[ "$output" == *"silent-framework"* ]] || [[ "$output" == *"category 4"* ]] || [[ "$output" == *"category-4"* ]]
51
- }
52
-
53
- @test "SKILL.md Step 2 cross-references ADR-044 category-1 (direction-setting) for user-judgment fields" {
54
- # Decision Drivers / Considered Options / Decision Outcome / Consequences /
55
- # Confirmation retain AskUserQuestion as the genuine cat-1 surfaces —
56
- # ADR creation is fundamentally user-judgment-bound; only the user knows
57
- # the alternative space, the chosen-option rationale, and the testable
58
- # confirmation criteria.
59
- run awk '/^### 2\. /,/^### 2b\. /' "$SKILL_FILE"
60
- [ "$status" -eq 0 ]
61
- [[ "$output" == *"direction-setting"* ]] || [[ "$output" == *"category 1"* ]] || [[ "$output" == *"category-1"* ]]
62
- }
63
-
64
- @test "SKILL.md Step 2 derives Title from prose silently (P132 inverse-P078)" {
65
- # The 2026-05-06 I001 declaration regression cited in P132 was the agent
66
- # asking "Title" with N candidate options when kebab-casing the description
67
- # would have produced the slug directly. create-adr Step 2 must ship the
68
- # same derive-first pattern as the 3 itil declaration-skill surfaces.
69
- run awk '/^### 2\. /,/^### 2b\. /' "$SKILL_FILE"
70
- [ "$status" -eq 0 ]
71
- [[ "$output" == *"Title"* ]] || [[ "$output" == *"title"* ]]
72
- [[ "$output" == *"derive"* ]] || [[ "$output" == *"derived"* ]]
73
- [[ "$output" == *"kebab"* ]] || [[ "$output" == *"prose"* ]]
74
- }
75
-
76
- @test "SKILL.md Step 2 derives status / date / reassessment-date silently (P132 derive-first)" {
77
- # Frontmatter defaults (status=proposed, date=today, reassessment-date=
78
- # today+3mo) are SKILL conventions — no user judgment required at capture.
79
- # Step 4's existing template already mandates these defaults; Step 2 must
80
- # name them as silent-framework cat-4 surfaces explicitly so the
81
- # I2-isomorphic stderr advisory contract covers them.
82
- run awk '/^### 2\. /,/^### 2b\. /' "$SKILL_FILE"
83
- [ "$status" -eq 0 ]
84
- [[ "$output" == *"status"* ]]
85
- [[ "$output" == *"date"* ]]
86
- [[ "$output" == *"reassessment"* ]] || [[ "$output" == *"proposed"* ]]
87
- }
88
-
89
- @test "SKILL.md Step 2 retains Considered Options + Decision Outcome as AskUserQuestion (negative-of-negative guard)" {
90
- # Regression-resistance: the refactor MUST preserve the genuine cat-1
91
- # direction-setting surfaces on Considered Options + Decision Outcome.
92
- # The framework cannot generate the alternative space — only the user
93
- # knows the alternatives evaluated. Architect verdict 2026-05-16:
94
- # confirmed cat-1 over cat-5.
95
- run awk '/^### 2\. /,/^### 2b\. /' "$SKILL_FILE"
96
- [ "$status" -eq 0 ]
97
- [[ "$output" == *"AskUserQuestion"* ]]
98
- [[ "$output" == *"Considered Options"* ]] || [[ "$output" == *"options"* ]] || [[ "$output" == *"alternative"* ]]
99
- [[ "$output" == *"Decision Outcome"* ]] || [[ "$output" == *"chosen"* ]] || [[ "$output" == *"rationale"* ]]
100
- }
101
-
102
- @test "SKILL.md Step 2 retains decision-makers as AskUserQuestion (architect verdict — no silent derive from git user.name)" {
103
- # Architect verdict 2026-05-16: decision-makers MUST stay cat-1
104
- # AskUserQuestion. `git config user.name` would conflate "who committed
105
- # the ADR" with "who made the decision" — a multi-party decision is one
106
- # of the canonical mis-attribution risks ADR-013's identity model rejects.
107
- # Once-per-ADR ask is low-friction in absolute terms.
108
- run awk '/^### 2\. /,/^### 2b\. /' "$SKILL_FILE"
109
- [ "$status" -eq 0 ]
110
- [[ "$output" == *"decision-makers"* ]] || [[ "$output" == *"decision makers"* ]]
111
- }
112
-
113
- @test "SKILL.md Step 2 cites P132 (inverse-P078 audit traceability)" {
114
- # P132 + ADR-044 must appear in Step 2 or Related section so the audit
115
- # trail for the Phase 2a-iii-B refactor is recoverable from the SKILL.md
116
- # surface.
117
- run grep -nE "P132" "$SKILL_FILE"
118
- [ "$status" -eq 0 ]
119
- }
120
-
121
- @test "SKILL.md Step 2 documents stderr advisory shape for derived fields (ADR-026 grounding)" {
122
- # ADR-026 cost-source grounding: each silent derivation emits a stderr
123
- # advisory citing the source. Pattern parity with capture-problem Step
124
- # 1.5 + manage-incident Step 4 + manage-problem Step 4 (I2-isomorphic
125
- # across the four declaration-skill surfaces per Phase 2a-iii-B).
126
- run awk '/^### 2\. /,/^### 2b\. /' "$SKILL_FILE"
127
- [ "$status" -eq 0 ]
128
- [[ "$output" == *"stderr"* ]] || [[ "$output" == *"advisory"* ]]
129
- }
130
-
131
- @test "SKILL.md Step 2 cross-references the 3 prior derive-first surfaces (cross-skill consistency lock-in)" {
132
- # Phase 2a-iii-B is the 4th adopter. The Step 2 prose must explicitly
133
- # cite the 3 prior surfaces (capture-problem + manage-incident +
134
- # manage-problem) so the I2-isomorphic stderr advisory format is
135
- # locked-in by reference across the 4-surface set.
136
- run awk '/^### 2\. /,/^### 2b\. /' "$SKILL_FILE"
137
- [ "$status" -eq 0 ]
138
- [[ "$output" == *"capture-problem"* ]]
139
- [[ "$output" == *"manage-incident"* ]]
140
- [[ "$output" == *"manage-problem"* ]]
141
- }
142
-
143
- @test "SKILL.md Step 2 references derive-first-dispatch.sh helper (sourced from architect package per ADR-017)" {
144
- # Per ADR-017 self-contained-published-package property: create-adr lives
145
- # in @windyroad/architect, so it MUST source the helper from its own
146
- # package lib (packages/architect/lib/derive-first-dispatch.sh), NOT
147
- # cross-package from packages/itil/lib/. The canonical source lives at
148
- # packages/shared/derive-first-dispatch.sh; both itil and architect have
149
- # synced per-package lib/ copies.
150
- run grep -E "packages/architect/lib/derive-first-dispatch" "$SKILL_FILE"
151
- [ "$status" -eq 0 ]
152
- }
153
-
154
- # ----------------------------------------------------------------------
155
- # Negative-of-negative guards — Step 2b multi-decision split + Step 5
156
- # confirm-with-user remain unchanged.
157
- # ----------------------------------------------------------------------
158
-
159
- @test "SKILL.md Step 2b multi-decision AskUserQuestion is preserved (cat-1 direction-setting, not touched by Phase 2a-iii-B)" {
160
- # Step 2b is a separate cat-1 direction-setting surface — only the
161
- # user knows whether multiple decisions can be independently accepted.
162
- # The Phase 2a-iii-B refactor MUST NOT touch Step 2b's AskUserQuestion gate.
163
- run awk '/^### 2b\. /,/^### 3\. /' "$SKILL_FILE"
164
- [ "$status" -eq 0 ]
165
- [[ "$output" == *"AskUserQuestion"* ]]
166
- [[ "$output" == *"decision"* ]] || [[ "$output" == *"split"* ]]
167
- }
168
-
169
- @test "SKILL.md Step 5 confirm-with-user AskUserQuestion is preserved (post-write review surface)" {
170
- # Step 5 is the genuine cat-2 deviation-approval post-write review
171
- # surface (analogous to manage-incident Step 6 evidence-first gate).
172
- # The Phase 2a-iii-B refactor MUST NOT touch Step 5's AskUserQuestion gate.
173
- run awk '/^### 5\. /,/^### 6\. /' "$SKILL_FILE"
174
- [ "$status" -eq 0 ]
175
- [[ "$output" == *"AskUserQuestion"* ]]
176
- }
177
-
178
- # ----------------------------------------------------------------------
179
- # P081 + P132 bridge marker
180
- # ----------------------------------------------------------------------
181
-
182
- @test "bats file carries the tdd-review: structural-permitted marker" {
183
- run grep -nE "tdd-review:[[:space:]]+structural-permitted" "${BATS_TEST_FILENAME}"
184
- [ "$status" -eq 0 ]
185
- }
@@ -1,34 +0,0 @@
1
- #!/usr/bin/env bats
2
-
3
- setup() {
4
- REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../../.." && pwd)"
5
- EVAL_DIR="$REPO_ROOT/packages/architect/skills/create-adr/eval"
6
- }
7
-
8
- @test "create-adr Codex promptfoo config sits beside Claude config" {
9
- [ -f "$EVAL_DIR/promptfooconfig.yaml" ]
10
- [ -f "$EVAL_DIR/promptfooconfig.codex.yaml" ]
11
- run grep -n "run-codex-skill-eval.sh" "$EVAL_DIR/promptfooconfig.codex.yaml"
12
- [ "$status" -eq 0 ]
13
- run grep -n "grade-codex-rubric.sh" "$EVAL_DIR/promptfooconfig.codex.yaml"
14
- [ "$status" -eq 0 ]
15
- }
16
-
17
- @test "create-adr Codex eval runner uses packed installer and codex exec" {
18
- run grep -n 'npm pack' "$EVAL_DIR/run-codex-skill-eval.sh"
19
- [ "$status" -eq 0 ]
20
- run grep -n 'windyroad-architect --runtime codex --scope user' "$EVAL_DIR/run-codex-skill-eval.sh"
21
- [ "$status" -eq 0 ]
22
- run grep -n 'agents/wr-architect-agent.toml' "$EVAL_DIR/run-codex-skill-eval.sh"
23
- [ "$status" -eq 0 ]
24
- run grep -n "codex exec" "$EVAL_DIR/run-codex-skill-eval.sh"
25
- [ "$status" -eq 0 ]
26
- run grep -n -- "--ephemeral" "$EVAL_DIR/run-codex-skill-eval.sh"
27
- [ "$status" -eq 0 ]
28
- run grep -n -- 'approval_policy="never"' "$EVAL_DIR/run-codex-skill-eval.sh"
29
- [ "$status" -eq 0 ]
30
- run grep -n -- "--sandbox read-only" "$EVAL_DIR/run-codex-skill-eval.sh"
31
- [ "$status" -eq 0 ]
32
- run grep -n -- '</dev/null' "$EVAL_DIR/run-codex-skill-eval.sh"
33
- [ "$status" -eq 0 ]
34
- }
@@ -1,49 +0,0 @@
1
- #!/usr/bin/env bats
2
- # Doc-lint guard: create-adr SKILL.md must include a decision-boundary
3
- # analysis step for new ADR creation.
4
- #
5
- # Structural assertion — Permitted Exception to the source-grep ban (ADR-005 / P011).
6
- # These tests assert that the skill specification document conforms to the
7
- # decision-boundary splitting contract introduced by P017.
8
- #
9
- # Cross-reference:
10
- # P017: docs/problems/017-create-adr-should-split-multi-decision-records.open.md
11
- # ADR-013: docs/decisions/013-structured-user-interaction-for-governance-decisions.proposed.md
12
- # Sibling: packages/itil/skills/manage-problem/test/manage-problem-concern-boundary.bats (P016)
13
- # @jtbd JTBD-001 (enforce governance without slowing down)
14
- # @jtbd JTBD-101 (extend the suite with clear patterns)
15
-
16
- setup() {
17
- SKILL_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
18
- SKILL_FILE="${SKILL_DIR}/SKILL.md"
19
- }
20
-
21
- @test "SKILL.md includes a decision-boundary analysis step for new ADR creation" {
22
- # P017: Before writing an ADR file, the skill must check whether the input
23
- # contains multiple distinct decisions, and offer to split if it does.
24
- # Conflated ADRs damage auditability and block independent status transitions.
25
- run grep -in "decision.boundary\|decision-boundary\|decision boundary\|boundary.*decision\|split.*decision\|multi.decision\|single.*decision\|distinct.*decision\|decision.*distinct" "$SKILL_FILE"
26
- [ "$status" -eq 0 ]
27
- }
28
-
29
- @test "SKILL.md decision-boundary step uses AskUserQuestion for split decision (ADR-013)" {
30
- # ADR-013 Rule 1: all branch points must use AskUserQuestion, not prose options.
31
- # The "split into separate ADRs" option must be presented via AskUserQuestion.
32
- # Match: AskUserQuestion appearing in context of "split" ADR instruction.
33
- run grep -in "Split into separate\|split into.*ADR\|ADR.*split\|split.*ADR" "$SKILL_FILE"
34
- [ "$status" -eq 0 ]
35
- }
36
-
37
- @test "SKILL.md decision-boundary step specifies non-interactive auto-split fallback" {
38
- # ADR-013 Rule 6: non-interactive fail-safe — when AskUserQuestion is unavailable,
39
- # the skill must auto-split (not block/hang) for creation workflows.
40
- run grep -in "auto.split\|automatically split" "$SKILL_FILE"
41
- [ "$status" -eq 0 ]
42
- }
43
-
44
- @test "SKILL.md decision-boundary step is scoped to new ADR creation (not supersession)" {
45
- # P017 fix must only fire during new ADR creation, not during supersession handling.
46
- # Checks for explicit scope language excluding supersession from the boundary check.
47
- run grep -in "not.*supersession\|supersession.*not\|new ADR creation only\|creation only\|does not apply.*supersession\|Scoped to" "$SKILL_FILE"
48
- [ "$status" -eq 0 ]
49
- }
@@ -1,35 +0,0 @@
1
- #!/usr/bin/env bats
2
- # Doc-lint guard: create-adr SKILL.md step 3 (Determine sequence number)
3
- # must include the next-ID collision guard against origin per ADR-019
4
- # confirmation criterion 2.
5
- #
6
- # Structural assertion — Permitted Exception to the source-grep ban (ADR-005 / P011).
7
- # These tests assert that the skill specification document instructs the
8
- # ADR creator to compare next-number against origin/<base> before
9
- # assigning, so parallel sessions don't produce colliding ADR numbers.
10
- #
11
- # Cross-reference:
12
- # P043 (next-ID collision guard in ticket-creator skills)
13
- # ADR-019 (AFK orchestrator preflight, including next-ID guard)
14
-
15
- setup() {
16
- SKILL_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
17
- SKILL_FILE="${SKILL_DIR}/SKILL.md"
18
- }
19
-
20
- @test "SKILL.md cites ADR-019 (next-ID collision guard)" {
21
- run grep -n "ADR-019" "$SKILL_FILE"
22
- [ "$status" -eq 0 ]
23
- }
24
-
25
- @test "SKILL.md step 3 references git ls-tree origin for next-number lookup" {
26
- # ADR-019 mechanism: the ADR creator MUST re-check next-number against
27
- # `git ls-tree origin/<base>` before assigning.
28
- run grep -n "git ls-tree origin" "$SKILL_FILE"
29
- [ "$status" -eq 0 ]
30
- }
31
-
32
- @test "SKILL.md mentions taking the max of local and origin numbers" {
33
- run grep -niE "max of (the )?(two|local and origin)|max\(.*origin" "$SKILL_FILE"
34
- [ "$status" -eq 0 ]
35
- }