@windyroad/itil 0.35.15 → 0.35.16-preview.426
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/bin/wr-itil-check-upstream-cache-staleness +3 -0
- package/bin/wr-itil-mark-create-gate +3 -0
- package/bin/wr-itil-mark-rfc-capture-gate +3 -0
- package/bin/wr-itil-migrate-problems-layout +3 -0
- package/bin/wr-itil-update-jtbd-references-section +3 -0
- package/bin/wr-itil-update-problem-references-section +3 -0
- package/bin/wr-itil-update-problem-rfcs-section +3 -0
- package/bin/wr-itil-update-rfc-references-section +3 -0
- package/hooks/lib/runtime-sid.sh +3 -2
- package/hooks/lib/session-id.sh +7 -5
- package/package.json +1 -1
- package/scripts/mark-create-gate.sh +26 -0
- package/scripts/mark-rfc-capture-gate.sh +32 -0
- package/scripts/run-check-upstream-cache-staleness.sh +21 -0
- package/scripts/run-migrate-problems-layout.sh +19 -0
- package/scripts/test/kind-a-commands.bats +46 -0
- package/scripts/test/mark-create-gate.bats +59 -0
- package/scripts/test/rfc-stories-extension.bats +1 -1
- package/skills/capture-problem/SKILL.md +4 -4
- package/skills/capture-rfc/SKILL.md +10 -2
- package/skills/capture-story/SKILL.md +3 -3
- package/skills/capture-story-map/SKILL.md +2 -2
- package/skills/manage-problem/SKILL.md +7 -8
- package/skills/manage-rfc/SKILL.md +3 -3
- package/skills/manage-story/SKILL.md +3 -3
- package/skills/manage-story-map/SKILL.md +2 -2
- package/skills/manage-story-map/test/manage-story-map-contract.bats +2 -2
- package/skills/reconcile-stories/SKILL.md +3 -3
- package/skills/work-problems/SKILL.md +6 -4
package/hooks/lib/runtime-sid.sh
CHANGED
|
@@ -44,8 +44,9 @@
|
|
|
44
44
|
|
|
45
45
|
# Echoes the runtime-SID marker path on stdout. Always exits 0.
|
|
46
46
|
#
|
|
47
|
-
# Usage
|
|
48
|
-
#
|
|
47
|
+
# Usage (resolve relative to the caller's own location — NEVER repo-relative
|
|
48
|
+
# `packages/...`, which only exists in the source monorepo; P317/RFC-009):
|
|
49
|
+
# source "$(dirname "${BASH_SOURCE[0]}")/runtime-sid.sh"
|
|
49
50
|
# path=$(runtime_sid_path)
|
|
50
51
|
runtime_sid_path() {
|
|
51
52
|
if [ -n "${SESSION_MARKER_DIR:-}" ]; then
|
package/hooks/lib/session-id.sh
CHANGED
|
@@ -57,8 +57,9 @@
|
|
|
57
57
|
# Returns the canonical session UUID for the current invocation.
|
|
58
58
|
# Echoes the UUID on stdout. Exit 0 if discovered, 1 if not.
|
|
59
59
|
#
|
|
60
|
-
# Usage
|
|
61
|
-
#
|
|
60
|
+
# Usage (resolve relative to the caller's own location — NEVER repo-relative
|
|
61
|
+
# `packages/...`, which only exists in the source monorepo; P317/RFC-009):
|
|
62
|
+
# source "$(dirname "${BASH_SOURCE[0]}")/session-id.sh" # or ../hooks/lib/ from a scripts/ wrapper
|
|
62
63
|
# sid=$(get_current_session_id) || { echo "no SID available" >&2; exit 1; }
|
|
63
64
|
get_current_session_id() {
|
|
64
65
|
# Env-var fast path. CLAUDE_SESSION_ID is not exported in agent
|
|
@@ -203,9 +204,10 @@ get_current_session_id() {
|
|
|
203
204
|
# Test overrides: SESSION_MARKER_DIR (marker dir, default /tmp) +
|
|
204
205
|
# SESSION_CANDIDATE_WINDOW_MINS (window minutes, default 1440).
|
|
205
206
|
#
|
|
206
|
-
# Usage
|
|
207
|
-
#
|
|
208
|
-
#
|
|
207
|
+
# Usage — SKILLs call the `wr-itil-mark-create-gate` command (it does the
|
|
208
|
+
# source+pipe internally, adopter-safe); direct callers resolve the libs relative
|
|
209
|
+
# to their OWN location, NEVER repo-relative `packages/...` (P317/RFC-009):
|
|
210
|
+
# LIB="$(dirname "${BASH_SOURCE[0]}")"; source "$LIB/session-id.sh"; source "$LIB/create-gate.sh"
|
|
209
211
|
# get_candidate_session_ids | mark_step2_complete_candidates
|
|
210
212
|
get_candidate_session_ids() {
|
|
211
213
|
local marker_dir="${SESSION_MARKER_DIR:-/tmp}"
|
package/package.json
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# wr-itil — write the problem-tier create-gate marker (P119) under every
|
|
3
|
+
# candidate session SID (P260 / ADR-050 Option C).
|
|
4
|
+
#
|
|
5
|
+
# Internalises the source+pipe that capture-problem / manage-problem Step 2
|
|
6
|
+
# previously ran INLINE with repo-relative `source packages/itil/hooks/lib/*.sh`
|
|
7
|
+
# — which only resolved in the source monorepo and broke in adopter installs
|
|
8
|
+
# (P317 / RFC-009). This script resolves its sibling libs RELATIVE TO ITS OWN
|
|
9
|
+
# LOCATION (`$(dirname)/../hooks/lib`), so it works wherever the plugin is
|
|
10
|
+
# installed. SKILLs invoke it by name via the `wr-itil-mark-create-gate` PATH
|
|
11
|
+
# shim (ADR-049) instead of sourcing repo-relative lib files.
|
|
12
|
+
set -uo pipefail
|
|
13
|
+
|
|
14
|
+
LIB="$(cd "$(dirname "${BASH_SOURCE[0]}")/../hooks/lib" 2>/dev/null && pwd)" || {
|
|
15
|
+
echo "wr-itil-mark-create-gate: cannot locate hooks/lib next to the script" >&2
|
|
16
|
+
exit 2
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
# shellcheck source=/dev/null
|
|
20
|
+
source "$LIB/session-id.sh"
|
|
21
|
+
# shellcheck source=/dev/null
|
|
22
|
+
source "$LIB/create-gate.sh"
|
|
23
|
+
|
|
24
|
+
# Writes /tmp/manage-problem-grep-<SID> under each recent candidate SID; returns
|
|
25
|
+
# non-zero only if no candidate SID was discoverable (fail-closed parity).
|
|
26
|
+
get_candidate_session_ids | mark_step2_complete_candidates
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# wr-itil — write the RFC-tier create-gate marker (P119) under every candidate
|
|
3
|
+
# session SID (P260 / ADR-050 Option C). Adopter-safe sibling of
|
|
4
|
+
# wr-itil-mark-create-gate (P317 / RFC-009): resolves its libs relative to the
|
|
5
|
+
# script location, not cwd. SKILLs (capture-rfc / manage-rfc) invoke it by name
|
|
6
|
+
# via the `wr-itil-mark-rfc-capture-gate` PATH shim (ADR-049) before writing a
|
|
7
|
+
# docs/rfcs/RFC-*.proposed.md file.
|
|
8
|
+
#
|
|
9
|
+
# The RFC tier has no `_candidates` helper in create-gate.sh (only the single
|
|
10
|
+
# `mark_rfc_capture_complete`), so this script loops the candidate set itself —
|
|
11
|
+
# the RFC-tier analogue of `mark_step2_complete_candidates`.
|
|
12
|
+
set -uo pipefail
|
|
13
|
+
|
|
14
|
+
LIB="$(cd "$(dirname "${BASH_SOURCE[0]}")/../hooks/lib" 2>/dev/null && pwd)" || {
|
|
15
|
+
echo "wr-itil-mark-rfc-capture-gate: cannot locate hooks/lib next to the script" >&2
|
|
16
|
+
exit 2
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
# shellcheck source=/dev/null
|
|
20
|
+
source "$LIB/session-id.sh"
|
|
21
|
+
# shellcheck source=/dev/null
|
|
22
|
+
source "$LIB/create-gate.sh"
|
|
23
|
+
|
|
24
|
+
count=0
|
|
25
|
+
while IFS= read -r sid; do
|
|
26
|
+
[ -n "$sid" ] || continue
|
|
27
|
+
mark_rfc_capture_complete "$sid"
|
|
28
|
+
count=$((count + 1))
|
|
29
|
+
done < <(get_candidate_session_ids)
|
|
30
|
+
|
|
31
|
+
# Fail-closed parity with mark_step2_complete_candidates: non-zero if no SID.
|
|
32
|
+
[ "$count" -gt 0 ]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# wr-itil — echo the inbound-discovery-preflight promotion reason, or empty if
|
|
3
|
+
# promotion is not warranted (P317/RFC-009).
|
|
4
|
+
#
|
|
5
|
+
# Adopter-safe wrapper: sources the canonical lib RELATIVE TO THIS SCRIPT
|
|
6
|
+
# (`$(dirname)/../lib`), then echoes the function's result on stdout (the SKILL
|
|
7
|
+
# captures it via `$(...)`). Replaces the SKILL-inline
|
|
8
|
+
# `source packages/itil/lib/check-upstream-cache-staleness.sh;
|
|
9
|
+
# preflight_reason="$(should_promote_inbound_discovery_preflight "$PWD")"`,
|
|
10
|
+
# which only resolved in the source monorepo (P317). SKILLs invoke this by name
|
|
11
|
+
# via the `wr-itil-check-upstream-cache-staleness` PATH shim (ADR-049).
|
|
12
|
+
# Operates on the directory given as $1 (defaults to $PWD).
|
|
13
|
+
set -uo pipefail
|
|
14
|
+
|
|
15
|
+
LIB="$(cd "$(dirname "${BASH_SOURCE[0]}")/../lib" 2>/dev/null && pwd)" || {
|
|
16
|
+
echo "wr-itil-check-upstream-cache-staleness: cannot locate lib next to the script" >&2
|
|
17
|
+
exit 2
|
|
18
|
+
}
|
|
19
|
+
# shellcheck source=/dev/null
|
|
20
|
+
source "$LIB/check-upstream-cache-staleness.sh"
|
|
21
|
+
should_promote_inbound_discovery_preflight "${1:-$PWD}"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# wr-itil — run the problems-layout flat→per-state migration (P317/RFC-009).
|
|
3
|
+
#
|
|
4
|
+
# Adopter-safe wrapper: sources the canonical lib RELATIVE TO THIS SCRIPT
|
|
5
|
+
# (`$(dirname)/../lib`), then invokes the function. Replaces the SKILL-inline
|
|
6
|
+
# `source packages/itil/lib/migrate-problems-layout.sh; migrate_... "$PWD"`,
|
|
7
|
+
# which only resolved in the source monorepo (P317). SKILLs invoke this by name
|
|
8
|
+
# via the `wr-itil-migrate-problems-layout` PATH shim (ADR-049). The migration
|
|
9
|
+
# routine is idempotent + partial-migration-safe (no-op when no flat-layout
|
|
10
|
+
# files exist). Operates on the directory given as $1 (defaults to $PWD).
|
|
11
|
+
set -uo pipefail
|
|
12
|
+
|
|
13
|
+
LIB="$(cd "$(dirname "${BASH_SOURCE[0]}")/../lib" 2>/dev/null && pwd)" || {
|
|
14
|
+
echo "wr-itil-migrate-problems-layout: cannot locate lib next to the script" >&2
|
|
15
|
+
exit 2
|
|
16
|
+
}
|
|
17
|
+
# shellcheck source=/dev/null
|
|
18
|
+
source "$LIB/migrate-problems-layout.sh"
|
|
19
|
+
migrate_problems_to_per_state_layout "${1:-$PWD}"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env bats
|
|
2
|
+
# P317 / RFC-009 T2 + ADR-049: the KIND A wrapper commands resolve their
|
|
3
|
+
# canonical lib RELATIVE TO THE SCRIPT (`$(dirname)/../lib`), so they work in an
|
|
4
|
+
# adopter install — not just the source monorepo where `source packages/...`
|
|
5
|
+
# happened to resolve. Behavioural: simulate an install tree, invoke from a
|
|
6
|
+
# FOREIGN cwd, assert clean lib resolution.
|
|
7
|
+
|
|
8
|
+
setup() {
|
|
9
|
+
REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../.." && pwd)"
|
|
10
|
+
INSTALL="$(mktemp -d)"
|
|
11
|
+
mkdir -p "$INSTALL/scripts" "$INSTALL/lib" "$INSTALL/bin"
|
|
12
|
+
cp "$REPO_ROOT/packages/itil/scripts/run-migrate-problems-layout.sh" "$INSTALL/scripts/" 2>/dev/null || true
|
|
13
|
+
cp "$REPO_ROOT/packages/itil/scripts/run-check-upstream-cache-staleness.sh" "$INSTALL/scripts/" 2>/dev/null || true
|
|
14
|
+
cp "$REPO_ROOT/packages/itil/bin/wr-itil-migrate-problems-layout" "$INSTALL/bin/" 2>/dev/null || true
|
|
15
|
+
cp "$REPO_ROOT/packages/itil/bin/wr-itil-check-upstream-cache-staleness" "$INSTALL/bin/" 2>/dev/null || true
|
|
16
|
+
cp "$REPO_ROOT"/packages/itil/lib/*.sh "$INSTALL/lib/" 2>/dev/null || true
|
|
17
|
+
FOREIGN="$(mktemp -d)" # adopter repo cwd — no packages/ tree
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
teardown() {
|
|
21
|
+
rm -rf "$INSTALL" "$FOREIGN"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@test "wr-itil-migrate-problems-layout resolves its lib from a foreign cwd, no-ops on empty dir (P317)" {
|
|
25
|
+
cd "$FOREIGN"
|
|
26
|
+
run bash "$INSTALL/bin/wr-itil-migrate-problems-layout" "$FOREIGN"
|
|
27
|
+
[ "$status" -eq 0 ]
|
|
28
|
+
[[ "$output" != *"No such file"* ]]
|
|
29
|
+
[[ "$output" != *"command not found"* ]]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@test "wr-itil-check-upstream-cache-staleness resolves its lib from a foreign cwd (P317)" {
|
|
33
|
+
cd "$FOREIGN"
|
|
34
|
+
run bash "$INSTALL/bin/wr-itil-check-upstream-cache-staleness" "$FOREIGN"
|
|
35
|
+
[ "$status" -eq 0 ]
|
|
36
|
+
[[ "$output" != *"No such file"* ]]
|
|
37
|
+
[[ "$output" != *"command not found"* ]]
|
|
38
|
+
[[ "$output" != *"migrate_problems_to_per_state_layout: command not found"* ]]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@test "the direct script (not just the shim) also resolves its lib from a foreign cwd (P317)" {
|
|
42
|
+
cd "$FOREIGN"
|
|
43
|
+
run bash "$INSTALL/scripts/run-migrate-problems-layout.sh" "$FOREIGN"
|
|
44
|
+
[ "$status" -eq 0 ]
|
|
45
|
+
[[ "$output" != *"No such file"* ]]
|
|
46
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env bats
|
|
2
|
+
# P317 / RFC-009 T1 + ADR-049: the create-gate marker commands resolve their
|
|
3
|
+
# sibling libs RELATIVE TO THE SCRIPT (adopter-safe), not relative to cwd. The
|
|
4
|
+
# bug they fix: SKILLs did `source packages/itil/hooks/lib/*.sh`, which only
|
|
5
|
+
# resolves in the source monorepo and breaks in adopter installs.
|
|
6
|
+
#
|
|
7
|
+
# Behavioural — simulates an adopter install by copying the shipped script +
|
|
8
|
+
# lib tree to a temp dir in the SAME relative layout, then invokes from a
|
|
9
|
+
# FOREIGN cwd (an "adopter repo" with no packages/ tree) and asserts success.
|
|
10
|
+
|
|
11
|
+
setup() {
|
|
12
|
+
REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../.." && pwd)"
|
|
13
|
+
INSTALL="$(mktemp -d)"
|
|
14
|
+
mkdir -p "$INSTALL/scripts" "$INSTALL/hooks/lib" "$INSTALL/bin"
|
|
15
|
+
cp "$REPO_ROOT/packages/itil/scripts/mark-create-gate.sh" "$INSTALL/scripts/" 2>/dev/null || true
|
|
16
|
+
cp "$REPO_ROOT/packages/itil/scripts/mark-rfc-capture-gate.sh" "$INSTALL/scripts/" 2>/dev/null || true
|
|
17
|
+
cp "$REPO_ROOT/packages/itil/bin/wr-itil-mark-create-gate" "$INSTALL/bin/" 2>/dev/null || true
|
|
18
|
+
cp "$REPO_ROOT/packages/itil/bin/wr-itil-mark-rfc-capture-gate" "$INSTALL/bin/" 2>/dev/null || true
|
|
19
|
+
cp "$REPO_ROOT"/packages/itil/hooks/lib/*.sh "$INSTALL/hooks/lib/" 2>/dev/null || true
|
|
20
|
+
FOREIGN="$(mktemp -d)" # an adopter repo cwd — no packages/ tree
|
|
21
|
+
MARKERS="$(mktemp -d)" # empty announce-marker dir so candidates = CLAUDE_SESSION_ID only
|
|
22
|
+
SID="p317-test-$$-${RANDOM}"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
teardown() {
|
|
26
|
+
rm -rf "$INSTALL" "$FOREIGN" "$MARKERS"
|
|
27
|
+
rm -f "/tmp/manage-problem-grep-$SID" "/tmp/wr-itil-rfc-capture-grep-$SID"
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@test "mark-create-gate.sh runs from a foreign cwd, resolving libs from its own location (P317)" {
|
|
31
|
+
cd "$FOREIGN"
|
|
32
|
+
run env CLAUDE_SESSION_ID="$SID" SESSION_MARKER_DIR="$MARKERS" bash "$INSTALL/scripts/mark-create-gate.sh"
|
|
33
|
+
[ "$status" -eq 0 ]
|
|
34
|
+
[[ "$output" != *"No such file"* ]]
|
|
35
|
+
[[ "$output" != *"command not found"* ]]
|
|
36
|
+
[ -f "/tmp/manage-problem-grep-$SID" ]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@test "wr-itil-mark-create-gate shim dispatches the script from a foreign cwd (P317/ADR-049)" {
|
|
40
|
+
cd "$FOREIGN"
|
|
41
|
+
run env CLAUDE_SESSION_ID="$SID" SESSION_MARKER_DIR="$MARKERS" bash "$INSTALL/bin/wr-itil-mark-create-gate"
|
|
42
|
+
[ "$status" -eq 0 ]
|
|
43
|
+
[ -f "/tmp/manage-problem-grep-$SID" ]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@test "mark-rfc-capture-gate.sh writes the RFC-tier marker from a foreign cwd (P317)" {
|
|
47
|
+
cd "$FOREIGN"
|
|
48
|
+
run env CLAUDE_SESSION_ID="$SID" SESSION_MARKER_DIR="$MARKERS" bash "$INSTALL/scripts/mark-rfc-capture-gate.sh"
|
|
49
|
+
[ "$status" -eq 0 ]
|
|
50
|
+
[[ "$output" != *"No such file"* ]]
|
|
51
|
+
[ -f "/tmp/wr-itil-rfc-capture-grep-$SID" ]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@test "wr-itil-mark-rfc-capture-gate shim dispatches from a foreign cwd (P317/ADR-049)" {
|
|
55
|
+
cd "$FOREIGN"
|
|
56
|
+
run env CLAUDE_SESSION_ID="$SID" SESSION_MARKER_DIR="$MARKERS" bash "$INSTALL/bin/wr-itil-mark-rfc-capture-gate"
|
|
57
|
+
[ "$status" -eq 0 ]
|
|
58
|
+
[ -f "/tmp/wr-itil-rfc-capture-grep-$SID" ]
|
|
59
|
+
}
|
|
@@ -168,6 +168,6 @@ EOF
|
|
|
168
168
|
# in the SKILL body. Behavioural assertion on the presence of the
|
|
169
169
|
# load-bearing call path; without it, manage-rfc transitions would
|
|
170
170
|
# silently leave the body section stale.
|
|
171
|
-
run grep -E 'update-rfc-references-section
|
|
171
|
+
run grep -E 'wr-itil-update-rfc-references-section.*Stories' "$MANAGE_RFC"
|
|
172
172
|
[ "$status" -eq 0 ]
|
|
173
173
|
}
|
|
@@ -156,12 +156,12 @@ If matches are found: list them in the final report. **Do NOT halt or branch.**
|
|
|
156
156
|
**After the grep completes**, write the per-session create-gate marker so the `PreToolUse:Write` hook (P119) permits the subsequent Write of the new `.open.md` file. Per **P260 / ADR-050 Option C**, write it under EVERY recent candidate session SID (not just one) so a concurrent orchestrator+subprocess race cannot land the marker under the wrong UUID:
|
|
157
157
|
|
|
158
158
|
```bash
|
|
159
|
-
|
|
160
|
-
source packages/itil/hooks/lib/create-gate.sh
|
|
161
|
-
get_candidate_session_ids | mark_step2_complete_candidates
|
|
159
|
+
wr-itil-mark-create-gate
|
|
162
160
|
```
|
|
163
161
|
|
|
164
|
-
|
|
162
|
+
`wr-itil-mark-create-gate` is the ADR-049 `$PATH` shim that internalises the former inline `source packages/itil/hooks/lib/{session-id,create-gate}.sh` + `get_candidate_session_ids | mark_step2_complete_candidates`. It resolves those `hooks/lib` siblings RELATIVE TO THE SCRIPT, not cwd (P317/RFC-009) — so it works in adopter installs. NEVER `source packages/...` repo-relative from a SKILL; those paths only resolve in the source monorepo, not where the plugin is installed.
|
|
163
|
+
|
|
164
|
+
The marker is shared between `manage-problem` and `capture-problem` per ADR-032 amendment — same `/tmp/manage-problem-grep-${SESSION_ID}` path, idempotent across cross-skill ordering. Internally the command enumerates the `get_current_session_id` pick (P124) plus every recent `/tmp/<system>-announced-<UUID>` UUID within a 24h mtime window, and writes the marker under each — so whichever SID the hook reads from the Write's stdin, a matching marker exists. This closes the P260 create-gate race that fires when the orchestrator main turn captures a ticket while a backgrounded iter subprocess holds the per-machine runtime-sid marker (last-writer-wins). The candidate set is bounded to recent same-machine markers — not a global fail-open (the P119 audit invariant holds: each marker still records that THIS session ran the duplicate-check grep). See `/wr-itil:manage-problem` Step 2 substep 7 for the full mechanism.
|
|
165
165
|
|
|
166
166
|
### 3. Compute the next ID
|
|
167
167
|
|
|
@@ -135,6 +135,14 @@ For each resolved trace file, classify by suffix:
|
|
|
135
135
|
|
|
136
136
|
**Why advisory and not hard-block at capture-time**: the bounded-escape contract in ADR-060 § Confirmation criterion 2 scopes I1 hard-block to `accepted → in-progress` and `→ verifying` lifecycle transitions; advisory-with-escalation only fires at `→ closed` transition. Capture-time tolerance for Closed/Parked traces is **load-bearing for the Phase 1 dogfood pass**: RFC-001 retro on P168 (P168 is `.verifying.md`) is structurally impossible without it. This is NOT a relaxation of I1; it is the bounded-escape window the ADR carved out at the right lifecycle phase. See ADR-060 § Confirmation criterion 5 (no semantic loss) + Phase 1 item 9 (retro migration as dogfood pass).
|
|
137
137
|
|
|
138
|
+
**After the trace validation passes**, write the RFC-tier create-gate marker so the `PreToolUse:Write` hook (P119, `manage-problem-enforce-create.sh`) permits the Step 5 Write of the new `docs/rfcs/RFC-*.proposed.md` file:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
wr-itil-mark-rfc-capture-gate
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
`wr-itil-mark-rfc-capture-gate` is the ADR-049 `$PATH` shim (adopter-safe — resolves its `hooks/lib` siblings relative to the script, NOT cwd; P317/RFC-009) that writes `/tmp/wr-itil-rfc-capture-grep-${SESSION_ID}` under every recent candidate SID (P260 / ADR-050 Option C — same candidate-set discipline as `wr-itil-mark-create-gate`). NEVER `source packages/...` repo-relative from a SKILL — those paths only resolve in the source monorepo, not adopter installs. The marker is per-session and idempotent, so a single write covers multiple RFC creations this session (e.g. a multi-problem-trace split).
|
|
145
|
+
|
|
138
146
|
### 3. Compute next RFC ID
|
|
139
147
|
|
|
140
148
|
Same `max(local, origin) + 1` formula as `capture-problem` Step 3, scanning `docs/rfcs/RFC-*.md` instead:
|
|
@@ -218,7 +226,7 @@ for pid_token in $(echo "$problem_trace" | tr ',' ' '); do
|
|
|
218
226
|
# Dual-tolerant ticket discovery (RFC-002 migration window).
|
|
219
227
|
problem_file=$(ls docs/problems/${pid_num}-*.md docs/problems/*/${pid_num}-*.md 2>/dev/null | head -1)
|
|
220
228
|
[ -z "$problem_file" ] && continue
|
|
221
|
-
|
|
229
|
+
wr-itil-update-problem-rfcs-section "$problem_file" docs/rfcs
|
|
222
230
|
git add "$problem_file"
|
|
223
231
|
done
|
|
224
232
|
```
|
|
@@ -229,7 +237,7 @@ The helper (`packages/itil/scripts/update-problem-rfcs-section.sh`) is idempoten
|
|
|
229
237
|
|
|
230
238
|
```bash
|
|
231
239
|
if [ -n "$stories_trace" ]; then
|
|
232
|
-
|
|
240
|
+
wr-itil-update-rfc-references-section "docs/rfcs/RFC-${next}-${slug}.proposed.md" "Stories"
|
|
233
241
|
fi
|
|
234
242
|
```
|
|
235
243
|
|
|
@@ -260,7 +260,7 @@ for pid_token in $(echo "$problem_trace" | tr ',' ' '); do
|
|
|
260
260
|
# Dual-tolerant ticket discovery (RFC-002 migration window).
|
|
261
261
|
problem_file=$(ls docs/problems/${pid_num}-*.md docs/problems/*/${pid_num}-*.md 2>/dev/null | head -1)
|
|
262
262
|
[ -z "$problem_file" ] && continue
|
|
263
|
-
|
|
263
|
+
wr-itil-update-problem-references-section "$problem_file" "Stories"
|
|
264
264
|
git add "$problem_file"
|
|
265
265
|
done
|
|
266
266
|
```
|
|
@@ -272,7 +272,7 @@ for jid_token in $(echo "$jtbd_trace" | tr ',' ' '); do
|
|
|
272
272
|
jid_num="${jid_token#JTBD-}"
|
|
273
273
|
jtbd_file=$(ls docs/jtbd/*/JTBD-${jid_num}-*.md 2>/dev/null | head -1)
|
|
274
274
|
[ -z "$jtbd_file" ] && continue
|
|
275
|
-
|
|
275
|
+
wr-itil-update-jtbd-references-section "$jtbd_file" "Stories"
|
|
276
276
|
git add "$jtbd_file"
|
|
277
277
|
done
|
|
278
278
|
```
|
|
@@ -284,7 +284,7 @@ for rid_token in $(echo "$rfc_trace" | tr ',' ' '); do
|
|
|
284
284
|
[ -z "$rid_token" ] && continue
|
|
285
285
|
rfc_file=$(ls docs/rfcs/${rid_token}-*.md 2>/dev/null | head -1)
|
|
286
286
|
[ -z "$rfc_file" ] && continue
|
|
287
|
-
|
|
287
|
+
wr-itil-update-rfc-references-section "$rfc_file" "Stories"
|
|
288
288
|
git add "$rfc_file"
|
|
289
289
|
done
|
|
290
290
|
```
|
|
@@ -170,14 +170,14 @@ for pid_token in $(echo "$problem_trace" | tr ',' ' '); do
|
|
|
170
170
|
pid_num="${pid_token#P}"
|
|
171
171
|
problem_file=$(ls docs/problems/${pid_num}-*.md docs/problems/*/${pid_num}-*.md 2>/dev/null | head -1)
|
|
172
172
|
[ -z "$problem_file" ] && continue
|
|
173
|
-
|
|
173
|
+
wr-itil-update-problem-references-section "$problem_file" "Story Maps"
|
|
174
174
|
git add "$problem_file"
|
|
175
175
|
done
|
|
176
176
|
|
|
177
177
|
for jid_token in $(echo "$jtbd_trace" | tr ',' ' '); do
|
|
178
178
|
jtbd_file=$(ls docs/jtbd/*/${jid_token}-*.md 2>/dev/null | head -1)
|
|
179
179
|
[ -z "$jtbd_file" ] && continue
|
|
180
|
-
|
|
180
|
+
wr-itil-update-jtbd-references-section "$jtbd_file" "Story Maps"
|
|
181
181
|
git add "$jtbd_file"
|
|
182
182
|
done
|
|
183
183
|
|
|
@@ -212,12 +212,11 @@ The Phase 2 working-the-problem traversal makes "implement the fix" concretely t
|
|
|
212
212
|
Before the README-reconciliation preflight (Step 0) and any other layout-dependent logic, source the shared shell migration routine and call the idempotent entrypoint:
|
|
213
213
|
|
|
214
214
|
```bash
|
|
215
|
-
|
|
216
|
-
# packages/shared/lib/migrate-problems-layout.sh per ADR-017 sync pattern).
|
|
217
|
-
source packages/itil/lib/migrate-problems-layout.sh
|
|
218
|
-
migrate_problems_to_per_state_layout "$PWD"
|
|
215
|
+
wr-itil-migrate-problems-layout "$PWD"
|
|
219
216
|
```
|
|
220
217
|
|
|
218
|
+
`wr-itil-migrate-problems-layout` is the ADR-049 `$PATH` shim (adopter-safe — resolves the canonical `lib/migrate-problems-layout.sh` relative to the script, NOT cwd; P317/RFC-009) that internalises the former inline `source packages/itil/lib/migrate-problems-layout.sh; migrate_problems_to_per_state_layout "$PWD"`. NEVER `source packages/...` repo-relative from a SKILL — those paths only resolve in the source monorepo, not adopter installs.
|
|
219
|
+
|
|
221
220
|
The routine is **idempotent and partial-migration-safe**. It no-ops when no flat-layout files (`docs/problems/*.<state>.md` at the top level of `docs/problems/`) are detected — the common case in this monorepo (post-Slice-5 T5a 2026-05-10) and in freshly-migrated adopter repos.
|
|
222
221
|
|
|
223
222
|
On a flat-layout adopter repo (first invocation post-update — JTBD-101 plugin-developer auto-migration path), the routine:
|
|
@@ -337,12 +336,12 @@ Before creating, search existing problems for similar issues. The user may not k
|
|
|
337
336
|
7. **After the grep completes** (whether duplicates were found or not), write the per-session create-gate marker so the `PreToolUse:Write` hook (`packages/itil/hooks/manage-problem-enforce-create.sh`, P119) allows the subsequent Write of the new `.open.md` file. The marker is `/tmp/manage-problem-grep-${SESSION_ID}`. Per **P260 / ADR-050 Option C**, the agent writes it under EVERY recent candidate session SID — not just one — by sourcing the discovery helpers (P124) and piping the candidate set into `mark_step2_complete_candidates`:
|
|
338
337
|
|
|
339
338
|
```bash
|
|
340
|
-
|
|
341
|
-
source packages/itil/hooks/lib/create-gate.sh
|
|
342
|
-
get_candidate_session_ids | mark_step2_complete_candidates
|
|
339
|
+
wr-itil-mark-create-gate
|
|
343
340
|
```
|
|
344
341
|
|
|
345
|
-
|
|
342
|
+
`wr-itil-mark-create-gate` is the ADR-049 `$PATH` shim (adopter-safe — resolves its `hooks/lib` siblings relative to the script, NOT cwd; P317/RFC-009) that internalises the former inline `source packages/itil/hooks/lib/{session-id,create-gate}.sh` + `get_candidate_session_ids | mark_step2_complete_candidates`. NEVER `source packages/...` repo-relative from a SKILL — those paths only resolve in the source monorepo, not adopter installs.
|
|
343
|
+
|
|
344
|
+
**Why every candidate, not one (P260 / ADR-050 Option C)**: under `/wr-itil:work-problems` the orchestrator main turn fires PreToolUse hooks concurrently with its backgrounded iter subprocess (Step 5). Both sessions write the same per-machine runtime-sid marker (last-writer-wins), so the single-SID `get_current_session_id` can return the subprocess SID while the orchestrator's Write carries the orchestrator SID on its stdin — marker mismatch, create-gate deny. No agent-side algorithm can predict the right single SID from filesystem state alone (ADR-050 §Context). The command instead enumerates EVERY candidate SID the hook might read — the `get_current_session_id` pick (env-var > runtime-sid > announce-marker priority, P124) PLUS every recent `/tmp/<system>-announced-<UUID>` UUID within a 24h mtime window (ADR-038 announce markers, set on prompt 1 of every session by architect / jtbd / tdd / style-guide / voice-tone / itil-assistant-gate / itil-correction-detect hooks) — and writes the marker under each. Whichever SID the hook reads from the Write's stdin, a matching marker provably exists. The candidate set is **bounded** to recent same-machine announce markers + the runtime-sid value — NOT a global fail-open: the P119 audit invariant holds (every marker still records that THIS session ran the duplicate-check grep). The marker is per-session, so a single write covers all new tickets for the rest of this session, enabling Step 4b multi-concern splits and same-session unrelated-ticket creation without re-running the grep.
|
|
346
345
|
|
|
347
346
|
**Why helpers instead of inline `${CLAUDE_SESSION_ID:-default}`**: the agent's process does NOT export `CLAUDE_SESSION_ID` today; the hook side reads `session_id` from its stdin JSON payload (per the Claude Code PreToolUse contract). The prior fallback wrote the marker under `default` while the hook checked the real UUID — mismatch caused the Write deny on every first ticket of a session until the agent ad-hoc scraped a UUID-bearing marker. The helpers canonicalise that scrape so every agent context discovers candidate SIDs the same way. P124.
|
|
348
347
|
|
|
@@ -147,7 +147,7 @@ for pid_token in $(awk '/^problems:/{gsub(/[][]/,"");gsub(/,/,"\n");for(i=2;i<=N
|
|
|
147
147
|
# subdir (`docs/problems/<state>/<NNN>-<title>.md`) layouts.
|
|
148
148
|
problem_file=$(ls docs/problems/${pid_num}-*.md docs/problems/*/${pid_num}-*.md 2>/dev/null | head -1)
|
|
149
149
|
[ -z "$problem_file" ] && continue
|
|
150
|
-
|
|
150
|
+
wr-itil-update-problem-rfcs-section "$problem_file" docs/rfcs
|
|
151
151
|
git add "$problem_file"
|
|
152
152
|
done
|
|
153
153
|
```
|
|
@@ -164,7 +164,7 @@ The trailer hook (`itil-rfc-trailer-advisory.sh`) sits on top of this skill-side
|
|
|
164
164
|
Per ADR-060 line 270 + line 296: every transition that touches the RFC body refreshes the RFC's own `## Stories` body section from its frontmatter `stories:` array. The forward-trace surface renders the ordered execution sequence as inline links to the story files, lazy-empty when `stories: []` (an RFC not decomposed into stories). The helper is the Slice 2b sibling `update-rfc-references-section.sh`:
|
|
165
165
|
|
|
166
166
|
```bash
|
|
167
|
-
|
|
167
|
+
wr-itil-update-rfc-references-section "$rfc_file" "Stories"
|
|
168
168
|
```
|
|
169
169
|
|
|
170
170
|
Idempotent + lazy-empty per the Slice 2a/2b contract. Run after the rename + frontmatter edit so the section reflects the post-transition `stories:` shape. Stage the RFC file (already staged for the lifecycle transition; the helper modifies the same file in-place).
|
|
@@ -197,7 +197,7 @@ Batch re-rank all RFCs and refresh `docs/rfcs/README.md`.
|
|
|
197
197
|
```bash
|
|
198
198
|
# Aggregate the union of P<NNN> across all RFCs touched in this review.
|
|
199
199
|
for problem_file in $(printf '%s\n' "${touched_problem_files[@]}" | sort -u); do
|
|
200
|
-
|
|
200
|
+
wr-itil-update-problem-rfcs-section "$problem_file" docs/rfcs
|
|
201
201
|
git add "$problem_file"
|
|
202
202
|
done
|
|
203
203
|
```
|
|
@@ -138,7 +138,7 @@ for pid_token in $(awk '/^problems:/{gsub(/[][]/,""); gsub(/,/," "); for(i=2;i<=
|
|
|
138
138
|
pid_num="${pid_token#P}"
|
|
139
139
|
problem_file=$(ls docs/problems/${pid_num}-*.md docs/problems/*/${pid_num}-*.md 2>/dev/null | head -1)
|
|
140
140
|
[ -z "$problem_file" ] && continue
|
|
141
|
-
|
|
141
|
+
wr-itil-update-problem-references-section "$problem_file" "Stories"
|
|
142
142
|
git add "$problem_file"
|
|
143
143
|
done
|
|
144
144
|
|
|
@@ -146,7 +146,7 @@ done
|
|
|
146
146
|
for jid in $(awk '/^jtbd:/{gsub(/[][]/,""); gsub(/,/," "); for(i=2;i<=NF;i++)print $i; exit}' "$story_file"); do
|
|
147
147
|
jtbd_file=$(ls docs/jtbd/*/${jid}-*.md 2>/dev/null | head -1)
|
|
148
148
|
[ -z "$jtbd_file" ] && continue
|
|
149
|
-
|
|
149
|
+
wr-itil-update-jtbd-references-section "$jtbd_file" "Stories"
|
|
150
150
|
git add "$jtbd_file"
|
|
151
151
|
done
|
|
152
152
|
|
|
@@ -154,7 +154,7 @@ done
|
|
|
154
154
|
for rid in $(awk '/^rfcs:/{gsub(/[][]/,""); gsub(/,/," "); for(i=2;i<=NF;i++)print $i; exit}' "$story_file"); do
|
|
155
155
|
rfc_file=$(ls docs/rfcs/${rid}-*.md 2>/dev/null | head -1)
|
|
156
156
|
[ -z "$rfc_file" ] && continue
|
|
157
|
-
|
|
157
|
+
wr-itil-update-rfc-references-section "$rfc_file" "Stories"
|
|
158
158
|
git add "$rfc_file"
|
|
159
159
|
done
|
|
160
160
|
|
|
@@ -104,11 +104,11 @@ for pid_token in $(grep -oE '<meta name="problems" content="[^"]*"' "$map_file"
|
|
|
104
104
|
pid_num="${pid_token#P}"
|
|
105
105
|
problem_file=$(ls docs/problems/${pid_num}-*.md docs/problems/*/${pid_num}-*.md 2>/dev/null | head -1)
|
|
106
106
|
[ -z "$problem_file" ] && continue
|
|
107
|
-
|
|
107
|
+
wr-itil-update-problem-references-section "$problem_file" "Story Maps"
|
|
108
108
|
git add "$problem_file"
|
|
109
109
|
done
|
|
110
110
|
|
|
111
|
-
# Same for JTBDs via update-jtbd-references-section
|
|
111
|
+
# Same for JTBDs via wr-itil-update-jtbd-references-section "Story Maps"
|
|
112
112
|
```
|
|
113
113
|
|
|
114
114
|
Per architect amend finding 2 on Slice 7: story-map HTML files do NOT carry an auto-maintained markdown reverse-trace section themselves (the `<a class="slice">` data-attribute traces are authored manually during backbone design). No reverse-trace refresh on the map itself; reverse-trace only flows OUT to problem + JTBD parents.
|
|
@@ -43,12 +43,12 @@ setup() {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
@test "manage-story-map: SKILL.md names reverse-trace refresh on problem parents via Story Maps section" {
|
|
46
|
-
run grep -E 'update-problem-references-section
|
|
46
|
+
run grep -E 'wr-itil-update-problem-references-section.*Story Maps' "$SKILL_FILE"
|
|
47
47
|
[ "$status" -eq 0 ]
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
@test "manage-story-map: SKILL.md names reverse-trace refresh on JTBD parents via Story Maps section" {
|
|
51
|
-
run grep -E 'update-jtbd-references-section
|
|
51
|
+
run grep -E 'wr-itil-update-jtbd-references-section.*Story Maps' "$SKILL_FILE"
|
|
52
52
|
[ "$status" -eq 0 ]
|
|
53
53
|
}
|
|
54
54
|
|
|
@@ -56,11 +56,11 @@ For reverse-trace drift entries — invoke the appropriate Slice 2a/2b helper fo
|
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
58
|
# Problem parent
|
|
59
|
-
|
|
59
|
+
wr-itil-update-problem-references-section "$problem_file" "Stories"
|
|
60
60
|
# RFC parent
|
|
61
|
-
|
|
61
|
+
wr-itil-update-rfc-references-section "$rfc_file" "Stories"
|
|
62
62
|
# JTBD parent
|
|
63
|
-
|
|
63
|
+
wr-itil-update-jtbd-references-section "$jtbd_file" "Stories"
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
### 4. Verify + commit
|
|
@@ -127,10 +127,11 @@ This is a robustness layer ON TOP of P094 + P062, not a supersession — both pe
|
|
|
127
127
|
After Step 0's fetch/divergence preflight and the README reconciliation block but **before** Step 1's backlog scan, source the shared shell migration routine and call the idempotent entrypoint:
|
|
128
128
|
|
|
129
129
|
```bash
|
|
130
|
-
|
|
131
|
-
migrate_problems_to_per_state_layout "$PWD"
|
|
130
|
+
wr-itil-migrate-problems-layout "$PWD"
|
|
132
131
|
```
|
|
133
132
|
|
|
133
|
+
`wr-itil-migrate-problems-layout` is the ADR-049 `$PATH` shim (adopter-safe — resolves `lib/migrate-problems-layout.sh` relative to the script, NOT cwd; P317/RFC-009) that internalises the former inline `source packages/itil/lib/migrate-problems-layout.sh; migrate_problems_to_per_state_layout "$PWD"`. NEVER `source packages/...` repo-relative from a SKILL — those paths only resolve in the source monorepo, not adopter installs.
|
|
134
|
+
|
|
134
135
|
The routine is **idempotent and partial-migration-safe**. It no-ops when no flat-layout files (`docs/problems/*.<state>.md` at the top level of `docs/problems/`) are detected — the common case post-Slice-5 T5a in this monorepo and in freshly-migrated adopter repos.
|
|
135
136
|
|
|
136
137
|
**Closes the Step 1 false-zero defect** (per ADR-031 § Backward Compatibility line 126 "Why both skills"): Step 1 enumerates BEFORE delegating to manage-problem. On a flat-layout adopter repo, the post-ADR-031 Step 1 glob would return zero matches at the per-state shape and stop-condition #1 would fire incorrectly — the orchestrator would exit with a false "nothing to do" signal, never reaching manage-problem's Step 0a auto-migrate. Wiring auto-migrate here at Step 0a is structurally required, not an optimisation.
|
|
@@ -154,10 +155,11 @@ After Step 0a's auto-migrate and before Step 1's backlog scan, check whether the
|
|
|
154
155
|
**Mechanism:**
|
|
155
156
|
|
|
156
157
|
```bash
|
|
157
|
-
|
|
158
|
-
preflight_reason="$(should_promote_inbound_discovery_preflight "$PWD")"
|
|
158
|
+
preflight_reason="$(wr-itil-check-upstream-cache-staleness "$PWD")"
|
|
159
159
|
```
|
|
160
160
|
|
|
161
|
+
`wr-itil-check-upstream-cache-staleness` is the ADR-049 `$PATH` shim (adopter-safe — resolves `lib/check-upstream-cache-staleness.sh` relative to the script, NOT cwd; P317/RFC-009) that internalises the former inline `source ...; should_promote_inbound_discovery_preflight "$PWD"` and echoes the result. NEVER `source packages/...` repo-relative from a SKILL — those paths only resolve in the source monorepo, not adopter installs.
|
|
162
|
+
|
|
161
163
|
The helper returns one of five outcomes (contract documented at `packages/itil/lib/check-upstream-cache-staleness.sh` + asserted by `packages/itil/skills/work-problems/test/work-problems-step-0b-cache-staleness-behavioural.bats`):
|
|
162
164
|
|
|
163
165
|
| `preflight_reason` | Action |
|