@windyroad/architect 0.21.5 → 0.21.6-preview.1139

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.
@@ -123,5 +123,5 @@
123
123
  }
124
124
  },
125
125
  "name": "wr-architect",
126
- "version": "0.21.5"
126
+ "version": "0.21.6"
127
127
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wr-architect",
3
- "version": "0.21.5",
3
+ "version": "0.21.6",
4
4
  "description": "Architecture decision enforcement for AI coding agents",
5
5
  "author": {
6
6
  "name": "Windy Road Technology",
@@ -2,9 +2,9 @@
2
2
  # Architecture - PostToolUse:Agent|Bash|Skill slide-marker hook (P111 + P213).
3
3
  # Slides the parent session's existing architect-reviewed marker forward on
4
4
  # subprocess return, treating subprocess wall-clock as continuous parent-
5
- # session work for TTL purposes. Only TOUCHES an existing marker — never
6
- # creates one (creation requires a real architect review parsed from the
7
- # agent's verdict text in architect-mark-reviewed.sh).
5
+ # session work for TTL purposes. It only TOUCHES existing architecture-review
6
+ # markers. P368 also lets an exact successful oversight-helper event create
7
+ # its separate document-and-session evidence marker.
8
8
  #
9
9
  # This addresses P111 / ADR-009 "Subprocess-boundary refresh": Agent, Bash,
10
10
  # and Skill tool calls that wrap long-running subprocesses (other subagents,
@@ -23,6 +23,50 @@ source "$SCRIPT_DIR/lib/gate-helpers.sh"
23
23
  _parse_input
24
24
 
25
25
  SESSION_ID=$(_get_session_id)
26
+
27
+ # P368: the successful standalone helper invocation and its PostToolUse event
28
+ # are the only place where the confirming session id and artefact path coexist.
29
+ OVERSIGHT_PATH=$(printf '%s' "$_HOOK_INPUT" | python3 -c '
30
+ import json, shlex, sys
31
+ try:
32
+ data = json.load(sys.stdin)
33
+ response = data.get("tool_response", {})
34
+ argv = shlex.split(data.get("tool_input", {}).get("command", ""))
35
+ if (data.get("tool_name") == "Bash"
36
+ and isinstance(response, dict)
37
+ and response.get("is_error") is not True
38
+ and len(argv) == 2
39
+ and argv[0] == "wr-architect-mark-oversight-confirmed"):
40
+ print(argv[1])
41
+ except Exception:
42
+ pass
43
+ ' 2>/dev/null)
44
+
45
+ if [ -n "$OVERSIGHT_PATH" ]; then
46
+ if [ -z "$SESSION_ID" ]; then
47
+ echo "wr-architect-mark-oversight-confirmed: missing session id; no oversight marker written" >&2
48
+ else
49
+ ABS_DIR="$(cd "$(dirname "$OVERSIGHT_PATH")" 2>/dev/null && pwd)" || ABS_DIR=""
50
+ ABS_PATH="${ABS_DIR:+$ABS_DIR/}$(basename "$OVERSIGHT_PATH")"
51
+ case "$ABS_PATH" in
52
+ */docs/decisions/*.md)
53
+ if command -v sha256sum >/dev/null 2>&1; then
54
+ PATH_HASH=$(printf '%s' "$ABS_PATH" | sha256sum | cut -d' ' -f1 | cut -c1-16)
55
+ elif command -v shasum >/dev/null 2>&1; then
56
+ PATH_HASH=$(printf '%s' "$ABS_PATH" | shasum -a 256 | cut -d' ' -f1 | cut -c1-16)
57
+ else
58
+ echo "wr-architect-mark-oversight-confirmed: no SHA-256 utility; no oversight marker written" >&2
59
+ PATH_HASH=""
60
+ fi
61
+ if [ -n "$PATH_HASH" ] && ! : > "${SESSION_MARKER_DIR:-/tmp}/oversight-confirmed-${PATH_HASH}-${SESSION_ID}"; then
62
+ echo "wr-architect-mark-oversight-confirmed: marker write failed" >&2
63
+ fi
64
+ ;;
65
+ *) echo "wr-architect-mark-oversight-confirmed: invalid ADR path; no oversight marker written" >&2 ;;
66
+ esac
67
+ fi
68
+ fi
69
+
26
70
  [ -n "$SESSION_ID" ] || exit 0
27
71
 
28
72
  slide_marker_on_subprocess_return "/tmp/architect-reviewed-${SESSION_ID}"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/architect",
3
- "version": "0.21.5",
3
+ "version": "0.21.6-preview.1139",
4
4
  "description": "Architecture decision enforcement for AI coding agents",
5
5
  "bin": {
6
6
  "windyroad-architect": "./bin/install.mjs"
@@ -2,11 +2,10 @@
2
2
  # wr-architect — mark a decision/ADR's human-oversight: confirmed marker write
3
3
  # as user-substance-confirmed (P348 / ADR-110).
4
4
  #
5
- # Companion to the architect-oversight-marker-discipline.sh PreToolUse hook
6
- # (also P348). SKILLs invoke this script AFTER an AskUserQuestion lands the
7
- # user's substance-confirm answer for a specific ADR; the script writes the
8
- # evidence marker that the hook reads to permit the subsequent Edit/Write
9
- # that introduces `human-oversight: confirmed` into that ADR's frontmatter.
5
+ # Companion to the architect-oversight-marker-discipline.sh PreToolUse hook.
6
+ # SKILLs invoke this as a standalone Bash command AFTER an AskUserQuestion
7
+ # lands the user's substance-confirm answer. The existing PostToolUse:Bash
8
+ # hook binds that exact command event's path and session id into the marker.
10
9
  #
11
10
  # Why the marker is required:
12
11
  # ADR-066 establishes that `human-oversight: confirmed` is a write-once-
@@ -19,106 +18,25 @@
19
18
  # enforces the boundary structurally; this script is the evidence-write
20
19
  # side that legitimate substance-confirm flows use.
21
20
  #
22
- # Marker convention:
23
- # /tmp/oversight-confirmed-<sha256-of-path>-<session-id>
24
- # Written under EVERY recent candidate session SID per ADR-050 Option C
25
- # (concurrent orchestrator + subprocess sessions in the same project, the
26
- # per-machine runtime-sid marker is last-writer-wins). The PreToolUse hook
27
- # reads the SID from its stdin JSON; marking under every candidate
28
- # guarantees a matching marker exists whichever SID the hook reads.
29
- #
30
21
  # Usage:
31
22
  # wr-architect-mark-oversight-confirmed <artefact-path>
32
- # <artefact-path> the ADR file path the user just substance-confirmed.
33
- # The script computes sha256 of the absolute path.
23
+ # Must be the whole Bash command, with exactly one ADR path argument.
34
24
  #
35
25
  # Exit codes:
36
- # 0 — marker(s) written for at least one candidate SID, OR no candidate
37
- # SID was discoverable (cold path: no announce markers yet). The latter
38
- # writes no marker and prints a loud stderr diagnostic (P368) explaining
39
- # the downstream hook deny, then exits 0 so SKILL flows do not crash
40
- # before any hook has fired in the session.
41
- # 2 — bad argument (missing or empty artefact-path).
26
+ # 0 — command validated; PostToolUse writes the exact-session marker.
27
+ # 2 bad argument count.
42
28
  #
43
29
  # @adr ADR-066 (human-oversight marker)
44
30
  # @adr ADR-049 (PATH shim grammar)
45
- # @adr ADR-050 (multi-SID candidate enumeration)
46
31
  # @adr ADR-013 (Rule 6 fail-safe-defer in non-interactive contexts)
47
32
  # @problem P348 (iter subprocesses set human-oversight: confirmed without user event)
33
+ # @problem P368 (candidate enumeration grants unrelated sessions)
48
34
 
49
35
  set -uo pipefail
50
36
 
51
- ARTEFACT_PATH="${1:-}"
52
-
53
- if [ -z "$ARTEFACT_PATH" ]; then
54
- echo "wr-architect-mark-oversight-confirmed: missing <artefact-path>" >&2
55
- exit 2
56
- fi
57
-
58
- # Normalize to absolute path so the hash is stable regardless of CWD.
59
- # `cd $(dirname)` works whether the file exists or not (basename + abs dir).
60
- abs_dir="$(cd "$(dirname "$ARTEFACT_PATH")" 2>/dev/null && pwd)" || abs_dir=""
61
- if [ -n "$abs_dir" ]; then
62
- ABS_PATH="$abs_dir/$(basename "$ARTEFACT_PATH")"
63
- else
64
- ABS_PATH="$ARTEFACT_PATH"
65
- fi
66
-
67
- # Path hash — use shasum/sha256sum portably (macOS ships shasum; Linux usually
68
- # has both). First 16 hex chars are plenty for unique marker filenames.
69
- if command -v sha256sum >/dev/null 2>&1; then
70
- PATH_HASH=$(printf '%s' "$ABS_PATH" | sha256sum | cut -d' ' -f1 | cut -c1-16)
71
- elif command -v shasum >/dev/null 2>&1; then
72
- PATH_HASH=$(printf '%s' "$ABS_PATH" | shasum -a 256 | cut -d' ' -f1 | cut -c1-16)
73
- else
74
- echo "wr-architect-mark-oversight-confirmed: no sha256 tool available" >&2
37
+ if [ "$#" -ne 1 ] || [ -z "$1" ]; then
38
+ echo "wr-architect-mark-oversight-confirmed: expected exactly one <artefact-path>" >&2
75
39
  exit 2
76
40
  fi
77
41
 
78
- MARKER_DIR="${SESSION_MARKER_DIR:-/tmp}"
79
- WINDOW_MINS="${SESSION_CANDIDATE_WINDOW_MINS:-1440}"
80
-
81
- # Candidate SID enumeration — recent announce markers across all systems
82
- # within the mtime window. Mirrors get_candidate_session_ids in
83
- # packages/itil/hooks/lib/session-id.sh; inlined here so this script is
84
- # self-contained (no cross-plugin lib source — architect must not depend on
85
- # itil-internal helpers per ADR-002 plugin packaging).
86
- candidates=$(
87
- {
88
- # Env-var fast path. Not exported in agent contexts today, but if a
89
- # future Claude Code release adds it, this branch picks it up for free.
90
- if [ -n "${CLAUDE_SESSION_ID:-}" ]; then
91
- echo "$CLAUDE_SESSION_ID"
92
- fi
93
- # Recent announce markers. `-L` follows the start-point symlink — on macOS
94
- # MARKER_DIR defaults to /tmp, a symlink to /private/tmp, which `find` would
95
- # otherwise refuse to descend (no-op on Linux where /tmp is a real dir). P380.
96
- find -L "$MARKER_DIR" -maxdepth 1 -name '*-announced-*' -mmin "-${WINDOW_MINS}" 2>/dev/null \
97
- | sed 's|.*/||; s/.*-announced-//'
98
- } | awk 'NF && !seen[$0]++'
99
- )
100
-
101
- # No candidate SID — cold path. Emit a loud stderr diagnostic (P368) and still
102
- # exit 0. Exit 0 preserves the documented contract (do not crash SKILL flows
103
- # before any announce marker has fired this session); the diagnostic replaces the
104
- # prior SILENT no-op, which masqueraded as success and left the caller to hit the
105
- # oversight-marker-discipline hook's deny with no idea why — the confusing loop
106
- # P368 documents (the deny points back at this shim, which the caller already ran).
107
- if [ -z "$candidates" ]; then
108
- {
109
- echo "wr-architect-mark-oversight-confirmed: no candidate session id discoverable"
110
- echo " (CLAUDE_SESSION_ID empty and no *-announced-* markers in ${MARKER_DIR} within ${WINDOW_MINS}min)."
111
- echo " NO oversight marker was written for: ${ABS_PATH}"
112
- echo " The oversight-marker-discipline hook will DENY the 'human-oversight: confirmed' Edit"
113
- echo " until a session announce marker exists. Start a fresh session, or point SESSION_MARKER_DIR"
114
- echo " at a dir containing a *-announced-<sid> file, then re-run this shim."
115
- } >&2
116
- exit 0
117
- fi
118
-
119
- while IFS= read -r sid; do
120
- [ -n "$sid" ] || continue
121
- : > "$MARKER_DIR/oversight-confirmed-${PATH_HASH}-${sid}"
122
- done <<< "$candidates"
123
-
124
42
  exit 0
