@windyroad/architect 0.1.2 → 0.1.3-preview.27
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/README.md +66 -0
- package/agents/agent.md +1 -13
- package/hooks/architect-mark-reviewed.sh +17 -14
- package/hooks/lib/architect-gate.sh +1 -1
- package/hooks/test/architect-gate.bats +32 -0
- package/hooks/test/architect-mark-reviewed.bats +26 -0
- package/package.json +1 -1
- package/skills/{wr:adr → create-adr}/SKILL.md +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# @windyroad/architect
|
|
2
|
+
|
|
3
|
+
**Architecture decision enforcement for Claude Code.** Ensures every code change is reviewed against your project's architecture decisions before it lands.
|
|
4
|
+
|
|
5
|
+
Part of [Windy Road Agent Plugins](../../README.md).
|
|
6
|
+
|
|
7
|
+
## What It Does
|
|
8
|
+
|
|
9
|
+
The architect plugin prevents architectural drift by gating edits behind an architecture review. When you have a `docs/decisions/` directory, the plugin:
|
|
10
|
+
|
|
11
|
+
1. **Detects** your architecture decisions on every prompt
|
|
12
|
+
2. **Blocks** edits to project files until the architect agent has reviewed the proposed changes
|
|
13
|
+
3. **Reviews** changes against your existing ADRs (Architecture Decision Records) and flags conflicts
|
|
14
|
+
4. **Flags** when a new decision should be documented
|
|
15
|
+
|
|
16
|
+
No decisions directory yet? The plugin stays silent until you create one.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx @windyroad/architect
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Restart Claude Code after installing.
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
Once installed, the plugin works automatically. You don't need to invoke it -- it intercepts edits and runs the review before allowing changes through.
|
|
29
|
+
|
|
30
|
+
**Create a new Architecture Decision Record:**
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
/wr-architect:create-adr
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
This walks you through creating an ADR in [MADR 4.0](https://adr.github.io/madr/) format. It examines your existing decisions, asks about the problem and options, and writes a properly formatted record to `docs/decisions/`.
|
|
37
|
+
|
|
38
|
+
## How It Works
|
|
39
|
+
|
|
40
|
+
| Hook | Trigger | What it does |
|
|
41
|
+
|------|---------|-------------|
|
|
42
|
+
| `architect-detect.sh` | Every prompt | Checks for `docs/decisions/` and injects the review instruction |
|
|
43
|
+
| `architect-enforce-edit.sh` | Edit or Write | Blocks the edit if the architect hasn't reviewed yet |
|
|
44
|
+
| `architect-plan-enforce.sh` | ExitPlanMode | Ensures plans are reviewed before execution |
|
|
45
|
+
| `architect-mark-reviewed.sh` | Agent completes | Marks the review as done (TTL: 1800s) |
|
|
46
|
+
| `architect-refresh-hash.sh` | After edit | Refreshes the content hash so the next edit triggers a fresh review |
|
|
47
|
+
| `architect-reset-marker.sh` | Session end | Cleans up review markers |
|
|
48
|
+
|
|
49
|
+
## Agent
|
|
50
|
+
|
|
51
|
+
The `wr-architect:agent` reviews proposed changes against existing decisions in `docs/decisions/` and reports:
|
|
52
|
+
|
|
53
|
+
- Whether changes comply with or violate existing decisions
|
|
54
|
+
- Whether a new ADR should be created
|
|
55
|
+
- Whether existing decisions are stale and need reassessment
|
|
56
|
+
|
|
57
|
+
## Updating and Uninstalling
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npx @windyroad/architect --update
|
|
61
|
+
npx @windyroad/architect --uninstall
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Licence
|
|
65
|
+
|
|
66
|
+
[MIT](../../LICENSE)
|
package/agents/agent.md
CHANGED
|
@@ -10,7 +10,6 @@ tools:
|
|
|
10
10
|
- Read
|
|
11
11
|
- Glob
|
|
12
12
|
- Grep
|
|
13
|
-
- Bash
|
|
14
13
|
model: inherit
|
|
15
14
|
---
|
|
16
15
|
|
|
@@ -107,20 +106,9 @@ Issue types:
|
|
|
107
106
|
- **[Missing Supersession]**: A new decision should supersede an old one but doesn't
|
|
108
107
|
- **[Confirmation Violation]**: New code violates a confirmation criterion of an existing decision
|
|
109
108
|
|
|
110
|
-
## Verdict File
|
|
111
|
-
|
|
112
|
-
After completing your review, you MUST write a verdict file so the hook system knows the outcome:
|
|
113
|
-
|
|
114
|
-
- After **PASS**: `echo "PASS" > /tmp/architect-verdict`
|
|
115
|
-
- After **ISSUES FOUND**: `echo "FAIL" > /tmp/architect-verdict`
|
|
116
|
-
|
|
117
|
-
Advisory items (staleness flags) do NOT count as FAIL. Only write FAIL when there are actionable issues (Decision Conflict, Undocumented Decision, Decision Format, Missing Supersession, Confirmation Violation).
|
|
118
|
-
|
|
119
|
-
You MUST NOT use Bash for anything other than writing the verdict file.
|
|
120
|
-
|
|
121
109
|
## Constraints
|
|
122
110
|
|
|
123
|
-
- You are read-only. You do not edit files
|
|
111
|
+
- You are read-only. You do not edit files.
|
|
124
112
|
- You review all project files: source code, configuration, CI workflows, hook scripts, build scripts, and decision files. The only exclusions are stylesheets, images, lockfiles, and font files.
|
|
125
113
|
- If the change is purely cosmetic (comments, formatting, whitespace), report PASS.
|
|
126
114
|
- Do not block changes that are clearly within the scope of an existing accepted decision.
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# Architecture - PostToolUse hook for Agent tool
|
|
3
3
|
# Creates a session marker when architect has been consulted.
|
|
4
|
+
# Parses verdict from agent output text (session-safe, no temp files).
|
|
4
5
|
# This marker unlocks the architect-enforce-edit.sh PreToolUse block.
|
|
5
|
-
# Mirrors: voice-tone-mark-reviewed.sh
|
|
6
6
|
|
|
7
|
-
# Source shared portable helpers (_mtime, _hashcmd)
|
|
8
7
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
9
8
|
source "$SCRIPT_DIR/lib/gate-helpers.sh"
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
_parse_input
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
TOOL_NAME=$(_get_tool_name)
|
|
13
|
+
[ "$TOOL_NAME" = "Agent" ] || exit 0
|
|
14
|
+
|
|
15
|
+
SUBAGENT=$(_get_subagent_type)
|
|
16
|
+
SESSION_ID=$(_get_session_id)
|
|
15
17
|
|
|
16
18
|
if [ -z "$SESSION_ID" ]; then
|
|
17
19
|
exit 0
|
|
@@ -19,25 +21,24 @@ fi
|
|
|
19
21
|
|
|
20
22
|
case "$SUBAGENT" in
|
|
21
23
|
*architect*)
|
|
22
|
-
#
|
|
23
|
-
|
|
24
|
+
# Parse verdict from agent output text (no temp file needed)
|
|
25
|
+
AGENT_OUTPUT=$(_get_tool_output)
|
|
24
26
|
VERDICT=""
|
|
25
|
-
if
|
|
26
|
-
VERDICT
|
|
27
|
-
|
|
27
|
+
if echo "$AGENT_OUTPUT" | grep -q "Architecture Review: PASS"; then
|
|
28
|
+
VERDICT="PASS"
|
|
29
|
+
elif echo "$AGENT_OUTPUT" | grep -q "ISSUES FOUND"; then
|
|
30
|
+
VERDICT="FAIL"
|
|
28
31
|
fi
|
|
29
32
|
|
|
30
33
|
case "$VERDICT" in
|
|
31
34
|
PASS)
|
|
32
|
-
# Architect explicitly passed, create marker
|
|
33
35
|
touch "/tmp/architect-reviewed-${SESSION_ID}"
|
|
34
36
|
;;
|
|
35
37
|
FAIL)
|
|
36
|
-
#
|
|
38
|
+
# Do NOT create marker — review found issues
|
|
37
39
|
;;
|
|
38
40
|
*)
|
|
39
|
-
#
|
|
40
|
-
# Allow with warning to avoid permanent lockout
|
|
41
|
+
# Could not parse verdict — allow with marker to avoid lockout
|
|
41
42
|
touch "/tmp/architect-reviewed-${SESSION_ID}"
|
|
42
43
|
;;
|
|
43
44
|
esac
|
|
@@ -52,6 +53,8 @@ case "$SUBAGENT" in
|
|
|
52
53
|
echo "$HASH" > "/tmp/architect-reviewed-${SESSION_ID}.hash"
|
|
53
54
|
fi
|
|
54
55
|
|
|
56
|
+
# Plan review marker
|
|
57
|
+
touch "/tmp/architect-plan-reviewed-${SESSION_ID}"
|
|
55
58
|
;;
|
|
56
59
|
esac
|
|
57
60
|
|
|
@@ -12,7 +12,7 @@ source "$_ARCHITECT_GATE_DIR/gate-helpers.sh"
|
|
|
12
12
|
check_architect_gate() {
|
|
13
13
|
local SESSION_ID="$1"
|
|
14
14
|
local MARKER="/tmp/architect-reviewed-${SESSION_ID}"
|
|
15
|
-
local TTL_SECONDS="${ARCHITECT_TTL:-
|
|
15
|
+
local TTL_SECONDS="${ARCHITECT_TTL:-1800}"
|
|
16
16
|
|
|
17
17
|
if [ -n "$SESSION_ID" ] && [ -f "$MARKER" ]; then
|
|
18
18
|
local NOW=$(date +%s)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env bats
|
|
2
|
+
|
|
3
|
+
# Tests for architect-gate.sh (TTL, drift, marker)
|
|
4
|
+
|
|
5
|
+
setup() {
|
|
6
|
+
SCRIPT_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
|
|
7
|
+
source "$SCRIPT_DIR/lib/architect-gate.sh"
|
|
8
|
+
TEST_SESSION="test-$$-$BATS_TEST_NUMBER"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
teardown() {
|
|
12
|
+
rm -f "/tmp/architect-reviewed-${TEST_SESSION}"
|
|
13
|
+
rm -f "/tmp/architect-reviewed-${TEST_SESSION}.hash"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@test "gate denies when no marker exists" {
|
|
17
|
+
run check_architect_gate "$TEST_SESSION"
|
|
18
|
+
[ "$status" -ne 0 ]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@test "gate allows when marker exists and is fresh" {
|
|
22
|
+
touch "/tmp/architect-reviewed-${TEST_SESSION}"
|
|
23
|
+
run check_architect_gate "$TEST_SESSION"
|
|
24
|
+
[ "$status" -eq 0 ]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@test "gate denies when marker is expired" {
|
|
28
|
+
touch "/tmp/architect-reviewed-${TEST_SESSION}"
|
|
29
|
+
# Set TTL to 0 to force expiry
|
|
30
|
+
ARCHITECT_TTL=0 run check_architect_gate "$TEST_SESSION"
|
|
31
|
+
[ "$status" -ne 0 ]
|
|
32
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env bats
|
|
2
|
+
|
|
3
|
+
# Tests for architect verdict parsing from output text
|
|
4
|
+
|
|
5
|
+
@test "grep matches 'Architecture Review: PASS'" {
|
|
6
|
+
output="Some preamble text\n\n**Architecture Review: PASS**\n\nNo conflicts."
|
|
7
|
+
echo -e "$output" | grep -q "Architecture Review: PASS"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@test "grep matches 'ISSUES FOUND'" {
|
|
11
|
+
output="**Architecture Review: ISSUES FOUND**\n\n1. [Decision Conflict]"
|
|
12
|
+
echo -e "$output" | grep -q "ISSUES FOUND"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@test "grep does NOT match unrelated text" {
|
|
16
|
+
output="The review is complete. Everything looks good."
|
|
17
|
+
! echo -e "$output" | grep -q "Architecture Review: PASS"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@test "subagent pattern matches wr-architect:agent" {
|
|
21
|
+
SUBAGENT="wr-architect:agent"
|
|
22
|
+
case "$SUBAGENT" in
|
|
23
|
+
*architect*) true ;;
|
|
24
|
+
*) false ;;
|
|
25
|
+
esac
|
|
26
|
+
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: wr:adr
|
|
2
|
+
name: wr-architect:create-adr
|
|
3
3
|
description: Create a new Architecture Decision Record (MADR 4.0) in docs/decisions/. Examines existing decisions, asks about the problem and options, and writes a properly formatted ADR.
|
|
4
4
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion
|
|
5
5
|
---
|