@windyroad/architect 0.4.0 → 0.4.1

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.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "wr-architect",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Architecture decision enforcement for Claude Code"
5
5
  }
@@ -38,7 +38,7 @@ scripts, and decisions.
38
38
  Does NOT apply to: CSS/SCSS files, image assets, lockfiles, font files,
39
39
  docs/problems/ (problem tickets), docs/BRIEFING.md, RISK-POLICY.md,
40
40
  .risk-reports/, .changeset/, memory files, plan files, docs/jtbd/,
41
- docs/JOBS_TO_BE_DONE.md, docs/PRODUCT_DISCOVERY.md, docs/VOICE-AND-TONE.md,
41
+ docs/PRODUCT_DISCOVERY.md, docs/VOICE-AND-TONE.md,
42
42
  docs/STYLE-GUIDE.md.
43
43
  HOOK_OUTPUT
44
44
  else
@@ -65,8 +65,6 @@ case "$FILE_PATH" in
65
65
  */docs/problems/*.md|docs/problems/*.md)
66
66
  exit 0 ;;
67
67
  # Peer-plugin policy files — governed by their own plugin's enforce hook, not architect (P009)
68
- */docs/JOBS_TO_BE_DONE.md|docs/JOBS_TO_BE_DONE.md)
69
- exit 0 ;;
70
68
  */docs/PRODUCT_DISCOVERY.md|docs/PRODUCT_DISCOVERY.md)
71
69
  exit 0 ;;