@@ -316,12 +316,14 @@ Only after every draft edit is complete, call the marker-evidence helper and ins
316
316
  bash "<architect-plugin-root>/scripts/mark-oversight-confirmed.sh" docs/decisions/<NNN>-<slug>.proposed.md
317
317
  ```
318
318
 
319
+ Run that helper as the complete standalone Bash command. Do not combine it with another command: the PostToolUse hook binds this exact successful command event's session id and ADR path into the evidence marker.
320
+
319
321
  ```yaml
320
322
  human-oversight: confirmed
321
323
  oversight-date: YYYY-MM-DD # today
322
324
  ```
323
325
 
324
- The helper writes the session-scoped evidence marker consumed by `architect-oversight-marker-discipline.sh`. Calling it without a real substance-confirm event is forbidden. Once these lines land, do not edit the ADR body or clear the marker; a later choice requires a new superseding ADR.
326
+ The PostToolUse hook writes the session-scoped evidence marker consumed by `architect-oversight-marker-discipline.sh`. Calling the helper without a real substance-confirm event is forbidden. Once these lines land, do not edit the ADR body or clear the marker; a later choice requires a new superseding ADR.
325
327
 
326
328
  **Refresh the decisions compendium (the decisions-compendium load rule).** After the ADR file is written and any born-confirmed marker is applied, regenerate `docs/decisions/README.md` so the architect-agent routine load surface includes the new entry. Run:
327
329
 
@@ -76,7 +76,7 @@ This is a genuine human-decision surface (the whole point of the unpinned archit
76
76
 
77
77
  ### Step 4: Apply the outcome
78
78
 
79
- - **Confirm / Amend**: this queue contains only unconfirmed ADRs, so the user may still amend their draft substance. Apply any directed body change first, then write `human-oversight: confirmed` + `oversight-date: <today, YYYY-MM-DD>` into the ADR's frontmatter (insert after the `date:` line if absent; never duplicate). Confirmation is the final content write. Both edits go through the standard architect / JTBD edit gate per the governance skills commit completed work rule.
79
+ - **Confirm / Amend**: this queue contains only unconfirmed ADRs, so the user may still amend their draft substance. Apply any directed body change first. Then run `bash "<architect-plugin-root>/scripts/mark-oversight-confirmed.sh" <adr-path>` as a standalone Bash command; do not combine it with another command, because its PostToolUse event binds the evidence to this exact session and ADR. Finally, write `human-oversight: confirmed` + `oversight-date: <today, YYYY-MM-DD>` into the ADR's frontmatter (insert after the `date:` line if absent; never duplicate). Confirmation is the final content write. Both edits go through the standard architect / JTBD edit gate per the governance skills commit completed work rule.
80
80
  - **Reject / supersede** (the architecture human-oversight rule amendment per the rejected-decision drain recurrence):
81
81
  1. Capture the supersede ticket via a follow-up `request_user_input`: "Which problem ticket tracks the supersede?" — options: existing `P<NNN>` IDs surfaced from `docs/problems/`, **Capture a new ticket** (delegate to `/wr-itil:capture-problem`), or **Defer (leave un-tracked for now)**.
82
82
  2. If a ticket ID is captured, write `human-oversight: rejected-pending-supersede` + `supersede-ticket: P<NNN>` into the ADR's frontmatter. The detector excludes ADRs carrying both, so the drain stops re-asking until either the successor lands (the rejected file is renamed to `*.superseded.md` without rewriting its content) or the rejection is revisited.