@windyroad/itil 0.21.6-preview.239 → 0.21.7-preview.241

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.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "wr-itil",
3
- "version": "0.21.6",
3
+ "version": "0.21.7",
4
4
  "description": "ITIL-aligned IT service management for Claude Code"
5
5
  }
@@ -88,15 +88,25 @@ get_current_session_id() {
88
88
  voice-tone
89
89
  )
90
90
 
91
- local system marker
91
+ local system marker f
92
92
  for system in "${systems[@]}"; do
93
- # Glob expansion: nullglob avoids the literal-pattern-on-no-match
94
- # pitfall. Subshell isolates the shopt change.
95
- marker=$(
96
- shopt -s nullglob
97
- set -- "${marker_dir}/${system}-announced-"*
98
- [ "$#" -gt 0 ] && printf '%s\n' "$1"
99
- )
93
+ # Portable existence-check loop. The previous implementation used
94
+ # `shopt -s nullglob` in a subshell — bash-only, errors under zsh
95
+ # with `command not found: shopt` and lets the glob fall through to
96
+ # the literal unmatched-pattern string, returning a wrong UUID.
97
+ # P124 Phase 2: the for-loop existence check works identically
98
+ # under bash, zsh, and POSIX dash. The first existing match wins
99
+ # (selection by fixed marker-system priority order, NOT mtime —
100
+ # `-announced-` markers are write-once-per-session per ADR-038
101
+ # so any present marker is the active SID; mtime selection would
102
+ # reintroduce the `-reviewed-` marker fragility ADR-009 + P111
103
+ # describe).
104
+ marker=""
105
+ for f in "${marker_dir}/${system}-announced-"*; do
106
+ [ -e "$f" ] || continue
107
+ marker="$f"
108
+ break
109
+ done
100
110
  if [ -n "$marker" ]; then
101
111
  # Strip the prefix to recover the trailing UUID.
102
112
  basename "$marker" | sed "s/^${system}-announced-//"
@@ -106,3 +106,32 @@ mark_announced() {
106
106
  [[ "$output" == *"$architect_uuid"* ]]
107
107
  [[ "$output" != *"$jtbd_uuid"* ]]
108
108
  }
109
+
110
+ # --- Behavioural contract: shell portability (P124 Phase 2) ---
111
+ #
112
+ # The helper is sourced by `/wr-itil:manage-problem` Step 2 substep 7 from
113
+ # whichever shell the agent runs Bash tool calls under. On macOS that is
114
+ # zsh by default; the Phase 1 implementation used `shopt -s nullglob` (a
115
+ # bash builtin), which under zsh errors with `shopt: command not found`
116
+ # and lets the subshell glob expression fall through to a literal
117
+ # unmatched-pattern string. The helper then returned a stale or wrong
118
+ # UUID — defeating its stated guarantee. Citations: P124 ticket
119
+ # "Regression Evidence (2026-04-27)" — main-turn P130 capture, line 119:
120
+ # `get_current_session_id:33: command not found: shopt`.
121
+ #
122
+ # This test asserts the helper works identically under zsh as under bash:
123
+ # same UUID returned, exit 0, no `shopt: command not found` error on
124
+ # stderr.
125
+
126
+ @test "zsh portability: helper returns the same UUID under zsh -c as under bash -c" {
127
+ if ! command -v zsh >/dev/null 2>&1; then
128
+ skip "zsh not available"
129
+ fi
130
+ expected_uuid="cccccccc-cccc-cccc-cccc-cccccccccccc"
131
+ mark_announced "architect" "$expected_uuid"
132
+ zsh_run=$(SESSION_MARKER_DIR="$SANDBOX_TMP" zsh -c "source '$HELPER'; get_current_session_id; echo \"EXIT:\$?\"" 2>&1)
133
+ [[ "$zsh_run" == *"$expected_uuid"* ]]
134
+ [[ "$zsh_run" == *"EXIT:0"* ]]
135
+ [[ "$zsh_run" != *"shopt: command not found"* ]]
136
+ [[ "$zsh_run" != *"command not found: shopt"* ]]
137
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/itil",
3
- "version": "0.21.6-preview.239",
3
+ "version": "0.21.7-preview.241",
4
4
  "description": "ITIL-aligned IT service management for Claude Code (problem, and future incident/change skills)",
5
5
  "bin": {
6
6
  "windyroad-itil": "./bin/install.mjs"