@windyroad/itil 0.61.1 → 0.61.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.
Files changed (171) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/package.json +7 -2
  3. package/agents/test/fixtures/proceed-new-genuinely-new.md +0 -43
  4. package/agents/test/fixtures/proceed-new-subtle-sibling.md +0 -47
  5. package/agents/test/fixtures/regression-p347-vs-p346.md +0 -54
  6. package/agents/test/hang-off-check.bats +0 -225
  7. package/hooks/test/block-list.bats +0 -153
  8. package/hooks/test/command-detect.bats +0 -181
  9. package/hooks/test/itil-assistant-output-gate.bats +0 -114
  10. package/hooks/test/itil-assistant-output-review.bats +0 -224
  11. package/hooks/test/itil-bash-polling-antipattern-detect.bats +0 -154
  12. package/hooks/test/itil-changeset-discipline.bats +0 -603
  13. package/hooks/test/itil-claude-space-protection.bats +0 -294
  14. package/hooks/test/itil-commit-trailer-transition-advisory.bats +0 -80
  15. package/hooks/test/itil-correction-detect.bats +0 -189
  16. package/hooks/test/itil-deferral-cadence-gate.bats +0 -187
  17. package/hooks/test/itil-fictional-defer-detect.bats +0 -292
  18. package/hooks/test/itil-fix-title-lifecycle-advisory.bats +0 -129
  19. package/hooks/test/itil-mid-loop-ask-detect.bats +0 -220
  20. package/hooks/test/itil-no-implement-draft-gate.bats +0 -210
  21. package/hooks/test/itil-pending-questions-surface.bats +0 -307
  22. package/hooks/test/itil-readme-refresh-discipline.bats +0 -642
  23. package/hooks/test/itil-rfc-oversight-nudge.bats +0 -83
  24. package/hooks/test/itil-rfc-trailer-advisory.bats +0 -375
  25. package/hooks/test/itil-story-mirror-migration-nudge.bats +0 -122
  26. package/hooks/test/manage-problem-enforce-create.bats +0 -424
  27. package/hooks/test/p057-staging-trap-detect.bats +0 -231
  28. package/hooks/test/pre-publish-intake-gate.bats +0 -144
  29. package/hooks/test/runtime-sid-marker.bats +0 -90
  30. package/hooks/test/session-id.bats +0 -370
  31. package/scripts/migrate-problems-add-type.sh +0 -116
  32. package/scripts/test/catchup-scan.bats +0 -274
  33. package/scripts/test/check-afk-accept-eligible.bats +0 -310
  34. package/scripts/test/check-fail-soft-skip-discipline.bats +0 -172
  35. package/scripts/test/check-fix-rfc-trace.bats +0 -164
  36. package/scripts/test/check-locale-discipline.bats +0 -291
  37. package/scripts/test/check-problems-readme-budget.bats +0 -192
  38. package/scripts/test/check-rfc-has-stories.bats +0 -69
  39. package/scripts/test/check-rfc-rejected-alternatives.bats +0 -108
  40. package/scripts/test/check-rfc-stories-ratified.bats +0 -82
  41. package/scripts/test/check-upstream-responses.bats +0 -503
  42. package/scripts/test/classify-readme-drift.bats +0 -392
  43. package/scripts/test/derive-first-dispatch.bats +0 -274
  44. package/scripts/test/derive-release-vehicle.bats +0 -454
  45. package/scripts/test/detect-unratified-stories-maps.bats +0 -60
  46. package/scripts/test/dual-tolerant-glob-rfc-002-t2.bats +0 -309
  47. package/scripts/test/effort-tally.bats +0 -170
  48. package/scripts/test/evaluate-relevance.bats +0 -773
  49. package/scripts/test/kind-a-commands.bats +0 -46
  50. package/scripts/test/mark-create-gate.bats +0 -59
  51. package/scripts/test/mark-story-oversight-confirmed.bats +0 -53
  52. package/scripts/test/migrate-problems-add-type.bats +0 -280
  53. package/scripts/test/migrate-story-status-mirror.bats +0 -167
  54. package/scripts/test/no-type-regression-guard.bats +0 -74
  55. package/scripts/test/oversight-mirror-corpus-lint.bats +0 -150
  56. package/scripts/test/plugin-exercise-index.bats +0 -386
  57. package/scripts/test/plugin-maturity-doc-lint.bats +0 -470
  58. package/scripts/test/plugin-maturity-populate.bats +0 -631
  59. package/scripts/test/plugin-maturity-render.bats +0 -469
  60. package/scripts/test/plugin-validate-ci-gate.bats +0 -208
  61. package/scripts/test/reconcile-readme.bats +0 -1007
  62. package/scripts/test/reconcile-rfcs.bats +0 -496
  63. package/scripts/test/reconcile-stories.bats +0 -173
  64. package/scripts/test/reconcile-story-maps.bats +0 -74
  65. package/scripts/test/release-watch-poll-loop.bats +0 -180
  66. package/scripts/test/resolve-governance-plugin-dirs.bats +0 -78
  67. package/scripts/test/rfc-stories-extension.bats +0 -175
  68. package/scripts/test/skill-invocations.bats +0 -535
  69. package/scripts/test/skill-md-dual-tolerant-coverage-rfc-002-t3.bats +0 -374
  70. package/scripts/test/story-oversight-lib.bats +0 -190
  71. package/scripts/test/update-jtbd-references-related-problems.bats +0 -178
  72. package/scripts/test/update-problem-references-section.bats +0 -242
  73. package/scripts/test/update-problem-rfcs-section.bats +0 -242
  74. package/scripts/test/update-references-section-sibling-helpers.bats +0 -80
  75. package/scripts/test/update-rfc-commits-section.bats +0 -77
  76. package/scripts/test/verify-iter-summary.bats +0 -196
  77. package/scripts/test/working-the-problem-traversal.bats +0 -116
  78. package/skills/capture-problem/test/capture-problem-step-1-5b-jtbd-trace.bats +0 -398
  79. package/skills/capture-problem/test/capture-problem.bats +0 -389
  80. package/skills/capture-story/test/capture-story-behavioural.bats +0 -317
  81. package/skills/capture-story-map/test/capture-story-map-behavioural.bats +0 -98
  82. package/skills/close-incident/test/close-incident-contract.bats +0 -146
  83. package/skills/link-incident/test/link-incident-contract.bats +0 -125
  84. package/skills/list-incidents/test/list-incidents-contract.bats +0 -115
  85. package/skills/list-problems/test/list-problems-contract.bats +0 -100
  86. package/skills/list-stories/test/list-stories-contract.bats +0 -127
  87. package/skills/list-story-maps/test/list-story-maps-contract.bats +0 -46
  88. package/skills/manage-incident/test/manage-incident-adr-044-contract.bats +0 -206
  89. package/skills/manage-incident/test/manage-incident-close-forwarder.bats +0 -67
  90. package/skills/manage-incident/test/manage-incident-link-forwarder.bats +0 -67
  91. package/skills/manage-incident/test/manage-incident-list-forwarder.bats +0 -68
  92. package/skills/manage-incident/test/manage-incident-mitigate-forwarder.bats +0 -66
  93. package/skills/manage-incident/test/manage-incident-restore-forwarder.bats +0 -66
  94. package/skills/manage-incident/test/manage-incident.bats +0 -171
  95. package/skills/manage-problem/test/manage-problem-adr-044-step4-derive-first.bats +0 -151
  96. package/skills/manage-problem/test/manage-problem-auto-migrate-step.bats +0 -53
  97. package/skills/manage-problem/test/manage-problem-concern-boundary.bats +0 -64
  98. package/skills/manage-problem/test/manage-problem-effort-buckets.bats +0 -56
  99. package/skills/manage-problem/test/manage-problem-external-root-cause-detection.bats +0 -119
  100. package/skills/manage-problem/test/manage-problem-first-run-intake-prompt.bats +0 -43
  101. package/skills/manage-problem/test/manage-problem-git-mv-restage-reminder.bats +0 -48
  102. package/skills/manage-problem/test/manage-problem-id-collision-guard.bats +0 -39
  103. package/skills/manage-problem/test/manage-problem-list-forwarder.bats +0 -66
  104. package/skills/manage-problem/test/manage-problem-next-id-origin-lookup.bats +0 -50
  105. package/skills/manage-problem/test/manage-problem-no-prose-options.bats +0 -74
  106. package/skills/manage-problem/test/manage-problem-output-formatting.bats +0 -30
  107. package/skills/manage-problem/test/manage-problem-parked-and-cache.bats +0 -73
  108. package/skills/manage-problem/test/manage-problem-readme-refresh-on-transition.bats +0 -62
  109. package/skills/manage-problem/test/manage-problem-readme-tie-break-order.bats +0 -318
  110. package/skills/manage-problem/test/manage-problem-readme-vq-sort-order.bats +0 -206
  111. package/skills/manage-problem/test/manage-problem-release-vehicle-seed.bats +0 -83
  112. package/skills/manage-problem/test/manage-problem-review-forwarder.bats +0 -71
  113. package/skills/manage-problem/test/manage-problem-step-9d-recovery-path.bats +0 -97
  114. package/skills/manage-problem/test/manage-problem-transition-forwarder.bats +0 -96
  115. package/skills/manage-problem/test/manage-problem-transitive-dependencies.bats +0 -365
  116. package/skills/manage-problem/test/manage-problem-verification-detection.bats +0 -64
  117. package/skills/manage-problem/test/manage-problem-verification-pending.bats +0 -114
  118. package/skills/manage-problem/test/manage-problem-work-forwarder.bats +0 -88
  119. package/skills/manage-story/test/manage-story-contract.bats +0 -174
  120. package/skills/manage-story-map/test/manage-story-map-contract.bats +0 -63
  121. package/skills/mitigate-incident/test/mitigate-incident-contract.bats +0 -258
  122. package/skills/reconcile-readme/test/reconcile-readme-contract.bats +0 -201
  123. package/skills/report-upstream/test/report-upstream-contract.bats +0 -394
  124. package/skills/restore-incident/test/restore-incident-contract.bats +0 -170
  125. package/skills/review-problems/test/inbound-channels-cache-shape.bats +0 -127
  126. package/skills/review-problems/test/inbound-discovery-contract.bats +0 -383
  127. package/skills/review-problems/test/jtbd-301-verdict-shape-contract.bats +0 -225
  128. package/skills/review-problems/test/review-problems-contract.bats +0 -235
  129. package/skills/review-problems/test/review-problems-likely-verified-cell-shape.bats +0 -229
  130. package/skills/scaffold-intake/test/scaffold-intake-contract.bats +0 -126
  131. package/skills/scaffold-intake/test/scaffold-intake-fixture.bats +0 -164
  132. package/skills/scaffold-intake/test/scaffold-intake-secrets-absent.bats +0 -87
  133. package/skills/transition-problem/test/transition-problem-contract.bats +0 -285
  134. package/skills/transition-problems/test/transition-problems-contract.bats +0 -331
  135. package/skills/update-upstream/test/update-upstream-contract.bats +0 -375
  136. package/skills/work-problem/test/work-problem-contract.bats +0 -294
  137. package/skills/work-problems/test/work-problems-above-appetite-remediation.bats +0 -139
  138. package/skills/work-problems/test/work-problems-adr-013-rule-6-p352-amendment.bats +0 -166
  139. package/skills/work-problems/test/work-problems-auto-migrate-step.bats +0 -57
  140. package/skills/work-problems/test/work-problems-cost-logging.bats +0 -109
  141. package/skills/work-problems/test/work-problems-deviation-candidate-shape.bats +0 -121
  142. package/skills/work-problems/test/work-problems-first-run-intake-prompt.bats +0 -36
  143. package/skills/work-problems/test/work-problems-inter-iteration-verify.bats +0 -59
  144. package/skills/work-problems/test/work-problems-mid-loop-userpromptsubmit-handler.bats +0 -69
  145. package/skills/work-problems/test/work-problems-no-mid-loop-asking.bats +0 -192
  146. package/skills/work-problems/test/work-problems-p341-pre-all-done-gate.bats +0 -122
  147. package/skills/work-problems/test/work-problems-p342-r007-derive-then-pass-flags.bats +0 -170
  148. package/skills/work-problems/test/work-problems-p342-retro-auto-ticket-carveout.bats +0 -120
  149. package/skills/work-problems/test/work-problems-preflight-failure-handling.bats +0 -248
  150. package/skills/work-problems/test/work-problems-preflight-session-continuity.bats +0 -139
  151. package/skills/work-problems/test/work-problems-preflight.bats +0 -69
  152. package/skills/work-problems/test/work-problems-release-cadence.bats +0 -63
  153. package/skills/work-problems/test/work-problems-step-0-iter-error-staleness.bats +0 -93
  154. package/skills/work-problems/test/work-problems-step-0b-cache-staleness-behavioural.bats +0 -138
  155. package/skills/work-problems/test/work-problems-step-0c-deferred-placeholder-staleness-behavioural.bats +0 -238
  156. package/skills/work-problems/test/work-problems-step-0d-outbound-responses-staleness-behavioural.bats +0 -174
  157. package/skills/work-problems/test/work-problems-step-2-5-routing.bats +0 -80
  158. package/skills/work-problems/test/work-problems-step-2-5b-cross-halt-routing.bats +0 -149
  159. package/skills/work-problems/test/work-problems-step-3-5-jtbd-ratification-predicate.bats +0 -191
  160. package/skills/work-problems/test/work-problems-step-5-bats-polling-discipline.bats +0 -91
  161. package/skills/work-problems/test/work-problems-step-5-delegation.bats +0 -333
  162. package/skills/work-problems/test/work-problems-step-5-idle-timeout-sigterm.bats +0 -421
  163. package/skills/work-problems/test/work-problems-step-5-is-error-transient-halt.bats +0 -278
  164. package/skills/work-problems/test/work-problems-step-5-iter-changeset-required.bats +0 -95
  165. package/skills/work-problems/test/work-problems-step-5-prompt-body-re-grounding.bats +0 -128
  166. package/skills/work-problems/test/work-problems-step-5-stream-timeout-salvage.bats +0 -251
  167. package/skills/work-problems/test/work-problems-step-6-5-always-drain.bats +0 -203
  168. package/skills/work-problems/test/work-problems-step-6-5-cache-refresh-chain.bats +0 -174
  169. package/skills/work-problems/test/work-problems-step-6-5-fix-and-continue.bats +0 -254
  170. package/skills/work-problems/test/work-problems-step-6-5-postrelease-kv-callback.bats +0 -209
  171. package/skills/work-problems/test/work-problems-stop-condition-questions.bats +0 -85
