@windyroad/itil 2.1.6 → 2.1.7-preview.1157

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.
@@ -497,5 +497,5 @@
497
497
  }
498
498
  },
499
499
  "name": "wr-itil",
500
- "version": "2.1.6"
500
+ "version": "2.1.7"
501
501
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wr-itil",
3
- "version": "2.1.6",
3
+ "version": "2.1.7",
4
4
  "description": "ITIL problem-management workflows for AI coding agents",
5
5
  "author": {
6
6
  "name": "Windy Road Technology",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/itil",
3
- "version": "2.1.6",
3
+ "version": "2.1.7-preview.1157",
4
4
  "description": "ITIL-aligned IT service management for Claude Code and Codex",
5
5
  "bin": {
6
6
  "windyroad-itil": "./bin/install.mjs"
@@ -558,10 +558,11 @@ If a problem is skipped by this step, add it to a "skipped" list with the reason
558
558
  **Dispatch command shape (Bash, backgrounded with idle-timeout poll loop per the "AFK orchestrator should SIGTERM stuck `claude -p` subprocesses after idle-timeout — and SIGTERM appears to flush a clean JSON" problem):**
559
559
 
560
560
  ```bash
561
- ITERATION_PROMPT=$(cat <<'PROMPT_EOF'
561
+ ITERATION_PROMPT_FILE=$(mktemp)
562
+ cat > "$ITERATION_PROMPT_FILE" <<'PROMPT_EOF'
562
563
  <iteration prompt body — see below>
563
564
  PROMPT_EOF
564
- )
565
+ ITERATION_PROMPT=$(cat "$ITERATION_PROMPT_FILE")
565
566
 
566
567
  ITER_JSON=$(mktemp)
567
568
  DISPATCH_START_EPOCH=$(date +%s)
@@ -604,7 +605,10 @@ export WR_SUPPRESS_CORRECTION_DETECT=1
604
605
  # marketplace cache (highest-version-wins, the "Highest-version-wins shim wrapper for plugin scaffold-template shims" architecture rule; adopter-safe via the
605
606
  # the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule bin-on-PATH shim, NOT a repo-relative path). Unresolvable plugins are
606
607
  # skipped silently. <!-- @jtbd the ": Enforce Governance Without Slowing Down" user outcome (iter commits ship gated) @jtbd the ": Progress the Backlog While I'm Away" user outcome (full governance surface inside AFK iters) -->
607
- mapfile -t PLUGIN_DIR_ARGS < <(wr-itil-resolve-governance-plugin-dirs)
608
+ PLUGIN_DIR_ARGS=()
609
+ while IFS= read -r plugin_dir_arg; do
610
+ [ -n "$plugin_dir_arg" ] && PLUGIN_DIR_ARGS+=("$plugin_dir_arg")
611
+ done < <(wr-itil-resolve-governance-plugin-dirs)
608
612
 
609
613
  claude -p \
610
614
  --permission-mode bypassPermissions \
@@ -657,14 +661,14 @@ done
657
661
  wait "$ITER_PID" 2>/dev/null
658
662
  ITER_EXIT=$?
659
663
  SUBPROCESS_OUTPUT=$(<"$ITER_JSON")
660
- rm -f "$ITER_JSON"
664
+ rm -f "$ITER_JSON" "$ITERATION_PROMPT_FILE"
661
665
  ```
662
666
 
663
667
  **Flag rationale:**
664
668
 
665
669
  - `--permission-mode bypassPermissions` — handles non-interactive permission prompts. Without this, Bash/Edit/Write calls inside the subprocess halt on approval prompts (no TTY). Alternative modes (`acceptEdits`, `auto`, `dontAsk`) are acceptable if adopters need narrower permission scopes; `bypassPermissions` is the broadest and the empirically-verified path.
666
670
  - `--output-format json` — deterministic structured output. The subprocess's final agent message lands in the JSON response's `.result` field; orchestrator extracts `ITERATION_SUMMARY` from that field. Plain-text output would require fragile scraping.
667
- - `"${PLUGIN_DIR_ARGS[@]}"` — `--plugin-dir <root>` pairs for each governance plugin, emitted by `wr-itil-resolve-governance-plugin-dirs` (the `mapfile` line above). **Load-bearing (the "work-problems `claude -p` iter subprocesses miss project-scoped governance plugins (need `--plugin-dir` in dispatch)" problem).** Headless `claude -p` activates only USER-scoped `enabledPlugins`; project-scoped plugins stay inactive because project-plugin activation is trust-gated and headless skips the trust prompt. Empirically (verified 2026-06-21) `--setting-sources user,project` does NOT fix this — only `--plugin-dir` makes a project-scoped plugin's agents/hooks/skills available. Without these args an iter in a project-scope adopter tree commits ungated (architect/jtbd/risk-scorer/voice-tone agents resolve to "not found") and cannot run retro-on-exit. The resolver derives each plugin's root from its `bin/` dir on `$PATH` (the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule — present in adopter marketplace-cache trees and source-dev alike) and selects the highest-semver cached version (the "Highest-version-wins shim wrapper for plugin scaffold-template shims" architecture rule — `$PATH` order is frozen at session init and goes stale mid-session, so it is NOT trusted for version selection). Behavioural second-source: `packages/itil/scripts/test/resolve-governance-plugin-dirs.bats`. The expansion is empty (no-op) when no governance plugins resolve, so source-repo dev sessions and minimal adopters degrade gracefully.
671
+ - `"${PLUGIN_DIR_ARGS[@]}"` — `--plugin-dir <root>` pairs for each governance plugin, emitted by `wr-itil-resolve-governance-plugin-dirs` and accumulated by the Bash 3.2-compatible loop above. **Load-bearing (the "work-problems `claude -p` iter subprocesses miss project-scoped governance plugins (need `--plugin-dir` in dispatch)" problem).** Headless `claude -p` activates only USER-scoped `enabledPlugins`; project-scoped plugins stay inactive because project-plugin activation is trust-gated and headless skips the trust prompt. Empirically (verified 2026-06-21) `--setting-sources user,project` does NOT fix this — only `--plugin-dir` makes a project-scoped plugin's agents/hooks/skills available. Without these args an iter in a project-scope adopter tree commits ungated (architect/jtbd/risk-scorer/voice-tone agents resolve to "not found") and cannot run retro-on-exit. The resolver derives each plugin's root from its `bin/` dir on `$PATH` (the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule — present in adopter marketplace-cache trees and source-dev alike) and selects the highest-semver cached version (the "Highest-version-wins shim wrapper for plugin scaffold-template shims" architecture rule — `$PATH` order is frozen at session init and goes stale mid-session, so it is NOT trusted for version selection). Behavioural second-source: `packages/itil/scripts/test/resolve-governance-plugin-dirs.bats`. The expansion is empty (no-op) when no governance plugins resolve, so source-repo dev sessions and minimal adopters degrade gracefully.
668
672
  - `< /dev/null` — explicit stdin-closed redirect (the "Problem 089: work-problems Step 5 dispatch has two robustness gaps — stdin warning pollutes JSON output, and cost metadata undercounts when subprocess exits via background-task-notification ack" problem Gap 1). Without this, `claude -p` waits up to 3s for stdin data in non-TTY contexts and then prints `Warning: no stdin data received in 3s, proceeding without it. If piping from a slow command, redirect stdin explicitly: < /dev/null to skip, or wait longer.` to stderr. The warning is on stderr — if the caller separates stderr and stdout streams, the warning is harmless. But the orchestrator captures via `2>&1` (required because the CLI emits progress prose on stderr that must not interleave between JSON responses when multiple invocations chain). Under the `2>&1` merge the stderr warning prefixes the stdout JSON and breaks `jq` / `json.load` / `JSON.parse` extraction at "line 1, column 1: Expecting value". The redirect suppresses the warning at source. First observed AFK-iter-7 iter 1 (2026-04-21); workaround is the Anthropic CLI help's own suggestion.
669
673
 
670
674
  **No per-iteration budget cap.** The dispatch deliberately omits `--max-budget-usd`. Per user direction 2026-04-21: the natural stop condition for an AFK loop is quota exhaustion, not an arbitrary per-iteration dollar cap. A cap would halt iterations before quota is actually exhausted, wasting remaining budget. Runaway-iteration risk is bounded by quota + the orchestrator's Step 6.75 halt on unexpected dirty state + exit-code handling below.