@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.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/package.json +6 -2
- package/agents/test/architect-codex-eval-contract.bats +0 -33
- package/agents/test/architect-needs-direction-verdict.bats +0 -64
- package/agents/test/architect-output-formatting.bats +0 -26
- package/agents/test/architect-performance-review.bats +0 -76
- package/agents/test/architect-pre-edit-review-mode.bats +0 -50
- package/agents/test/architect-unratified-dependency-verdict.bats +0 -55
- package/hooks/test/architect-compendium-update-entry.bats +0 -299
- package/hooks/test/architect-detect-once-per-session.bats +0 -106
- package/hooks/test/architect-detect-scope.bats +0 -56
- package/hooks/test/architect-enforce-scope.bats +0 -124
- package/hooks/test/architect-gate.bats +0 -102
- package/hooks/test/architect-mark-reviewed-verdict-grep.bats +0 -113
- package/hooks/test/architect-mark-reviewed.bats +0 -26
- package/hooks/test/architect-marker-only-exempt.bats +0 -183
- package/hooks/test/architect-no-stop-hook.bats +0 -17
- package/hooks/test/architect-oversight-marker-discipline.bats +0 -245
- package/hooks/test/architect-oversight-nudge.bats +0 -75
- package/hooks/test/architect-project-root.bats +0 -81
- package/hooks/test/architect-readme-pairing-check.bats +0 -126
- package/hooks/test/architect-slide-marker.bats +0 -92
- package/hooks/test/codex-agent-completion.bats +0 -64
- package/hooks/test/slide-marker-on-subprocess-return.bats +0 -118
- package/hooks/test/substance-aware-drift.bats +0 -243
- package/scripts/test/check-amends-backreference.bats +0 -68
- package/scripts/test/codex-pack-and-agent.bats +0 -86
- package/scripts/test/detect-unoversighted.bats +0 -139
- package/scripts/test/generate-decisions-compendium.bats +0 -210
- package/scripts/test/is-decision-unconfirmed.bats +0 -143
- package/skills/capture-adr/test/capture-adr.bats +0 -362
- package/skills/create-adr/test/create-adr-adr-044-contract.bats +0 -185
- package/skills/create-adr/test/create-adr-codex-eval-contract.bats +0 -34
- package/skills/create-adr/test/create-adr-decision-boundary.bats +0 -49
- package/skills/create-adr/test/create-adr-id-collision-guard.bats +0 -35
- package/skills/create-adr/test/create-adr-next-id-origin-lookup.bats +0 -45
- package/skills/create-adr/test/create-adr-rename-restage-reminder.bats +0 -38
- package/skills/create-adr/test/create-adr-substance-confirm-pattern.bats +0 -169
- 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
|
-
}
|