@@ -1,307 +0,0 @@
1
- #!/usr/bin/env bats
2
- # Behavioural fixtures for itil-pending-questions-surface.sh (P157).
3
- #
4
- # SessionStart hook that reads the AFK-loop-accumulated outstanding-questions
5
- # JSONL queue at .afk-run-state/outstanding-questions.jsonl, ranks entries
6
- # per ADR-044 6-class taxonomy, and emits an additionalContext directive on
7
- # stdout for the agent to surface via AskUserQuestion (batched <=4).
8
- #
9
- # Per ADR-052 (behavioural-tests-default), these tests exercise the hook's
10
- # observable stdout / exit-code behaviour against fixture queue files —
11
- # NOT the prose contents of the script itself.
12
- #
13
- # Behavioural surfaces under test:
14
- # 1. Silent-on-no-content per ADR-040 Mechanism step 1 — missing or empty
15
- # queue file produces zero stdout and exits 0.
16
- # 2. Non-empty queue produces additionalContext naming the entries.
17
- # 3. ADR-044 6-class precedence — when multiple categories present,
18
- # deviation-approval ranks first; correction-followup ranks last.
19
- # 4. Deduplication — identical entries (same category + question + ticket_id)
20
- # collapse to one.
21
- # 5. Batching directive — when N > 4, output names the AskUserQuestion
22
- # batched-call cap.
23
- # 6. Cleanup directive — output instructs the agent to truncate resolved
24
- # entries from the queue file.
25
- # 7. AFK-iter cross-context-leak prevention — WR_SUPPRESS_PENDING_QUESTIONS=1
26
- # env var forces silent exit even when queue is non-empty.
27
- #
28
- # @problem P157
29
- # @jtbd JTBD-006 (progress backlog while AFK — surface accumulated questions
30
- # on session resume)
31
- # @jtbd JTBD-001 (enforce governance without slowing down — direction-class
32
- # observations resolve before user begins foreground work)
33
- # @jtbd JTBD-101 (extend the suite — sibling SessionStart hook reuses
34
- # ADR-040 silent-on-no-content shape)
35
- # @adr ADR-032 (governance skill invocation patterns — P157 amendment for
36
- # JSONL-queue SessionStart variant)
37
- # @adr ADR-040 (session-start briefing surface — SessionStart precedent +
38
- # silent-on-no-content shape)
39
- # @adr ADR-044 (decision-delegation contract — 6-class taxonomy precedence)
40
- # @adr ADR-052 (behavioural-tests-default — these tests exercise hook
41
- # stdout / exit-code, not script prose)
42
-
43
- setup() {
44
- REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../.." && pwd)"
45
- HOOK_SCRIPT="${REPO_ROOT}/packages/itil/hooks/itil-pending-questions-surface.sh"
46
-
47
- TMPROOT=$(mktemp -d)
48
- mkdir -p "$TMPROOT/.afk-run-state"
49
- QUEUE_FILE="$TMPROOT/.afk-run-state/outstanding-questions.jsonl"
50
-
51
- export CLAUDE_PROJECT_DIR="$TMPROOT"
52
- unset WR_SUPPRESS_PENDING_QUESTIONS
53
- }
54
-
55
- teardown() {
56
- rm -rf "$TMPROOT"
57
- unset CLAUDE_PROJECT_DIR WR_SUPPRESS_PENDING_QUESTIONS
58
- }
59
-
60
- # ---------------------------------------------------------------------------
61
- # Existence — minimum surface required for hooks.json to wire it up.
62
- # ---------------------------------------------------------------------------
63
-
64
- @test "hook script exists and is executable" {
65
- [ -f "$HOOK_SCRIPT" ]
66
- [ -x "$HOOK_SCRIPT" ]
67
- }
68
-
69
- @test "hooks.json registers the SessionStart hook with matcher startup" {
70
- HOOKS_JSON="${REPO_ROOT}/packages/itil/hooks/hooks.json"
71
- run jq -r '.hooks.SessionStart[] | select(.matcher == "startup") | .hooks[].command' "$HOOKS_JSON"
72
- [ "$status" -eq 0 ]
73
- echo "$output" | grep -qF 'itil-pending-questions-surface.sh'
74
- }
75
-
76
- # ---------------------------------------------------------------------------
77
- # Silent-on-no-content per ADR-040 Mechanism step 1.
78
- # ---------------------------------------------------------------------------
79
-
80
- @test "missing queue file: silent exit 0" {
81
- # No queue file at all (typical state for projects that have never run AFK).
82
- rm -f "$QUEUE_FILE"
83
- run "$HOOK_SCRIPT"
84
- [ "$status" -eq 0 ]
85
- [ -z "$output" ]
86
- }
87
-
88
- @test "empty queue file: silent exit 0" {
89
- : > "$QUEUE_FILE"
90
- run "$HOOK_SCRIPT"
91
- [ "$status" -eq 0 ]
92
- [ -z "$output" ]
93
- }
94
-
95
- @test "queue with only whitespace lines: silent exit 0" {
96
- printf '\n \n\t\n' > "$QUEUE_FILE"
97
- run "$HOOK_SCRIPT"
98
- [ "$status" -eq 0 ]
99
- [ -z "$output" ]
100
- }
101
-
102
- # ---------------------------------------------------------------------------
103
- # Non-empty queue → additionalContext emitted.
104
- # ---------------------------------------------------------------------------
105
-
106
- @test "single entry: additionalContext names the question and ticket_id" {
107
- cat > "$QUEUE_FILE" <<'JSONL'
108
- {"category":"direction","question":"Pick A or B for the storage layer?","context":"iter1 P200","ticket_id":"P200"}
109
- JSONL
110
- run "$HOOK_SCRIPT"
111
- [ "$status" -eq 0 ]
112
- echo "$output" | grep -qF 'Pick A or B for the storage layer?'
113
- echo "$output" | grep -qF 'P200'
114
- }
115
-
116
- @test "single entry: output cites the queue file path so user can inspect" {
117
- cat > "$QUEUE_FILE" <<'JSONL'
118
- {"category":"direction","question":"Q1","context":"c1","ticket_id":"P201"}
119
- JSONL
120
- run "$HOOK_SCRIPT"
121
- [ "$status" -eq 0 ]
122
- echo "$output" | grep -qF '.afk-run-state/outstanding-questions.jsonl'
123
- }
124
-
125
- # ---------------------------------------------------------------------------
126
- # ADR-044 6-class precedence ordering.
127
- # ---------------------------------------------------------------------------
128
-
129
- @test "ranking: deviation-approval ranks first among mixed categories" {
130
- cat > "$QUEUE_FILE" <<'JSONL'
131
- {"category":"correction-followup","question":"low-rank Q","context":"c","ticket_id":"P301"}
132
- {"category":"direction","question":"mid-rank Q","context":"c","ticket_id":"P302"}
133
- {"category":"deviation-approval","existing_decision":"ADR-001","contradicting_evidence":"ev","proposed_shape":"amend","rationale":"r","ticket_id":"P303"}
134
- JSONL
135
- run "$HOOK_SCRIPT"
136
- [ "$status" -eq 0 ]
137
- # The deviation-approval entry's rationale must appear before the direction Q
138
- # in the output (precedence: deviation-approval > direction > correction-followup).
139
- DEVIATION_LINE=$(echo "$output" | grep -n 'P303' | head -1 | cut -d: -f1)
140
- DIRECTION_LINE=$(echo "$output" | grep -n 'mid-rank Q' | head -1 | cut -d: -f1)
141
- CORRECTION_LINE=$(echo "$output" | grep -n 'low-rank Q' | head -1 | cut -d: -f1)
142
- [ -n "$DEVIATION_LINE" ]
143
- [ -n "$DIRECTION_LINE" ]
144
- [ -n "$CORRECTION_LINE" ]
145
- [ "$DEVIATION_LINE" -lt "$DIRECTION_LINE" ]
146
- [ "$DIRECTION_LINE" -lt "$CORRECTION_LINE" ]
147
- }
148
-
149
- @test "ranking: full 6-class precedence is deviation > direction > one-time > silent-framework > taste > correction" {
150
- cat > "$QUEUE_FILE" <<'JSONL'
151
- {"category":"taste","question":"q-taste","context":"c","ticket_id":"P401"}
152
- {"category":"correction-followup","question":"q-correction","context":"c","ticket_id":"P402"}
153
- {"category":"silent-framework","question":"q-silent","context":"c","ticket_id":"P403"}
154
- {"category":"one-time-override","question":"q-onetime","context":"c","ticket_id":"P404"}
155
- {"category":"direction","question":"q-direction","context":"c","ticket_id":"P405"}
156
- {"category":"deviation-approval","existing_decision":"ADR-X","contradicting_evidence":"ev","proposed_shape":"amend","rationale":"q-deviation","ticket_id":"P406"}
157
- JSONL
158
- run "$HOOK_SCRIPT"
159
- [ "$status" -eq 0 ]
160
- # Capture the line number of each category-tagged ticket marker; assert order.
161
- L1=$(echo "$output" | grep -n 'P406' | head -1 | cut -d: -f1)
162
- L2=$(echo "$output" | grep -n 'q-direction' | head -1 | cut -d: -f1)
163
- L3=$(echo "$output" | grep -n 'q-onetime' | head -1 | cut -d: -f1)
164
- L4=$(echo "$output" | grep -n 'q-silent' | head -1 | cut -d: -f1)
165
- L5=$(echo "$output" | grep -n 'q-taste' | head -1 | cut -d: -f1)
166
- L6=$(echo "$output" | grep -n 'q-correction' | head -1 | cut -d: -f1)
167
- [ "$L1" -lt "$L2" ]
168
- [ "$L2" -lt "$L3" ]
169
- [ "$L3" -lt "$L4" ]
170
- [ "$L4" -lt "$L5" ]
171
- [ "$L5" -lt "$L6" ]
172
- }
173
-
174
- # ---------------------------------------------------------------------------
175
- # Deduplication of identical entries.
176
- # ---------------------------------------------------------------------------
177
-
178
- @test "dedup: identical entries (same category+question+ticket_id) collapse to one" {
179
- cat > "$QUEUE_FILE" <<'JSONL'
180
- {"category":"direction","question":"Same Q","context":"c","ticket_id":"P500"}
181
- {"category":"direction","question":"Same Q","context":"c","ticket_id":"P500"}
182
- {"category":"direction","question":"Same Q","context":"different-context-different-iter","ticket_id":"P500"}
183
- JSONL
184
- run "$HOOK_SCRIPT"
185
- [ "$status" -eq 0 ]
186
- # "Same Q" should appear exactly once in the output (after dedup).
187
- COUNT=$(echo "$output" | grep -cF 'Same Q')
188
- [ "$COUNT" -eq 1 ]
189
- }
190
-
191
- @test "dedup: different question text on same ticket survives as two entries" {
192
- cat > "$QUEUE_FILE" <<'JSONL'
193
- {"category":"direction","question":"Question one","context":"c","ticket_id":"P501"}
194
- {"category":"direction","question":"Question two","context":"c","ticket_id":"P501"}
195
- JSONL
196
- run "$HOOK_SCRIPT"
197
- [ "$status" -eq 0 ]
198
- echo "$output" | grep -qF 'Question one'
199
- echo "$output" | grep -qF 'Question two'
200
- }
201
-
202
- # ---------------------------------------------------------------------------
203
- # Batching directive — names the AskUserQuestion <=4 cap when N > 4.
204
- # ---------------------------------------------------------------------------
205
-
206
- @test "batching: output names AskUserQuestion when entries present" {
207
- cat > "$QUEUE_FILE" <<'JSONL'
208
- {"category":"direction","question":"Q1","context":"c","ticket_id":"P600"}
209
- JSONL
210
- run "$HOOK_SCRIPT"
211
- [ "$status" -eq 0 ]
212
- echo "$output" | grep -qiE 'AskUserQuestion'
213
- }
214
-
215
- @test "batching: directive cites the <=4-per-call cap" {
216
- # 5 entries should trigger the batching note since AskUserQuestion caps at 4.
217
- cat > "$QUEUE_FILE" <<'JSONL'
218
- {"category":"direction","question":"Q1","context":"c","ticket_id":"P601"}
219
- {"category":"direction","question":"Q2","context":"c","ticket_id":"P602"}
220
- {"category":"direction","question":"Q3","context":"c","ticket_id":"P603"}
221
- {"category":"direction","question":"Q4","context":"c","ticket_id":"P604"}
222
- {"category":"direction","question":"Q5","context":"c","ticket_id":"P605"}
223
- JSONL
224
- run "$HOOK_SCRIPT"
225
- [ "$status" -eq 0 ]
226
- echo "$output" | grep -qE '(<=|≤|max(imum)?[ -]?)4|four'
227
- }
228
-
229
- # ---------------------------------------------------------------------------
230
- # Cleanup-on-resolve directive.
231
- # ---------------------------------------------------------------------------
232
-
233
- @test "cleanup: output instructs the agent to remove resolved entries from the queue" {
234
- cat > "$QUEUE_FILE" <<'JSONL'
235
- {"category":"direction","question":"Q1","context":"c","ticket_id":"P700"}
236
- JSONL
237
- run "$HOOK_SCRIPT"
238
- [ "$status" -eq 0 ]
239
- # The cleanup directive must instruct removing resolved entries from the
240
- # queue file. Match on the load-bearing words rather than exact phrasing.
241
- echo "$output" | grep -qiE '(remove|delete|truncat|clear).*queue|outstanding-questions\.jsonl'
242
- }
243
-
244
- # ---------------------------------------------------------------------------
245
- # AFK-iter cross-context-leak prevention (architect Note 2).
246
- # ---------------------------------------------------------------------------
247
-
248
- @test "WR_SUPPRESS_PENDING_QUESTIONS=1 forces silent exit even when queue non-empty" {
249
- cat > "$QUEUE_FILE" <<'JSONL'
250
- {"category":"direction","question":"Q-should-not-leak","context":"c","ticket_id":"P800"}
251
- JSONL
252
- export WR_SUPPRESS_PENDING_QUESTIONS=1
253
- run "$HOOK_SCRIPT"
254
- [ "$status" -eq 0 ]
255
- [ -z "$output" ]
256
- }
257
-
258
- @test "WR_SUPPRESS_PENDING_QUESTIONS=0 does NOT suppress (only =1 does)" {
259
- cat > "$QUEUE_FILE" <<'JSONL'
260
- {"category":"direction","question":"Q-must-surface","context":"c","ticket_id":"P801"}
261
- JSONL
262
- export WR_SUPPRESS_PENDING_QUESTIONS=0
263
- run "$HOOK_SCRIPT"
264
- [ "$status" -eq 0 ]
265
- echo "$output" | grep -qF 'Q-must-surface'
266
- }
267
-
268
- @test "work-problems Step 5 dispatch block exports WR_SUPPRESS_PENDING_QUESTIONS=1 before claude -p" {
269
- # The orchestrator MUST set WR_SUPPRESS_PENDING_QUESTIONS=1 before each
270
- # iter subprocess spawn so the queue does not surface inside iter contexts
271
- # (cross-context leak per ADR-032 line 127).
272
- WP_SKILL="${REPO_ROOT}/packages/itil/skills/work-problems/SKILL.md"
273
- [ -f "$WP_SKILL" ]
274
- # Find the export line; it must come before the "claude -p" dispatch line in
275
- # the same Step 5 dispatch block.
276
- EXPORT_LINE=$(grep -n 'export WR_SUPPRESS_PENDING_QUESTIONS=1' "$WP_SKILL" | head -1 | cut -d: -f1)
277
- CLAUDE_P_LINE=$(grep -n '^claude -p \\$' "$WP_SKILL" | head -1 | cut -d: -f1)
278
- [ -n "$EXPORT_LINE" ]
279
- [ -n "$CLAUDE_P_LINE" ]
280
- [ "$EXPORT_LINE" -lt "$CLAUDE_P_LINE" ]
281
- }
282
-
283
- # ---------------------------------------------------------------------------
284
- # Malformed input — silent skip, do not crash the SessionStart hook chain.
285
- # ---------------------------------------------------------------------------
286
-
287
- @test "malformed JSON line: skipped silently, well-formed lines still surface" {
288
- cat > "$QUEUE_FILE" <<'JSONL'
289
- {not valid json at all
290
- {"category":"direction","question":"Valid Q","context":"c","ticket_id":"P900"}
291
- JSONL
292
- run "$HOOK_SCRIPT"
293
- [ "$status" -eq 0 ]
294
- echo "$output" | grep -qF 'Valid Q'
295
- }
296
-
297
- @test "all-malformed queue: silent exit 0 (do not block session start)" {
298
- # Defensive — if the queue file is corrupted, the hook MUST NOT prevent
299
- # the session from starting. SessionStart hook failures cascade into
300
- # "session won't start" UX which is far worse than missing one surfacing.
301
- cat > "$QUEUE_FILE" <<'JSONL'
302
- {not json
303
- also not json
304
- JSONL
305
- run "$HOOK_SCRIPT"
306
- [ "$status" -eq 0 ]
307
- }