@windyroad/architect 0.8.0 → 0.9.0-preview.412
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/README.md +17 -20
- package/bin/wr-architect-detect-unoversighted +3 -0
- package/hooks/architect-oversight-nudge.sh +46 -0
- package/hooks/hooks.json +3 -0
- package/hooks/test/architect-oversight-nudge.bats +70 -0
- package/package.json +2 -1
- package/scripts/detect-unoversighted.sh +51 -0
- package/scripts/test/detect-unoversighted.bats +99 -0
- package/skills/create-adr/SKILL.md +9 -0
- package/skills/review-decisions/SKILL.md +74 -0
package/README.md
CHANGED
|
@@ -43,6 +43,22 @@ This walks you through creating an ADR in [MADR 4.0](https://adr.github.io/madr/
|
|
|
43
43
|
|
|
44
44
|
The `capture-adr` skill is the foreground-lightweight aside-invocation variant of `create-adr` (per ADR-032 background-capture pattern). Use it when an architecture decision surfaces mid-conversation and you want the ADR scaffold drafted without losing the operational thread.
|
|
45
45
|
|
|
46
|
+
**Review recorded decisions that lack human oversight:**
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
/wr-architect:review-decisions
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The `review-decisions` skill drains the set of ADRs that were recorded without a human confirming the chosen option (per ADR-066). It surfaces each decision's chosen option and alternatives via AskUserQuestion so you confirm, amend, or reject the auto-made call, then writes a `human-oversight: confirmed` marker. Detection is a token-cheap grep over ADR frontmatter; a session-start nudge reports the unoversighted count. New ADRs created through `create-adr` are born oversighted, so the unconfirmed set only shrinks.
|
|
53
|
+
|
|
54
|
+
**Run an on-demand architecture compliance review:**
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
/wr-architect:review-design
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The `review-design` skill checks staged changes and recent commits against the existing ADRs in `docs/decisions/` — a pre-flight you can run before editing architecture-bearing files or cutting a release, without waiting for the per-edit gate.
|
|
61
|
+
|
|
46
62
|
## How It Works
|
|
47
63
|
|
|
48
64
|
| Hook | Trigger | What it does |
|
|
@@ -53,6 +69,7 @@ The `capture-adr` skill is the foreground-lightweight aside-invocation variant o
|
|
|
53
69
|
| `architect-mark-reviewed.sh` | Agent completes | Marks the review as done (TTL: 3600s) |
|
|
54
70
|
| `architect-refresh-hash.sh` | After edit | Refreshes the content hash so the next edit triggers a fresh review |
|
|
55
71
|
| `architect-slide-marker.sh` | Agent or Bash | Slides the review marker forward across non-edit operations so an active review session is not invalidated by intervening Bash or sub-agent calls |
|
|
72
|
+
| `architect-oversight-nudge.sh` | Session start | Reports how many recorded decisions lack human oversight and points to `/wr-architect:review-decisions`; silent when none, and self-suppressed inside AFK iterations |
|
|
56
73
|
|
|
57
74
|
## Agent
|
|
58
75
|
|
|
@@ -62,26 +79,6 @@ The `wr-architect:agent` reviews proposed changes against existing decisions in
|
|
|
62
79
|
- Whether a new ADR should be created
|
|
63
80
|
- Whether existing decisions are stale and need reassessment
|
|
64
81
|
|
|
65
|
-
## Jobs to be Done
|
|
66
|
-
|
|
67
|
-
This plugin serves the [Jobs to be Done](../../docs/jtbd/) below. Per [ADR-051](../../docs/decisions/051-jtbd-anchored-readme-with-drift-advisory.proposed.md), the persona-grouped JTBD anchor is the canonical source of truth for the README's value framing.
|
|
68
|
-
|
|
69
|
-
### Tech lead / consultant
|
|
70
|
-
|
|
71
|
-
- **[JTBD-202 Run Pre-Flight Governance Checks Before Release or Handover](../../docs/jtbd/tech-lead/JTBD-202-pre-flight-governance-check.proposed.md)** — architect review is available via `/wr-architect:review-design` for on-demand pre-flight, and via `wr-architect:agent` for automatic review on every edit.
|
|
72
|
-
|
|
73
|
-
### Solo developer
|
|
74
|
-
|
|
75
|
-
- **[JTBD-001 Enforce Governance Without Slowing Down](../../docs/jtbd/solo-developer/JTBD-001-enforce-governance.proposed.md)** — architecture decisions are reviewed automatically; the agent reads the project's existing ADRs without needing to be told what to look for.
|
|
76
|
-
|
|
77
|
-
### Plugin developer
|
|
78
|
-
|
|
79
|
-
- **[JTBD-101 Extend the Suite with New Plugins](../../docs/jtbd/plugin-developer/JTBD-101-extend-suite.proposed.md)** — `/wr-architect:create-adr` is the canonical surface for documenting structural decisions in MADR 4.0 format so contributors learn the "why" behind existing patterns.
|
|
80
|
-
|
|
81
|
-
### Plugin user
|
|
82
|
-
|
|
83
|
-
- **[JTBD-302 Trust That the README Describes the Plugin I Just Installed](../../docs/jtbd/plugin-user/JTBD-302-trust-readme-describes-installed-behaviour.proposed.md)** — this README is anchored on current JTBD job IDs; drift between prose and shipped behaviour is detectable at retro time per ADR-051.
|
|
84
|
-
|
|
85
82
|
## Updating and Uninstalling
|
|
86
83
|
|
|
87
84
|
```bash
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# wr-architect — SessionStart hook (ADR-066)
|
|
3
|
+
#
|
|
4
|
+
# Surfaces a one-line nudge when recorded decisions (ADRs) lack the
|
|
5
|
+
# human-oversight marker, so the user can drain them via
|
|
6
|
+
# /wr-architect:review-decisions. Modelled on the ADR-040 session-start
|
|
7
|
+
# briefing surface and packages/itil/hooks/itil-pending-questions-surface.sh.
|
|
8
|
+
#
|
|
9
|
+
# Detection is token-cheap: it delegates to detect-unoversighted.sh (a grep
|
|
10
|
+
# over ADR frontmatter — no body reads, no per-ADR LLM call). Silent when the
|
|
11
|
+
# unoversighted count is zero (steady state once the set is drained).
|
|
12
|
+
#
|
|
13
|
+
# AFK self-suppress (JTBD-006 friction guard): AFK orchestrators set
|
|
14
|
+
# WR_SUPPRESS_OVERSIGHT_NUDGE=1 before spawning each `claude -p` iteration so
|
|
15
|
+
# this interactive batch-confirm nudge never fires into an absent-user
|
|
16
|
+
# subprocess (the same discipline itil-pending-questions-surface.sh applies
|
|
17
|
+
# with WR_SUPPRESS_PENDING_QUESTIONS). Only the literal "1" suppresses.
|
|
18
|
+
|
|
19
|
+
set -euo pipefail
|
|
20
|
+
|
|
21
|
+
if [ "${WR_SUPPRESS_OVERSIGHT_NUDGE:-}" = "1" ]; then
|
|
22
|
+
exit 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-.}"
|
|
26
|
+
DECISIONS_DIR="$PROJECT_DIR/docs/decisions"
|
|
27
|
+
|
|
28
|
+
# Silent when this project has no decision records.
|
|
29
|
+
[ -d "$DECISIONS_DIR" ] || exit 0
|
|
30
|
+
|
|
31
|
+
DETECT="${CLAUDE_PLUGIN_ROOT:-$(dirname "$0")/..}/scripts/detect-unoversighted.sh"
|
|
32
|
+
[ -x "$DETECT" ] || DETECT="$(dirname "$0")/../scripts/detect-unoversighted.sh"
|
|
33
|
+
|
|
34
|
+
# Count unoversighted ADRs. `grep -c .` counts non-empty lines; tolerate the
|
|
35
|
+
# detector printing nothing (count 0).
|
|
36
|
+
COUNT="$(bash "$DETECT" "$DECISIONS_DIR" 2>/dev/null | grep -c . || true)"
|
|
37
|
+
COUNT="${COUNT:-0}"
|
|
38
|
+
|
|
39
|
+
# Silent-on-no-content per ADR-040 Mechanism step 1.
|
|
40
|
+
[ "$COUNT" -gt 0 ] 2>/dev/null || exit 0
|
|
41
|
+
|
|
42
|
+
if [ "$COUNT" -eq 1 ]; then
|
|
43
|
+
echo "[wr-architect] 1 recorded decision lacks human oversight — run /wr-architect:review-decisions to confirm it."
|
|
44
|
+
else
|
|
45
|
+
echo "[wr-architect] $COUNT recorded decisions lack human oversight — run /wr-architect:review-decisions to confirm them."
|
|
46
|
+
fi
|
package/hooks/hooks.json
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"hooks": {
|
|
3
|
+
"SessionStart": [
|
|
4
|
+
{ "matcher": "startup", "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/architect-oversight-nudge.sh" }] }
|
|
5
|
+
],
|
|
3
6
|
"UserPromptSubmit": [
|
|
4
7
|
{ "hooks": [{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/architect-detect.sh" }] }
|
|
5
8
|
],
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env bats
|
|
2
|
+
|
|
3
|
+
# ADR-066: architect-oversight-nudge.sh (SessionStart) emits a one-line nudge
|
|
4
|
+
# when ADRs lack the human-oversight marker, is silent when none do, and
|
|
5
|
+
# self-suppresses under the AFK guard (WR_SUPPRESS_OVERSIGHT_NUDGE=1) so the
|
|
6
|
+
# interactive batch-confirm never fires into an absent-user iteration (JTBD-006).
|
|
7
|
+
# Behavioural — exercises the hook against fixture trees and asserts on stdout.
|
|
8
|
+
|
|
9
|
+
setup() {
|
|
10
|
+
REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../.." && pwd)"
|
|
11
|
+
HOOK="$REPO_ROOT/packages/architect/hooks/architect-oversight-nudge.sh"
|
|
12
|
+
PLUGIN_ROOT="$REPO_ROOT/packages/architect"
|
|
13
|
+
DIR="$(mktemp -d)"
|
|
14
|
+
mkdir -p "$DIR/docs/decisions"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
teardown() {
|
|
18
|
+
rm -rf "$DIR"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
mk_unmarked() {
|
|
22
|
+
{ echo "---"; echo "status: \"proposed\""; echo "date: 2026-05-25"; echo "---"; echo "# $1"; } \
|
|
23
|
+
> "$DIR/docs/decisions/$1"
|
|
24
|
+
}
|
|
25
|
+
mk_marked() {
|
|
26
|
+
{ echo "---"; echo "status: \"proposed\""; echo "date: 2026-05-25"; echo "human-oversight: confirmed"; echo "---"; echo "# $1"; } \
|
|
27
|
+
> "$DIR/docs/decisions/$1"
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@test "emits a count line when there are unoversighted ADRs" {
|
|
31
|
+
mk_unmarked "010-a.proposed.md"
|
|
32
|
+
mk_unmarked "011-b.proposed.md"
|
|
33
|
+
run env CLAUDE_PROJECT_DIR="$DIR" CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" bash "$HOOK"
|
|
34
|
+
[ "$status" -eq 0 ]
|
|
35
|
+
[[ "$output" == *"2 recorded decisions lack human oversight"* ]]
|
|
36
|
+
[[ "$output" == *"/wr-architect:review-decisions"* ]]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@test "uses singular wording for exactly one unoversighted ADR" {
|
|
40
|
+
mk_unmarked "010-a.proposed.md"
|
|
41
|
+
run env CLAUDE_PROJECT_DIR="$DIR" CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" bash "$HOOK"
|
|
42
|
+
[[ "$output" == *"1 recorded decision lacks human oversight"* ]]
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@test "silent when every ADR is confirmed" {
|
|
46
|
+
mk_marked "010-a.proposed.md"
|
|
47
|
+
run env CLAUDE_PROJECT_DIR="$DIR" CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" bash "$HOOK"
|
|
48
|
+
[ "$status" -eq 0 ]
|
|
49
|
+
[ -z "$output" ]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@test "AFK guard suppresses the nudge entirely" {
|
|
53
|
+
mk_unmarked "010-a.proposed.md"
|
|
54
|
+
run env WR_SUPPRESS_OVERSIGHT_NUDGE=1 CLAUDE_PROJECT_DIR="$DIR" CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" bash "$HOOK"
|
|
55
|
+
[ "$status" -eq 0 ]
|
|
56
|
+
[ -z "$output" ]
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@test "guard value other than 1 does not suppress" {
|
|
60
|
+
mk_unmarked "010-a.proposed.md"
|
|
61
|
+
mk_unmarked "011-b.proposed.md"
|
|
62
|
+
run env WR_SUPPRESS_OVERSIGHT_NUDGE=0 CLAUDE_PROJECT_DIR="$DIR" CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" bash "$HOOK"
|
|
63
|
+
[[ "$output" == *"lack human oversight"* ]]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@test "silent when project has no docs/decisions dir" {
|
|
67
|
+
run env CLAUDE_PROJECT_DIR="$DIR/empty" CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" bash "$HOOK"
|
|
68
|
+
[ "$status" -eq 0 ]
|
|
69
|
+
[ -z "$output" ]
|
|
70
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@windyroad/architect",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0-preview.412",
|
|
4
4
|
"description": "Architecture decision enforcement for AI coding agents",
|
|
5
5
|
"bin": {
|
|
6
6
|
"windyroad-architect": "./bin/install.mjs"
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"agents/",
|
|
24
24
|
"hooks/",
|
|
25
25
|
"skills/",
|
|
26
|
+
"scripts/",
|
|
26
27
|
".claude-plugin/",
|
|
27
28
|
"lib/"
|
|
28
29
|
]
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# wr-architect — detect ADRs lacking the human-oversight marker (ADR-066)
|
|
3
|
+
#
|
|
4
|
+
# Token-cheap detection: greps each ADR's YAML frontmatter for the presence of
|
|
5
|
+
# `human-oversight: confirmed`. No body reads, no per-ADR LLM call. An ADR is
|
|
6
|
+
# "unoversighted" when its frontmatter does not carry that marker line (or has
|
|
7
|
+
# no frontmatter at all).
|
|
8
|
+
#
|
|
9
|
+
# Usage:
|
|
10
|
+
# detect-unoversighted.sh [DECISIONS_DIR]
|
|
11
|
+
# DECISIONS_DIR defaults to docs/decisions
|
|
12
|
+
#
|
|
13
|
+
# Output: one unoversighted ADR file path per line, sorted. Empty output = the
|
|
14
|
+
# whole set is confirmed. Callers derive the count with `grep -c .` / `wc -l`.
|
|
15
|
+
# Always exits 0 (it is a detector, not a gate).
|
|
16
|
+
#
|
|
17
|
+
# Consumed by: architect-oversight-nudge.sh (SessionStart count) and
|
|
18
|
+
# /wr-architect:review-decisions (the drain list). Marker contract: ADR-066.
|
|
19
|
+
|
|
20
|
+
set -euo pipefail
|
|
21
|
+
|
|
22
|
+
DECISIONS_DIR="${1:-docs/decisions}"
|
|
23
|
+
|
|
24
|
+
[ -d "$DECISIONS_DIR" ] || exit 0
|
|
25
|
+
|
|
26
|
+
# Match both the flat layout (docs/decisions/*.md) and any per-state subdir
|
|
27
|
+
# layout an adopter might introduce later (docs/decisions/*/*.md). README is
|
|
28
|
+
# never a decision record.
|
|
29
|
+
shopt -s nullglob
|
|
30
|
+
for f in "$DECISIONS_DIR"/*.md "$DECISIONS_DIR"/*/*.md; do
|
|
31
|
+
base="$(basename "$f")"
|
|
32
|
+
[ "$base" = "README.md" ] && continue
|
|
33
|
+
# Superseded decisions are retired — a newer ADR replaced them. Confirming a
|
|
34
|
+
# dead decision has no value, so they are not part of the "needs oversight"
|
|
35
|
+
# set (keeps the nudge count and the drain queue focused on live decisions).
|
|
36
|
+
case "$base" in *.superseded.md) continue ;; esac
|
|
37
|
+
|
|
38
|
+
# Extract the frontmatter block: lines between the leading `---` and the
|
|
39
|
+
# next `---`. If line 1 is not `---`, the file has no frontmatter and the
|
|
40
|
+
# awk prints nothing → treated as unoversighted.
|
|
41
|
+
fm="$(awk '
|
|
42
|
+
NR==1 && $0 != "---" { exit }
|
|
43
|
+
NR==1 { next }
|
|
44
|
+
/^---[[:space:]]*$/ { exit }
|
|
45
|
+
{ print }
|
|
46
|
+
' "$f")"
|
|
47
|
+
|
|
48
|
+
if ! printf '%s\n' "$fm" | grep -qiE '^human-oversight:[[:space:]]*confirmed[[:space:]]*$'; then
|
|
49
|
+
echo "$f"
|
|
50
|
+
fi
|
|
51
|
+
done | sort
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env bats
|
|
2
|
+
|
|
3
|
+
# ADR-066: detect-unoversighted.sh prints ADRs whose frontmatter lacks the
|
|
4
|
+
# `human-oversight: confirmed` marker. Behavioural — exercises the script
|
|
5
|
+
# against fixture trees and asserts on its stdout, not its source text.
|
|
6
|
+
|
|
7
|
+
setup() {
|
|
8
|
+
REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../.." && pwd)"
|
|
9
|
+
SCRIPT="$REPO_ROOT/packages/architect/scripts/detect-unoversighted.sh"
|
|
10
|
+
DIR="$(mktemp -d)"
|
|
11
|
+
mkdir -p "$DIR/docs/decisions"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
teardown() {
|
|
15
|
+
rm -rf "$DIR"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
mk() { # mk <filename> <frontmatter-extra-lines...>
|
|
19
|
+
local name="$1"; shift
|
|
20
|
+
{
|
|
21
|
+
echo "---"
|
|
22
|
+
echo "status: \"proposed\""
|
|
23
|
+
echo "date: 2026-05-25"
|
|
24
|
+
for line in "$@"; do echo "$line"; done
|
|
25
|
+
echo "---"
|
|
26
|
+
echo "# $name"
|
|
27
|
+
} > "$DIR/docs/decisions/$name"
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@test "an ADR without the marker is reported" {
|
|
31
|
+
mk "010-no-marker.proposed.md"
|
|
32
|
+
run bash "$SCRIPT" "$DIR/docs/decisions"
|
|
33
|
+
[ "$status" -eq 0 ]
|
|
34
|
+
[[ "$output" == *"010-no-marker.proposed.md"* ]]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@test "an ADR carrying human-oversight: confirmed is NOT reported" {
|
|
38
|
+
mk "011-confirmed.proposed.md" "human-oversight: confirmed" "oversight-date: 2026-05-25"
|
|
39
|
+
run bash "$SCRIPT" "$DIR/docs/decisions"
|
|
40
|
+
[ "$status" -eq 0 ]
|
|
41
|
+
[[ "$output" != *"011-confirmed.proposed.md"* ]]
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@test "marker match is case-insensitive and tolerant of trailing space" {
|
|
45
|
+
mk "012-spacey.proposed.md" "human-oversight: confirmed "
|
|
46
|
+
run bash "$SCRIPT" "$DIR/docs/decisions"
|
|
47
|
+
[[ "$output" != *"012-spacey.proposed.md"* ]]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@test "README.md is never reported" {
|
|
51
|
+
echo "# index" > "$DIR/docs/decisions/README.md"
|
|
52
|
+
run bash "$SCRIPT" "$DIR/docs/decisions"
|
|
53
|
+
[[ "$output" != *"README.md"* ]]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@test "superseded ADRs are excluded even without the marker" {
|
|
57
|
+
mk "013-old.superseded.md"
|
|
58
|
+
run bash "$SCRIPT" "$DIR/docs/decisions"
|
|
59
|
+
[[ "$output" != *"013-old.superseded.md"* ]]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@test "a file with no frontmatter counts as unoversighted" {
|
|
63
|
+
echo "# bare ADR, no frontmatter" > "$DIR/docs/decisions/014-bare.proposed.md"
|
|
64
|
+
run bash "$SCRIPT" "$DIR/docs/decisions"
|
|
65
|
+
[[ "$output" == *"014-bare.proposed.md"* ]]
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@test "a body line that looks like the marker does not count (frontmatter only)" {
|
|
69
|
+
{
|
|
70
|
+
echo "---"
|
|
71
|
+
echo "status: \"proposed\""
|
|
72
|
+
echo "date: 2026-05-25"
|
|
73
|
+
echo "---"
|
|
74
|
+
echo "# 015"
|
|
75
|
+
echo "human-oversight: confirmed" # in body, not frontmatter
|
|
76
|
+
} > "$DIR/docs/decisions/015-body-trick.proposed.md"
|
|
77
|
+
run bash "$SCRIPT" "$DIR/docs/decisions"
|
|
78
|
+
[[ "$output" == *"015-body-trick.proposed.md"* ]]
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@test "accepted ADRs are in scope (oversight is orthogonal to status)" {
|
|
82
|
+
mk "016-shipped.accepted.md"
|
|
83
|
+
run bash "$SCRIPT" "$DIR/docs/decisions"
|
|
84
|
+
[[ "$output" == *"016-shipped.accepted.md"* ]]
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@test "missing decisions dir exits 0 with no output" {
|
|
88
|
+
run bash "$SCRIPT" "$DIR/docs/nonexistent"
|
|
89
|
+
[ "$status" -eq 0 ]
|
|
90
|
+
[ -z "$output" ]
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@test "fully-confirmed set produces empty output" {
|
|
94
|
+
mk "017-a.proposed.md" "human-oversight: confirmed"
|
|
95
|
+
mk "018-b.accepted.md" "human-oversight: confirmed"
|
|
96
|
+
run bash "$SCRIPT" "$DIR/docs/decisions"
|
|
97
|
+
[ "$status" -eq 0 ]
|
|
98
|
+
[ -z "$output" ]
|
|
99
|
+
}
|
|
@@ -198,6 +198,15 @@ Present the written ADR and use AskUserQuestion to ask:
|
|
|
198
198
|
|
|
199
199
|
Apply any feedback by editing the file.
|
|
200
200
|
|
|
201
|
+
**Born-confirmed write (ADR-066).** Once the user confirms the ADR via this AskUserQuestion pass, write the human-oversight marker into the frontmatter — insert immediately after the `date:` line:
|
|
202
|
+
|
|
203
|
+
```yaml
|
|
204
|
+
human-oversight: confirmed
|
|
205
|
+
oversight-date: YYYY-MM-DD # today
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
This is the load-bearing born-confirmed gate: an ADR recorded through create-adr enters the world already human-oversighted (it does not appear in `/wr-architect:review-decisions`' unoversighted set). Do NOT write the marker if the user has not confirmed (rejected / still-iterating ADRs stay unmarked). The marker is orthogonal to `status:` — a `proposed` ADR can be `human-oversight: confirmed`.
|
|
209
|
+
|
|
201
210
|
### 6. Handle supersession (if applicable)
|
|
202
211
|
|
|
203
212
|
If the user mentions this decision replaces an existing one:
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wr-architect:review-decisions
|
|
3
|
+
description: Drain the set of recorded decisions (ADRs) that lack human oversight. Surfaces each unconfirmed ADR's chosen option and alternatives via AskUserQuestion so a human confirms, amends, or rejects the auto-made call, then writes the human-oversight marker. Use when the session-start nudge reports decisions lack oversight, or any time you want to review recorded decisions.
|
|
4
|
+
allowed-tools: Read, Glob, Grep, Bash, Edit, AskUserQuestion
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Review Decisions — human-oversight drain
|
|
8
|
+
|
|
9
|
+
Lift auto-made architecture decisions to human decisions. Many ADRs were recorded autocratically — the architect proposed an option and it stood without a human picking it. This skill drains the **unoversighted set** (ADRs lacking `human-oversight: confirmed` in frontmatter, per ADR-066): it surfaces each decision's chosen option + the alternatives via `AskUserQuestion`, and writes the oversight marker only when a human confirms.
|
|
10
|
+
|
|
11
|
+
This is the P283 prong-2 drain surface. It is the eat-our-own-dogfood loop: confirming a decision is itself a human decision, so it goes through `AskUserQuestion`.
|
|
12
|
+
|
|
13
|
+
## When to use
|
|
14
|
+
|
|
15
|
+
- The session-start nudge reported `N decisions lack human oversight`.
|
|
16
|
+
- Pre-handover / pre-release: confirm the recorded decision set reflects human intent.
|
|
17
|
+
- After a batch of AFK-recorded ADRs: review what landed without interactive confirmation.
|
|
18
|
+
- Any focused sitting — the drain is designed for **batches over multiple sittings**, not one blocking pass.
|
|
19
|
+
|
|
20
|
+
## How it works
|
|
21
|
+
|
|
22
|
+
Each run drains as many ADRs as the user has appetite for, in topic-clustered batches. The marker persists (ADR-009 never-re-ask principle), so a partially-drained set resumes cleanly on the next run.
|
|
23
|
+
|
|
24
|
+
### Step 1: Enumerate the unoversighted set
|
|
25
|
+
|
|
26
|
+
Run the detector (token-cheap — grep over frontmatter, no body reads):
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
wr-architect-detect-unoversighted docs/decisions
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The `wr-architect-detect-unoversighted` command is a `$PATH`-resolved shim (ADR-049 naming grammar) dispatching `packages/architect/scripts/detect-unoversighted.sh`. It prints one unoversighted ADR path per line (superseded ADRs are excluded — a retired decision needs no confirmation). Empty output → the set is fully drained; report "all recorded decisions carry human oversight" and stop.
|
|
33
|
+
|
|
34
|
+
### Step 2: Cluster + order
|
|
35
|
+
|
|
36
|
+
Read **only the frontmatter + title + Decision Outcome** of each unoversighted ADR (not full bodies — keep it cheap). Group by topic cluster (e.g. release-cadence, governance-gates, AFK-orchestration, decision-recording) and order **load-bearing first**: ADRs that other ADRs cite as parents, that are `accepted` (already shipped — highest drift cost if the auto-pick was wrong), or that govern a hook/gate the user interacts with daily. Defer narrow / low-coupling ADRs.
|
|
37
|
+
|
|
38
|
+
### Step 3: Present each decision via AskUserQuestion (batched)
|
|
39
|
+
|
|
40
|
+
For each ADR in the ordered queue, surface the decision as an `AskUserQuestion` (cap **4 ADRs per call** per ADR-013 Rule 1; issue further calls sequentially). For each ADR:
|
|
41
|
+
|
|
42
|
+
- **Question**: the decision the ADR records (its Decision Outcome, in one line).
|
|
43
|
+
- **Context**: the chosen option + the alternatives the ADR considered (grounded in the ADR's Considered Options section per ADR-026), and any cited parent ADRs.
|
|
44
|
+
- **Options** (per ADR):
|
|
45
|
+
- **Confirm** — the recorded decision is correct; write the marker.
|
|
46
|
+
- **Amend** — the decision is mostly right but needs a change; capture the change, apply it to the ADR body, then write the marker.
|
|
47
|
+
- **Reject / supersede** — the auto-made pick is wrong; do NOT write the marker. Note the rework needed (a follow-up `/wr-architect:create-adr` supersede, or a problem ticket).
|
|
48
|
+
- **Defer** — skip this sitting; leave unoversighted for a later run.
|
|
49
|
+
|
|
50
|
+
This is a genuine human-decision surface (the whole point of P283) — `AskUserQuestion` is correct here and is NOT over-asking. Do not auto-confirm; do not prose-ask.
|
|
51
|
+
|
|
52
|
+
### Step 4: Apply the outcome
|
|
53
|
+
|
|
54
|
+
- **Confirm / Amend**: write `human-oversight: confirmed` + `oversight-date: <today, YYYY-MM-DD>` into the ADR's frontmatter (insert after the `date:` line if absent; never duplicate). For Amend, apply the directed body change first. Both edits go through the standard architect / JTBD edit gate per ADR-014.
|
|
55
|
+
- **Reject / supersede**: leave the marker absent. Record the rework (follow-up create-adr supersede or `/wr-itil:capture-problem`).
|
|
56
|
+
- **Defer**: no write.
|
|
57
|
+
|
|
58
|
+
### Step 5: Commit + report
|
|
59
|
+
|
|
60
|
+
Commit the confirmed/amended ADRs per ADR-014 (one commit for the sitting's drained batch is acceptable — the unit of work is "this drain sitting"). Report: how many confirmed / amended / rejected / deferred, and the remaining unoversighted count (re-run the detector). The session-start nudge count drops by the number confirmed.
|
|
61
|
+
|
|
62
|
+
## Notes
|
|
63
|
+
|
|
64
|
+
- **Never re-ask** — a confirmed ADR carries the marker permanently and is excluded from future runs (ADR-009 never-re-ask principle). The marker is write-once **except** when an ADR is materially amended after confirmation (the Decision Outcome is rewritten) — a supersede/amend clears it for re-confirmation per ADR-066 Reassessment.
|
|
65
|
+
- **AFK** — this skill is interactive by construction (the confirm IS the human decision). It is not dispatched inside AFK iteration subprocesses; the session-start nudge self-suppresses there (`WR_SUPPRESS_OVERSIGHT_NUDGE=1`) so the drain is never half-run by an absent user.
|
|
66
|
+
- **Born-confirmed going forward** — `/wr-architect:create-adr` writes the marker at its Step 5 confirm, so new ADRs enter the set already oversighted and the unoversighted count only shrinks.
|
|
67
|
+
|
|
68
|
+
## Related
|
|
69
|
+
|
|
70
|
+
- **ADR-066** — the oversight marker + this drain skill + the detector + the nudge.
|
|
71
|
+
- **ADR-064** — the architect Needs-Direction verdict; the main agent owns `AskUserQuestion` (this skill is that ownership applied to the existing set).
|
|
72
|
+
- **ADR-009** — never-re-ask persistent-marker principle (the marker, not its TTL/drift lifecycle).
|
|
73
|
+
- **ADR-013 / ADR-044** — structured user interaction + decision-delegation taxonomy.
|
|
74
|
+
- **P283** — driving problem ticket (prong 2).
|