72
70
  */docs/jtbd/*|docs/jtbd/*)
@@ -41,8 +41,14 @@ assert_path_allowed() {
41
41
  [[ "$output" != *"BLOCKED"* ]]
42
42
  }
43
43
 
44
- @test "architect: exempts JTBD policy file (P009)" {
45
- assert_path_allowed "$PWD/docs/JOBS_TO_BE_DONE.md"
44
+ @test "architect: does NOT exempt legacy docs/JOBS_TO_BE_DONE.md (ADR-008 Option 3, P019)" {
45
+ # Legacy single-file path is no longer a recognised peer-plugin policy
46
+ # artefact — ADR-008 Option 3 removes it from runtime consideration.
47
+ # The architect gate treats it as ordinary content and applies its
48
+ # normal review rules.
49
+ run run_hook_with_file "$PWD/docs/JOBS_TO_BE_DONE.md"
50
+ [ "$status" -eq 0 ]
51
+ [[ "$output" == *"BLOCKED"* ]]
46
52
  }
47
53
 
48
54
  @test "architect: exempts JTBD directory file (P009)" {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/architect",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Architecture decision enforcement for AI coding agents",
5
5
  "bin": {
6
6
  "windyroad-architect": "./bin/install.mjs"
@@ -69,7 +69,13 @@ local_max=$(ls docs/decisions/*.md 2>/dev/null | sed 's/.*\///' | grep -oE '^[0-
69
69
  # Origin-max number — reads remote-tracking ref; no fetch needed here
70
70
  # because `wr-architect:agent` upstream callers (e.g. work-problems) run
71
71
  # the Step 0 preflight that does the fetch.
72
- origin_max=$(git ls-tree origin/main docs/decisions/ 2>/dev/null | grep -oE '[0-9]{3}' | sort -n | tail -1)
72
+ #
73
+ # `--name-only` is required (P056): without it, each ls-tree line is
74
+ # `<mode> <type> <sha>\t<path>` and the 40-char blob SHA can contain
75
+ # three-digit runs that `grep -oE '[0-9]{3}'` false-matches. `sed` strips
76
+ # the path prefix so the anchored `grep -oE '^[0-9]+'` only picks up
77
+ # filename IDs.
78
+ 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)
73
79
 
74
80
  # Take the max of the two and increment.
75
81
  next=$(printf '%03d' $(( $(echo -e "${local_max:-0}\n${origin_max:-0}" | sort -n | tail -1) + 1 )))
@@ -161,8 +167,9 @@ Apply any feedback by editing the file.
161
167
 
162
168
  If the user mentions this decision replaces an existing one:
163
169
  1. Add `supersedes: [NNN-old-decision-title]` to the new decision's frontmatter
164
- 2. Rename the old decision file from `.accepted.md` (or `.proposed.md`) to `.superseded.md`
170
+ 2. Rename the old decision file from `.accepted.md` (or `.proposed.md`) to `.superseded.md` using `git mv`
165
171
  3. Update the old decision's frontmatter status to `superseded`
166
172
  4. Add a "Superseded by" section to the old decision referencing the new one
173
+ 5. **Re-stage the renamed file explicitly after the `Edit` tool runs**: `git add docs/decisions/<NNN>-<title>.superseded.md`. `git mv` stages only the rename — the subsequent frontmatter and "Superseded by" edits must be added again before commit, or they leak into the next commit (P057 staging trap).
167
174
 
168
175
  $ARGUMENTS
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env bats
2
+ # Doc-lint guard: create-adr SKILL.md Step 3 origin-max lookup must use
3
+ # `git ls-tree --name-only` to avoid false-matching blob SHA digits (P056).
4
+ #
5
+ # Structural assertion — Permitted Exception to the source-grep ban
6
+ # (ADR-005 / P011). Same defect as manage-problem: default `git ls-tree`
7
+ # output carries a 40-char blob SHA that can contain three-digit runs,
8
+ # which `grep -oE '[0-9]{3}'` picks up as a false origin_max. `--name-only`
9
+ # restores the invariant ADR-019 presumes.
10
+ #
11
+ # Cross-reference:
12
+ # P056: docs/problems/056-ticket-creator-next-id-lookup-blob-sha-false-match.*.md
13
+ # P043 (closed): next-ID collision guard in ticket-creator skills
14
+ # ADR-019: docs/decisions/019-afk-orchestrator-preflight.*.md
15
+ # @jtbd JTBD-002 (ship with confidence — audit trail)
16
+
17
+ setup() {
18
+ TEST_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")" && pwd)"
19
+ REPO_ROOT="$(cd "${TEST_DIR}/../../../../.." && pwd)"
20
+ SKILL_FILE="${REPO_ROOT}/packages/architect/skills/create-adr/SKILL.md"
21
+ }
22
+
23
+ @test "create-adr SKILL.md exists (P056 precondition)" {
24
+ [ -f "$SKILL_FILE" ]
25
+ }
26
+
27
+ @test "create-adr SKILL.md origin-max lookup uses git ls-tree --name-only (P056)" {
28
+ # The fix: `git ls-tree --name-only` drops mode/type/SHA columns so the
29
+ # digit-extraction regex cannot match SHA hex runs.
30
+ run grep -nE "git ls-tree --name-only .* docs/decisions" "$SKILL_FILE"
31
+ [ "$status" -eq 0 ]
32
+ }
33
+
34
+ @test "create-adr SKILL.md does not keep the buggy bare git ls-tree pattern (P056)" {
35
+ # Regression guard: `git ls-tree <ref> docs/decisions/` without `--name-only`
36
+ # piped directly into a digit regex is the bug.
37
+ run grep -nE "git ls-tree [^-].* docs/decisions/ .*\| *grep -oE '\[0-9\]\{3\}'" "$SKILL_FILE"
38
+ [ "$status" -ne 0 ]
39
+ }
40
+
41
+ @test "create-adr SKILL.md cites P056 on the origin-max fix (P056)" {
42
+ # Traceability.
43
+ run grep -n "P056" "$SKILL_FILE"
44
+ [ "$status" -eq 0 ]
45
+ }
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env bats
2
+ # Doc-lint guard: create-adr SKILL.md must document the re-stage-after-Edit
3
+ # requirement for ADR supersession renames (Step 6).
4
+ #
5
+ # Structural assertion — Permitted Exception to the source-grep ban
6
+ # (ADR-005 / P011). The test asserts that the supersession step either
7
+ # warns authors that `git mv` stages only the rename, or instructs them
8
+ # to re-stage the file after editing frontmatter + "Superseded by" section.
9
+ #
10
+ # Cross-reference:
11
+ # P057: docs/problems/057-git-mv-plus-edit-staging-ordering-trap.*.md
12
+ # ADR-014: docs/decisions/014-governance-skills-commit-their-own-work.proposed.md
13
+ # @jtbd JTBD-002 (ship with confidence — audit trail)
14
+
15
+ setup() {
16
+ TEST_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")" && pwd)"
17
+ REPO_ROOT="$(cd "${TEST_DIR}/../../../../.." && pwd)"
18
+ SKILL_FILE="${REPO_ROOT}/packages/architect/skills/create-adr/SKILL.md"
19
+ }
20
+
21
+ @test "create-adr SKILL.md exists (P057 precondition)" {
22
+ [ -f "$SKILL_FILE" ]
23
+ }
24
+
25
+ @test "create-adr SKILL.md instructs re-staging the renamed ADR file after Edit (P057)" {
26
+ # Authors must be told to run `git add <new>` (or equivalent) after editing
27
+ # the renamed file (supersession adds a `Superseded by` section and a status
28
+ # frontmatter update).
29
+ run grep -inE "re-stage|re‑stage|\`git add\`.*after|after.*\`git add\`|git add <new>|git add .*\.superseded\.md|stages only the rename" "$SKILL_FILE"
30
+ [ "$status" -eq 0 ]
31
+ }
32
+
33
+ @test "create-adr SKILL.md cites P057 on the re-stage requirement (P057)" {
34
+ # Traceability: the new guidance must cite P057 so reviewers can chase
35
+ # the fix back to the incident that motivated it.
36
+ run grep -n "P057" "$SKILL_FILE"
37
+ [ "$status" -eq 0 ]
38
+ }