@windyroad/architect 0.3.1 → 0.3.2
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 +2 -2
- package/agents/agent.md +4 -0
- package/agents/test/architect-output-formatting.bats +26 -0
- package/hooks/architect-detect.sh +5 -1
- package/hooks/test/architect-detect-scope.bats +50 -0
- package/package.json +1 -1
- package/skills/create-adr/SKILL.md +40 -1
- package/skills/create-adr/test/create-adr-decision-boundary.bats +49 -0
- package/skills/create-adr/test/create-adr-id-collision-guard.bats +35 -0
- package/skills/review-design/SKILL.md +4 -0
package/agents/agent.md
CHANGED
|
@@ -81,6 +81,10 @@ When a change includes a new or modified decision file in `docs/decisions/`:
|
|
|
81
81
|
- Does it include reassessment criteria?
|
|
82
82
|
- If it supersedes another decision, is the old decision properly updated?
|
|
83
83
|
|
|
84
|
+
## Output Formatting
|
|
85
|
+
|
|
86
|
+
When referencing decision IDs (ADR-<NNN>), problem IDs (P<NNN>), or JTBD IDs in prose output, always include the human-readable title on first mention. Use the format `ADR-013 (Skill manifest in package.json)`, not bare `ADR-013`.
|
|
87
|
+
|
|
84
88
|
## How to Report
|
|
85
89
|
|
|
86
90
|
If the change is compliant and no new decision is needed:
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env bats
|
|
2
|
+
# Doc-lint guard: architect agent.md must include the output formatting rule
|
|
3
|
+
# requiring human-readable titles alongside bare IDs (P032).
|
|
4
|
+
#
|
|
5
|
+
# Structural assertion — Permitted Exception to the source-grep ban (ADR-005 / P011).
|
|
6
|
+
#
|
|
7
|
+
# Cross-reference:
|
|
8
|
+
# P032 (agent output uses opaque IDs without titles)
|
|
9
|
+
# @jtbd JTBD-001 (enforce governance without slowing down)
|
|
10
|
+
|
|
11
|
+
setup() {
|
|
12
|
+
AGENT_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
|
|
13
|
+
AGENT_FILE="${AGENT_DIR}/agent.md"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@test "agent.md contains output formatting section" {
|
|
17
|
+
run grep -n "## Output Formatting" "$AGENT_FILE"
|
|
18
|
+
[ "$status" -eq 0 ]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@test "agent.md output formatting rule requires titles with IDs (P032)" {
|
|
22
|
+
run grep -n "title" "$AGENT_FILE"
|
|
23
|
+
[ "$status" -eq 0 ]
|
|
24
|
+
run grep -n "Output Formatting" "$AGENT_FILE"
|
|
25
|
+
[ "$status" -eq 0 ]
|
|
26
|
+
}
|
|
@@ -35,7 +35,11 @@ REQUIRED ACTIONS:
|
|
|
35
35
|
|
|
36
36
|
SCOPE: All project files including source code, configs, CI, hooks,
|
|
37
37
|
scripts, and decisions.
|
|
38
|
-
Does NOT apply to: CSS/SCSS files, image assets, lockfiles, font files
|
|
38
|
+
Does NOT apply to: CSS/SCSS files, image assets, lockfiles, font files,
|
|
39
|
+
docs/problems/ (problem tickets), docs/BRIEFING.md, RISK-POLICY.md,
|
|
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,
|
|
42
|
+
docs/STYLE-GUIDE.md.
|
|
39
43
|
HOOK_OUTPUT
|
|
40
44
|
else
|
|
41
45
|
cat <<'HOOK_OUTPUT'
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env bats
|
|
2
|
+
|
|
3
|
+
# Tests for architect-detect.sh (UserPromptSubmit) — verifies the injected
|
|
4
|
+
# scope exclusion text lists governance docs that the PreToolUse gate already
|
|
5
|
+
# exempts (P029). Without this, the LLM wastes time delegating to the
|
|
6
|
+
# architect for files the edit gate would allow anyway.
|
|
7
|
+
|
|
8
|
+
setup() {
|
|
9
|
+
SCRIPT_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
|
|
10
|
+
HOOK="$SCRIPT_DIR/architect-detect.sh"
|
|
11
|
+
ORIG_DIR="$PWD"
|
|
12
|
+
TEST_DIR=$(mktemp -d)
|
|
13
|
+
cd "$TEST_DIR"
|
|
14
|
+
mkdir -p docs/decisions
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
teardown() {
|
|
18
|
+
cd "$ORIG_DIR"
|
|
19
|
+
rm -rf "$TEST_DIR"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@test "detect: scope text mentions problem files exemption (P029)" {
|
|
23
|
+
run bash "$HOOK"
|
|
24
|
+
[ "$status" -eq 0 ]
|
|
25
|
+
[[ "$output" == *"docs/problems/"* ]] || [[ "$output" == *"problem tickets"* ]]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@test "detect: scope text mentions BRIEFING.md exemption (P029)" {
|
|
29
|
+
run bash "$HOOK"
|
|
30
|
+
[ "$status" -eq 0 ]
|
|
31
|
+
[[ "$output" == *"BRIEFING"* ]]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@test "detect: scope text mentions RISK-POLICY exemption (P029)" {
|
|
35
|
+
run bash "$HOOK"
|
|
36
|
+
[ "$status" -eq 0 ]
|
|
37
|
+
[[ "$output" == *"RISK-POLICY"* ]]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@test "detect: scope text mentions changeset exemption (P029)" {
|
|
41
|
+
run bash "$HOOK"
|
|
42
|
+
[ "$status" -eq 0 ]
|
|
43
|
+
[[ "$output" == *"changeset"* ]]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@test "detect: scope text mentions memory files exemption (P029)" {
|
|
47
|
+
run bash "$HOOK"
|
|
48
|
+
[ "$status" -eq 0 ]
|
|
49
|
+
[[ "$output" == *"memory"* ]] || [[ "$output" == *"MEMORY"* ]]
|
|
50
|
+
}
|
package/package.json
CHANGED
|
@@ -32,12 +32,51 @@ Ask the user:
|
|
|
32
32
|
|
|
33
33
|
If the user has already provided this context in the conversation (e.g., as arguments), use what they've given and only ask about what's missing.
|
|
34
34
|
|
|
35
|
+
### 2b. Decision-boundary analysis (multi-decision check)
|
|
36
|
+
|
|
37
|
+
Before writing the ADR file, perform a decision-boundary analysis on the gathered context to prevent conflated ADRs that block independent status transitions and weaken auditability (P017).
|
|
38
|
+
|
|
39
|
+
**Self-check**: Read the context gathered in step 2. Answer: "How many distinct decisions are present? If each could be independently accepted, rejected, or superseded without affecting the others, they are distinct."
|
|
40
|
+
|
|
41
|
+
- **Single decision** (one coherent question with one chosen option): proceed directly to step 3.
|
|
42
|
+
- **Multiple decisions** (two or more distinct questions, different components, or different decision drivers that do not share the same trade-off): present a split prompt.
|
|
43
|
+
|
|
44
|
+
**Split prompt** — use `AskUserQuestion`:
|
|
45
|
+
- `header: "Multi-decision input"`
|
|
46
|
+
- `multiSelect: false`
|
|
47
|
+
- Options:
|
|
48
|
+
1. `Split into separate ADRs (Recommended)` — description: "Create one ADR per distinct decision, with consecutive IDs. Each ADR can be accepted, rejected, or superseded independently."
|
|
49
|
+
2. `Keep as a single ADR` — description: "Create one ADR covering all decisions. Use this only if the decisions are so tightly coupled that they cannot be made independently."
|
|
50
|
+
|
|
51
|
+
**Non-interactive fallback**: When `AskUserQuestion` is unavailable (e.g., non-interactive/AFK mode), automatically split into separate ADRs with consecutive IDs and note the auto-split in output. Do not block creation.
|
|
52
|
+
|
|
53
|
+
**Split implementation**: When splitting, assign consecutive IDs. Cross-reference each ADR in the other's Related section or as a linked decision in the consequences.
|
|
54
|
+
|
|
55
|
+
**Scope**: Scoped to new ADR creation only (steps 2–5). Does not apply to supersession handling (step 6), where the scope of the new decision is already known and bounded.
|
|
56
|
+
|
|
35
57
|
### 3. Determine sequence number and filename
|
|
36
58
|
|
|
37
|
-
- Next number = highest
|
|
59
|
+
- Next number = **max of the local and origin highest decision numbers**, plus 1 (or 001 if none exist).
|
|
38
60
|
- Filename: `NNN-decision-title-in-kebab-case.proposed.md`
|
|
39
61
|
- Pad the number to 3 digits (001, 002, ... 010, 011, etc.)
|
|
40
62
|
|
|
63
|
+
**Why compare against origin?** Per ADR-019 confirmation criterion 2, ticket-creator skills MUST re-check next-number assignment against `git ls-tree origin/<base>` before assigning. Without it, parallel sessions can mint the same ADR number for different decisions, causing a destructive surgical rebase on push (this was the failure mode that motivated ADR-019 itself).
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Local-max number
|
|
67
|
+
local_max=$(ls docs/decisions/*.md 2>/dev/null | sed 's/.*\///' | grep -oE '^[0-9]+' | sort -n | tail -1)
|
|
68
|
+
|
|
69
|
+
# Origin-max number — reads remote-tracking ref; no fetch needed here
|
|
70
|
+
# because `wr-architect:agent` upstream callers (e.g. work-problems) run
|
|
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)
|
|
73
|
+
|
|
74
|
+
# Take the max of the two and increment.
|
|
75
|
+
next=$(printf '%03d' $(( $(echo -e "${local_max:-0}\n${origin_max:-0}" | sort -n | tail -1) + 1 )))
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
If the local choice would have collided with an origin ADR created since the last fetch, the `git ls-tree origin/<base>` lookup catches it here and the renumber is automatic. Log the renumber in the user-facing report (e.g. "Bumped next ADR number from 020 → 021 to avoid collision with origin").
|
|
79
|
+
|
|
41
80
|
### 4. Write the ADR
|
|
42
81
|
|
|
43
82
|
Write the file to `docs/decisions/` with this structure:
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
}
|
|
@@ -17,6 +17,10 @@ This skill is **read-only**. It does not commit, push, or modify files.
|
|
|
17
17
|
- When proposing a structural change: get a review before editing architecture-bearing files
|
|
18
18
|
- Any time the hook gate is not convenient: e.g., planning mode, exploratory spikes
|
|
19
19
|
|
|
20
|
+
## Output Formatting
|
|
21
|
+
|
|
22
|
+
When referencing decision IDs (ADR-<NNN>), problem IDs (P<NNN>), or JTBD IDs in prose output, always include the human-readable title on first mention. Use the format `ADR-013 (Skill manifest in package.json)`, not bare `ADR-013`.
|
|
23
|
+
|
|
20
24
|
## Steps
|
|
21
25
|
|
|
22
26
|
### 1. Parse arguments
|