@windyroad/itil 2.1.0 → 2.1.1

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 (33) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/lib/install-utils.mjs +138 -8
  4. package/package.json +1 -1
  5. package/skills-codex/capture-problem/SKILL.md +1 -1
  6. package/skills-codex/capture-rfc/SKILL.md +1 -1
  7. package/skills-codex/capture-story/SKILL.md +1 -1
  8. package/skills-codex/capture-story-map/SKILL.md +1 -1
  9. package/skills-codex/check-upstream-responses/SKILL.md +1 -1
  10. package/skills-codex/close-incident/SKILL.md +1 -1
  11. package/skills-codex/link-incident/SKILL.md +1 -1
  12. package/skills-codex/list-incidents/SKILL.md +1 -1
  13. package/skills-codex/list-problems/SKILL.md +1 -1
  14. package/skills-codex/list-stories/SKILL.md +1 -1
  15. package/skills-codex/list-story-maps/SKILL.md +1 -1
  16. package/skills-codex/manage-incident/SKILL.md +1 -1
  17. package/skills-codex/manage-problem/SKILL.md +1 -1
  18. package/skills-codex/manage-rfc/SKILL.md +1 -1
  19. package/skills-codex/manage-story/SKILL.md +1 -1
  20. package/skills-codex/manage-story-map/SKILL.md +1 -1
  21. package/skills-codex/mitigate-incident/SKILL.md +1 -1
  22. package/skills-codex/reconcile-readme/SKILL.md +1 -1
  23. package/skills-codex/reconcile-stories/SKILL.md +1 -1
  24. package/skills-codex/reconcile-story-maps/SKILL.md +1 -1
  25. package/skills-codex/report-upstream/SKILL.md +1 -1
  26. package/skills-codex/restore-incident/SKILL.md +1 -1
  27. package/skills-codex/review-problems/SKILL.md +1 -1
  28. package/skills-codex/scaffold-intake/SKILL.md +1 -1
  29. package/skills-codex/transition-problem/SKILL.md +1 -1
  30. package/skills-codex/transition-problems/SKILL.md +1 -1
  31. package/skills-codex/update-upstream/SKILL.md +1 -1
  32. package/skills-codex/work-problem/SKILL.md +1 -1
  33. package/skills-codex/work-problems/SKILL.md +70 -17
@@ -497,5 +497,5 @@
497
497
  }
498
498
  },
499
499
  "name": "wr-itil",
500
- "version": "2.1.0"
500
+ "version": "2.1.1"
501
501
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wr-itil",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "ITIL problem-management workflows for AI coding agents",
5
5
  "author": {
6
6
  "name": "Windy Road Technology",
@@ -4,11 +4,17 @@
4
4
  */
5
5
 
6
6
  import { execSync } from "node:child_process";
7
+ import { createHash } from "node:crypto";
8
+ import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
9
+ import { homedir } from "node:os";
10
+ import { dirname, join, resolve } from "node:path";
11
+ import { fileURLToPath } from "node:url";
7
12
 
8
13
  const MARKETPLACE_REPO = "windyroad/agent-plugins";
9
14
  const MARKETPLACE_NAME = "windyroad";
10
15
  const CODEX_MARKETPLACE_PATH = ".";
11
16
  const CODEX_MARKETPLACE_NAME = "windyroad-local";
17
+ const PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
12
18
 
13
19
  let _dryRun = false;
14
20
 
@@ -82,6 +88,132 @@ export function addCodexMarketplace() {
82
88
  );
83
89
  }
84
90
 
91
+ function codexMarketplace(pluginName) {
92
+ return `windyroad-${pluginName.replace(/^wr-/, "")}-local`;
93
+ }
94
+
95
+ function codexMarketplaceRoot(pluginName) {
96
+ const version = JSON.parse(readFileSync(join(PACKAGE_ROOT, "package.json"), "utf8")).version;
97
+ return join(process.env.CODEX_HOME || join(homedir(), ".codex"), ".tmp", "marketplaces", `${pluginName}-${version}`);
98
+ }
99
+
100
+ function codexAgentDir(scope) {
101
+ return scope === "user"
102
+ ? join(process.env.CODEX_HOME || join(homedir(), ".codex"), "agents")
103
+ : join(process.cwd(), ".codex", "agents");
104
+ }
105
+
106
+ function codexTerms(text) {
107
+ return text
108
+ .replaceAll("AskUserQuestion", "request_user_input")
109
+ .replaceAll("Agent tool", "native Codex subagent tool")
110
+ .replaceAll("Skill tool", "installed skill invocation")
111
+ .replaceAll("Claude Code", "Codex")
112
+ .replace(/\bClaude\b/g, "Codex")
113
+ .replaceAll(".claude", ".codex");
114
+ }
115
+
116
+ function splitFrontmatter(markdown) {
117
+ const end = markdown.indexOf("\n---\n", 4);
118
+ return markdown.startsWith("---\n") && end !== -1
119
+ ? { frontmatter: markdown.slice(4, end), body: markdown.slice(end + 5) }
120
+ : { frontmatter: "", body: markdown };
121
+ }
122
+
123
+ function frontmatterDescription(frontmatter) {
124
+ const lines = frontmatter.split(/\r?\n/);
125
+ const start = lines.findIndex((line) => line.startsWith("description:"));
126
+ if (start === -1) return "Windy Road reviewer.";
127
+ const value = [lines[start].slice("description:".length).trim()];
128
+ for (let index = start + 1; index < lines.length && /^\s+/.test(lines[index]); index += 1) {
129
+ value.push(lines[index].trim());
130
+ }
131
+ return value.filter(Boolean).join(" ");
132
+ }
133
+
134
+ function renderCodexAgent(pluginName, agent) {
135
+ const source = join(PACKAGE_ROOT, agent.source);
136
+ const { frontmatter, body } = splitFrontmatter(readFileSync(source, "utf8"));
137
+ const codexInstructions = agent.name === "wr-voice-tone:external-comms"
138
+ ? `\n\n## Codex completion marker compatibility\n\nOn PASS, compute the lowercase SHA-256 marker key using the normalization specified above and append \`EXTERNAL_COMMS_VOICE_TONE_KEY: <64 lowercase hex characters>\`. Codex may hide the spawn prompt from PostToolUse hooks, so this emitted key is required. On FAIL, do not emit a key.`
139
+ : "";
140
+ const payload = [
141
+ `# Do not edit by hand; update ${agent.source} and reinstall.`,
142
+ `name = ${JSON.stringify(agent.name)}`,
143
+ `description = ${JSON.stringify(frontmatterDescription(frontmatter))}`,
144
+ 'sandbox_mode = "read-only"',
145
+ 'developer_instructions = """',
146
+ codexTerms(`${body.trimEnd()}${codexInstructions}`).replace(/\\/g, "\\\\").replace(/"""/g, '\\"\\"\\"').trimEnd(),
147
+ '"""',
148
+ "",
149
+ ].join("\n");
150
+ const owner = `# Generated by @windyroad/${pluginName.replace(/^wr-/, "")} from ${agent.source}.`;
151
+ const hash = createHash("sha256").update(payload).digest("hex");
152
+ return `${owner}\n# Generated content SHA-256: ${hash}\n${payload}`;
153
+ }
154
+
155
+ function isOwnedCodexAgent(content, pluginName, agent) {
156
+ const owner = `# Generated by @windyroad/${pluginName.replace(/^wr-/, "")} from ${agent.source}.`;
157
+ const lines = content.split("\n");
158
+ const hash = lines[1]?.match(/^# Generated content SHA-256: ([0-9a-f]{64})$/)?.[1];
159
+ return content.startsWith(`${owner}\n`) && Boolean(hash)
160
+ && createHash("sha256").update(lines.slice(2).join("\n")).digest("hex") === hash;
161
+ }
162
+
163
+ function installCodexAgents(pluginName, agents, scope) {
164
+ if (agents.length === 0 || _dryRun) return;
165
+ const targetDir = codexAgentDir(scope);
166
+ mkdirSync(targetDir, { recursive: true });
167
+ for (const agent of agents) {
168
+ const target = join(targetDir, agent.filename);
169
+ const expected = renderCodexAgent(pluginName, agent);
170
+ if (existsSync(target)) {
171
+ const current = readFileSync(target, "utf8");
172
+ if (current === expected) continue;
173
+ if (!isOwnedCodexAgent(current, pluginName, agent)) {
174
+ console.log(`Preserved user-managed Codex agent at ${target}.`);
175
+ continue;
176
+ }
177
+ }
178
+ writeFileSync(target, expected, "utf8");
179
+ }
180
+ }
181
+
182
+ function uninstallCodexAgents(pluginName, agents, scope) {
183
+ if (_dryRun) return;
184
+ for (const targetDir of new Set([codexAgentDir(scope), codexAgentDir("user")])) {
185
+ for (const agent of agents) {
186
+ const target = join(targetDir, agent.filename);
187
+ if (existsSync(target) && isOwnedCodexAgent(readFileSync(target, "utf8"), pluginName, agent)) rmSync(target);
188
+ }
189
+ }
190
+ }
191
+
192
+ function installPackedCodexPlugin(pluginName, { agents = [], scope = "project" } = {}) {
193
+ const marketplace = codexMarketplace(pluginName);
194
+ const root = codexMarketplaceRoot(pluginName);
195
+ if (!_dryRun) {
196
+ rmSync(root, { recursive: true, force: true });
197
+ mkdirSync(dirname(root), { recursive: true });
198
+ cpSync(PACKAGE_ROOT, root, { recursive: true });
199
+ const hooks = join(root, "hooks-codex", "hooks.json");
200
+ if (existsSync(hooks)) cpSync(hooks, join(root, "hooks", "hooks.json"));
201
+ }
202
+ if (!run(`codex plugin marketplace add ${JSON.stringify(root)}`, `Codex marketplace: ${marketplace}`)) return false;
203
+ if (!run(`codex plugin add ${pluginName}@${marketplace}`, pluginName)) return false;
204
+ installCodexAgents(pluginName, agents, scope);
205
+ return true;
206
+ }
207
+
208
+ function uninstallPackedCodexPlugin(pluginName, { agents = [], scope = "project" } = {}) {
209
+ const marketplace = codexMarketplace(pluginName);
210
+ const removed = run(`codex plugin remove ${pluginName}@${marketplace}`, `Removing ${pluginName}`);
211
+ run(`codex plugin marketplace remove ${marketplace}`, `Removing ${marketplace}`);
212
+ uninstallCodexAgents(pluginName, agents, scope);
213
+ if (!_dryRun) rmSync(codexMarketplaceRoot(pluginName), { recursive: true, force: true });
214
+ return removed;
215
+ }
216
+
85
217
  export function installPlugin(pluginName, { scope = "project" } = {}) {
86
218
  return run(
87
219
  `claude plugin install ${pluginName}@${MARKETPLACE_NAME} --scope ${scope}`,
@@ -121,7 +253,7 @@ export function uninstallCodexPlugin(pluginName) {
121
253
  /**
122
254
  * Install a single package: marketplace add + plugin install.
123
255
  */
124
- export function installPackage(pluginName, { deps = [], scope = "project", runtime = "claude" } = {}) {
256
+ export function installPackage(pluginName, { agents = [], deps = [], scope = "project", runtime = "claude" } = {}) {
125
257
  console.log(`\nInstalling @windyroad/${pluginName.replace("wr-", "")} (${scope} scope)...\n`);
126
258
 
127
259
  if (runtime === "claude" || runtime === "both") {
@@ -130,8 +262,7 @@ export function installPackage(pluginName, { deps = [], scope = "project", runti
130
262
  }
131
263
 
132
264
  if (runtime === "codex" || runtime === "both") {
133
- addCodexMarketplace();
134
- installCodexPlugin(pluginName);
265
+ if (!installPackedCodexPlugin(pluginName, { agents, scope })) process.exitCode = 1;
135
266
  }
136
267
 
137
268
  if (deps.length > 0) {
@@ -149,7 +280,7 @@ export function installPackage(pluginName, { deps = [], scope = "project", runti
149
280
  /**
150
281
  * Update a single package.
151
282
  */
152
- export function updatePackage(pluginName, { scope = "project", runtime = "claude" } = {}) {
283
+ export function updatePackage(pluginName, { agents = [], scope = "project", runtime = "claude" } = {}) {
153
284
  console.log(`\nUpdating @windyroad/${pluginName.replace("wr-", "")}...\n`);
154
285
 
155
286
  if (runtime === "claude" || runtime === "both") {
@@ -161,8 +292,7 @@ export function updatePackage(pluginName, { scope = "project", runtime = "claude
161
292
  }
162
293
 
163
294
  if (runtime === "codex" || runtime === "both") {
164
- updateCodexMarketplace();
165
- installCodexPlugin(pluginName);
295
+ if (!installPackedCodexPlugin(pluginName, { agents, scope })) process.exitCode = 1;
166
296
  }
167
297
 
168
298
  console.log(`\nDone! Restart ${runtime === "codex" ? "Codex" : runtime === "both" ? "Claude Code and Codex" : "Claude Code"} to apply updates.\n`);
@@ -171,7 +301,7 @@ export function updatePackage(pluginName, { scope = "project", runtime = "claude
171
301
  /**
172
302
  * Uninstall a single package.
173
303
  */
174
- export function uninstallPackage(pluginName, { runtime = "claude" } = {}) {
304
+ export function uninstallPackage(pluginName, { agents = [], scope = "project", runtime = "claude" } = {}) {
175
305
  console.log(`\nUninstalling @windyroad/${pluginName.replace("wr-", "")}...\n`);
176
306
 
177
307
  if (runtime === "claude" || runtime === "both") {
@@ -179,7 +309,7 @@ export function uninstallPackage(pluginName, { runtime = "claude" } = {}) {
179
309
  }
180
310
 
181
311
  if (runtime === "codex" || runtime === "both") {
182
- uninstallCodexPlugin(pluginName);
312
+ if (!uninstallPackedCodexPlugin(pluginName, { agents, scope })) process.exitCode = 1;
183
313
  }
184
314
 
185
315
  console.log(`\nDone. Restart ${runtime === "codex" ? "Codex" : runtime === "both" ? "Claude Code and Codex" : "Claude Code"} to apply changes.\n`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/itil",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "ITIL-aligned IT service management for Claude Code and Codex",
5
5
  "bin": {
6
6
  "windyroad-itil": "./bin/install.mjs"
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:capture-problem
2
+ name: capture-problem
3
3
  description: Lightweight problem-capture skill for aside-invocation during foreground work — minimal duplicate-check, skeleton ticket file, single commit per capture (covers new ticket + inline README refresh per the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem per the "capture-problem → manage-problem same-session halts at Step 0 reconcile (HALT_ROUTE_RECONCILE on deferred-refresh seam)" problem Option 2 amendment 2026-06-05). Defers full duplicate analysis to /wr-itil:review-problems. Use this when the user (or agent mid-iter) wants to capture an observation quickly without disrupting current task flow. For full-intake new-problem creation, use /wr-itil:manage-problem.
4
4
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob, request_user_input
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:capture-rfc
2
+ name: capture-rfc
3
3
  description: Draw a problem-traced RFC release row on a story map and attach at least one delivery story. Uses the existing delivery-planning vehicle instead of creating an RFC document.
4
4
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob, Skill, request_user_input
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:capture-story
2
+ name: capture-story
3
3
  description: Lightweight story-capture skill for aside-invocation during foreground work — mandatory leading problem-trace AND JTBD-trace per the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule I6 + I9 invariants, mandatory `--story-map` trace (I8 enforced AT CAPTURE per the "Story-map membership and story-content completeness are enforced at capture" architecture rule, refuse-and-route if absent) + optional `--rfc` (I7 at accepted) + real user-value + >=1 acceptance criterion at capture (I10 content subset / the "Story-map membership and story-content completeness are enforced at capture" architecture rule), skeleton story file at `docs/stories/draft/STORY-NNN-<slug>.md`, single commit per capture, no inline README refresh. Defers full INVEST shape + acceptance transition to /wr-itil:manage-story. Use when the user (or agent) wants to capture a story quickly with clear problem + JTBD anchoring. For full lifecycle management, use /wr-itil:manage-story.
4
4
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:capture-story-map
2
+ name: capture-story-map
3
3
  description: Lightweight story-map-capture skill for aside-invocation during foreground work — mandatory leading problem-trace AND JTBD-trace per the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule I3 + I4 invariants, skeleton HTML file at `docs/story-maps/draft/STORY-MAP-NNN-<slug>.html` per the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule § Phase 2 encoding amendment 2026-05-12, single commit per capture, no inline README refresh. Defers full backbone/ribs/slices authoring + lifecycle transitions to /wr-itil:manage-story-map. Use when the user (or agent) wants to capture a new story-map quickly with clear problem + JTBD anchoring.
4
4
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:check-upstream-responses
2
+ name: check-upstream-responses
3
3
  description: Poll upstream issues and pull requests we've filed via `/wr-itil:report-upstream` and surface new comments or reviews, state changes, or label changes since last check. Reads `## Reported Upstream` back-link sections in local problem tickets, queries GitHub read-only, diffs against `docs/problems/.outbound-responses-cache.json`, and appends an audit-log entry to `docs/audits/outbound-responses-log.md`. Outbound symmetric counterpart to the "Inbound upstream-report discovery + assessment pipeline (peer of )" architecture rule's inbound discovery pipeline (the "No process for issue reporters to check for responses — symmetric gap to inbound discovery" problem Phase 1).
4
4
  allowed-tools: Read, Edit, Write, Bash, Glob, Grep
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:close-incident
2
+ name: close-incident
3
3
  description: Close a restored incident — gated on the Linked Problem reaching Known Error, Verifying, or Closed (or a ## No Problem justification). Renames .restored.md to .closed.md.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:link-incident
2
+ name: link-incident
3
3
  description: Link an incident to an existing problem — writes or updates the ## Linked Problem section on the incident file with the problem's ID, title, and current status.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:list-incidents
2
+ name: list-incidents
3
3
  description: List active incidents from docs/incidents/ sorted by severity. Read-only display of the incident backlog — no edits, no interaction. Shown as a markdown table with ID, title, severity, and status columns.
4
4
  allowed-tools: Read, Bash, Grep, Glob
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:list-problems
2
+ name: list-problems
3
3
  description: List open and known-error problem tickets from docs/problems/ sorted by WSJF priority. Read-only display of the current backlog — no edits, no interaction. Shown as a markdown table with ID, title, severity, status, and effort columns.
4
4
  allowed-tools: Read, Bash, Grep, Glob
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:list-stories
2
+ name: list-stories
3
3
  description: List INVEST-shaped story tickets from docs/stories/ as a markdown table. Read-only display — no edits, no interaction. Optional `--rfc RFC-<NNN>` filter to surface a specific RFC's ordered story list per the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule Phase 2.
4
4
  allowed-tools: Read, Bash, Grep, Glob
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:list-story-maps
2
+ name: list-story-maps
3
3
  description: List story-map artefacts from docs/story-maps/ as a markdown table. Read-only display — no edits, no interaction. Renders <meta> block data (problems / rfcs / jtbd / status) from each HTML map per the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule § Phase 2 encoding amendment 2026-05-12.
4
4
  allowed-tools: Read, Bash, Grep, Glob
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:manage-incident
2
+ name: manage-incident
3
3
  description: Declare, triage, mitigate, and close an incident using an evidence-first workflow. Restores service first, then hands off to manage-problem for root-cause work.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill
5
5
  deprecated-arguments: true
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:manage-problem
2
+ name: manage-problem
3
3
  description: Create, update, or transition a problem ticket using an ITIL-aligned problem management workflow with WSJF prioritisation. Supports creating new problems, updating root cause analysis, transitioning status, and closing problems.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill
5
5
  deprecated-arguments: true
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:manage-rfc
2
+ name: manage-rfc
3
3
  description: Heavyweight RFC intake + lifecycle management following the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule Problem-RFC-Story framework. Creates new RFCs (delegates to /wr-itil:capture-rfc for the lightweight path), updates existing RFCs, transitions through proposed → accepted → in-progress → verifying → closed lifecycle, runs WSJF re-rank reviews, and refreshes docs/rfcs/README.md per the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem / the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem contract pattern.
4
4
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob, Task
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:manage-story
2
+ name: manage-story
3
3
  description: Heavyweight story intake + lifecycle management following the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule Phase 2. Creates and updates story tickets, transitions through draft → accepted → in-progress → done → archived lifecycle, enforces I7 + I8 trace-gate at the accepted transition, runs INVEST checks per I10 at acceptance, auto-detects accepted→in-progress on the first implementing commit and in-progress→done on all-criteria-ticked + linked RFC closes (per the "A story cannot be implemented while in draft — implementation requires accepted" architecture rule a draft story is NEVER implementable — draft→in-progress is removed; the itil-no-implement-draft-gate blocks implementing a draft story), and refreshes docs/stories/README.md per the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem / the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem contract pattern. Companion to /wr-itil:capture-story (lightweight aside surface).
4
4
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:manage-story-map
2
+ name: manage-story-map
3
3
  description: Heavyweight story-map intake + lifecycle management following the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule Phase 2. Authors backbone × ribs × slices structure on draft maps, transitions through draft → accepted → in-progress → completed → archived, re-validates I3 + I4 invariants at every transition, and refreshes docs/story-maps/README.md per the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem / the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem contract pattern. Companion to /wr-itil:capture-story-map (lightweight aside surface).
4
4
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:mitigate-incident
2
+ name: mitigate-incident
3
3
  description: Record a mitigation attempt against an incident — transitions an investigating incident to mitigating on the first attempt, appends subsequent attempts to the Mitigation attempts timeline. Evidence-first gate enforced per the "Add `manage-incident` Skill to `wr-itil` Plugin" architecture rule.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:reconcile-readme
2
+ name: reconcile-readme
3
3
  description: Detect and correct drift between docs/problems/README.md and the on-disk ticket inventory. Wraps the diagnose-only `<itil-plugin-root>/scripts/reconcile-readme.sh` script with an agent-applied-edits pattern that preserves narrative content (the "Last reviewed" prose paragraph and Closed-section closure-via free text). Use when README WSJF Rankings, Verification Queue, or Closed sections drift from filesystem state — typically detected by manage-problem Step 0 preflight or work-problems Step 0 preflight.
4
4
  allowed-tools: Read, Edit, Write, Bash, Grep, Glob
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:reconcile-stories
2
+ name: reconcile-stories
3
3
  description: Detect and correct drift between docs/stories/README.md and the on-disk story inventory. Wraps the diagnose-only <itil-plugin-root>/scripts/reconcile-stories.sh script with an agent-applied-edits pattern that preserves narrative content (the "Last reviewed" prose paragraph). Use when docs/stories/README.md Story Rankings or Done sections drift from filesystem state — typically detected by manage-story Step 0 preflight or work-problems preflight on RFC iters with story-tier traces.
4
4
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:reconcile-story-maps
2
+ name: reconcile-story-maps
3
3
  description: Detect and correct drift between docs/story-maps/README.md and the on-disk story-map HTML inventory. Wraps the diagnose-only <itil-plugin-root>/scripts/reconcile-story-maps.sh script with an agent-applied-edits pattern preserving narrative content.
4
4
  allowed-tools: Read, Write, Edit, Bash, Grep, Glob
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:report-upstream
2
+ name: report-upstream
3
3
  description: Report a local problem ticket as a structured issue against an upstream repository, with bidirectional cross-references and SECURITY.md-aware routing for security-classified tickets. Implements the contract in the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule, with the "Report-upstream classifier is problem-first — supersedes Decision Outcome Steps 3 + 5" architecture rule governing problem-first classifier + default body shape.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill, Agent
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:restore-incident
2
+ name: restore-incident
3
3
  description: Mark an incident as service-restored — transitions a mitigating incident to restored, appends a Timeline entry, and hands off to /wr-itil:manage-problem for linked-problem creation or update per the "Add `manage-incident` Skill to `wr-itil` Plugin" architecture rule.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:review-problems
2
+ name: review-problems
3
3
  description: Re-assess every open and known-error problem ticket in docs/problems/ — re-read RISK-POLICY.md, re-rate Impact × Likelihood, re-estimate Effort, recalculate WSJF, surface pending verifications, auto-transition Open → Known Error where warranted, and rewrite docs/problems/README.md with the refreshed ranking. Writes to problem files and the README cache; commits the refresh per the "Governance Skills Commit Their Own Completed Work" architecture rule.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:scaffold-intake
2
+ name: scaffold-intake
3
3
  description: Scaffold the four OSS intake surfaces (.github/ISSUE_TEMPLATE/, SECURITY.md, SUPPORT.md, CONTRIBUTING.md) for a downstream project that adopts @windyroad/itil. Idempotent, foreground-synchronous, and respects the "Gate Marker Lifecycle: TTL + Drift, Not Stop-Hook Reset" architecture rule marker semantics. Implements the contract in the "Scaffold downstream OSS intake — skill + layered triggers" architecture rule.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:transition-problem
2
+ name: transition-problem
3
3
  description: Advance a problem ticket's lifecycle status — Open → Known Error, Known Error → Verification Pending (verifying), Verification Pending → Closed. Renames the ticket file, updates the Status field, and refreshes docs/problems/README.md in the same commit. Hosts the transition execution inline (pre-flight checks, the "Problem 057: `git mv` + Edit + `git add` staging-ordering trap drops content edits from the commit" problem staging-trap handling, the "Problem 063: manage-problem does not trigger /wr-itil:report-upstream when root cause is external" problem external-root-cause detection, the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem README refresh, the "Governance Skills Commit Their Own Completed Work" architecture rule commit) per the "Rename `wr-problem` Plugin to `wr-itil`" architecture rule amended "Split-skill execution ownership". Use when the user asks to "transition", "close", "mark known-error", or "release" a specific ticket.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:transition-problems
2
+ name: transition-problems
3
3
  description: "Batch-advance multiple problem tickets through the lifecycle in one invocation — Open → Known Error, Known Error → Verification Pending, Verification Pending → Closed. Loops the per-ticket /wr-itil:transition-problem mechanic (rename, Status edit, the "Problem 057: `git mv` + Edit + `git add` staging-ordering trap drops content edits from the commit" problem re-stage, the "Problem 063: manage-problem does not trigger /wr-itil:report-upstream when root cause is external" problem external-root-cause detection, the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem README refresh) without paying N× SKILL.md reload latency or violating split-skill execution ownership. Produces ONE shared commit covering all surviving transitions per the "Governance Skills Commit Their Own Completed Work" architecture rule batch-grain. Use when closing the Verification Queue at the end of a `/wr-retrospective:run-retro` Step 4a pass, batch-closing release-aged verifyings during `/wr-itil:work-problems` AFK orchestration, or confirming multiple Step 9d verifications in `/wr-itil:manage-problem review`. Singular sibling — `/wr-itil:transition-problem` (one ticket per invocation)."
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill, Agent
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:update-upstream
2
+ name: update-upstream
3
3
  description: Post a lifecycle-update comment to an upstream issue when a local problem ticket transitions. Drafts a transition-specific update (root-cause confirmed / fix released / closed), composes the prose through the external-comms risk gate + voice-tone gate, auto-posts within appetite, queues above-appetite. Reciprocal sibling to /wr-itil:report-upstream — initial-filing vs lifecycle-update split per the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule amendment (the "Problem 080: No bidirectional update of upstream-reported problems — local lifecycle transitions never propagate back to the reporter" problem).
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill, Agent
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: wr-itil:work-problem
2
+ name: work-problem
3
3
  description: Pick the highest-WSJF open or known-error problem ticket and work it — investigate, implement, commit, and release per the standard manage-problem workflow. Selection is framework-mediated (WSJF + documented tie-break ladder per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule); singular variant; distinct from /wr-itil:work-problems (plural AFK orchestrator). Use this when the user asks to "work the next problem", "work the top of the queue", or "grind through one ticket".
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill, Agent
5
5
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
- name: wr-itil:work-problems
3
- description: Drain the ITIL problem backlog in WSJF order using native Codex subagents, governed commits, pushes, and releases.
2
+ name: work-problems
3
+ description: Drain the ITIL problem backlog in WSJF order using isolated Codex CLI iterations, governed commits, pushes, and releases.
4
4
  ---
5
5
 
6
6
  <!-- Generated from the runtime-neutral skill source. Do not edit. -->
@@ -16,32 +16,85 @@ description: Drain the ITIL problem backlog in WSJF order using native Codex sub
16
16
 
17
17
  # Work Problems in Codex
18
18
 
19
- Continuously work the highest-priority actionable problem until the backlog is drained, the user stops, or a real governance dependency requires human direction. Use Codex's native subagent tools. Never invoke `codex exec`, start a nested Codex CLI, or implement process/PID polling.
19
+ Continuously work the highest-priority actionable problem until the backlog is drained, the user stops, or a real governance dependency requires human direction. Run each selected problem in one fresh `codex exec` process and consume its structured result before continuing.
20
20
 
21
21
  ## Preflight
22
22
 
23
23
  1. If `docs/problems/` is absent, direct the user to `/wr-itil:scaffold-intake` and stop.
24
24
  2. Run the installed ITIL maintenance commands required by the repository, including layout migration, README reconciliation, catch-up scanning, stale upstream-cache checks, and unresolved-response checks. Resolve them from the plugin's bundled `bin/`; do not use source-repository paths.
25
- 3. Preserve unrelated working-tree changes. Revert only changes created by a failed preflight.
26
- 4. If the task has a persistent Codex goal, keep it active until this drain reaches a genuine terminal state. A slow tool or subagent is not a blocker.
25
+ 3. Resolve the exact checkout with `git rev-parse --show-toplevel`. Preserve unrelated working-tree changes and record the pre-iteration status. Revert only paths proven to have been created by a failed iteration.
26
+ 4. If the task has a persistent Codex goal, keep it active until this drain reaches a genuine terminal state. A slow process is not a blocker.
27
27
 
28
28
  ## Loop
29
29
 
30
30
  1. Read the problem index and current ticket files. Select the highest WSJF problem in the highest non-empty actionable tier. Use the documented tie-break rules.
31
31
  2. Skip tickets whose required JTBD, decision, risk, or story-map oversight is unconfirmed. Record one structured outstanding question for each genuinely user-answerable dependency; do not ask mid-loop.
32
32
  3. Run the relevance and stop-condition checks. Before declaring `ALL_DONE`, run the repository's unconditional pre-completion gates and rescan the backlog.
33
- 4. Spawn one native Codex subagent for the selected ticket. Give it the exact checkout, ticket, applicable decisions, and this contract:
34
- - invoke `/wr-itil:manage-problem` for the ticket and follow its lifecycle rules;
35
- - make only in-scope changes and preserve unrelated work;
36
- - run focused tests and the required architecture/risk checks;
37
- - create the required changeset for shippable plugin behavior;
38
- - commit the completed iteration, but do not push or release;
39
- - return one `ITERATION_SUMMARY` JSON object containing ticket, action, commits, tests, risks, outstanding questions, and remaining work.
40
- 5. Wait for that same subagent. Do not cancel, replace, retry, or fan out merely because Cruise or normal model execution makes the call slow. When it completes, consume its summary and close it.
41
- 6. Validate the summary with `<itil-plugin-root>/bin/wr-itil-verify-iter-summary`. If the subagent failed after changing the checkout, inspect and safely complete or revert only its own partial work before continuing.
33
+ 4. Dispatch exactly the selected ticket through the isolated Codex command below. Do not select or work a second ticket inside that process.
34
+ 5. Wait for that same process. Do not cancel, replace, retry, or fan out merely because normal model execution is slow.
35
+ 6. Classify the exit and JSONL metadata before reading the final-output file. On success, validate the summary with `<itil-plugin-root>/bin/wr-itil-verify-iter-summary` and consume it. On failure, apply the recovery contract below and halt.
42
36
  7. Run inter-iteration verification. If the iteration produced committed shippable work, complete the repository's governed push and release cadence when risk is within appetite. Above-appetite risk is a remediation instruction: reduce scope or split the change; never ask the user to approve risk above appetite.
43
37
  8. Report only material progress, then rescan and repeat.
44
38
 
39
+ ## Isolated Codex iteration
40
+
41
+ Build a self-contained prompt containing the selected ticket ID and title, the exact checkout, applicable confirmed decisions, and these requirements:
42
+
43
+ - invoke `/wr-itil:manage-problem <number>` and work only that problem;
44
+ - preserve unrelated work and use path-scoped staging;
45
+ - load and obey the installed governance skills, agents, and hooks;
46
+ - run focused tests and required architecture, JTBD, voice, accessibility, and risk checks when their gates apply;
47
+ - add a changeset for shippable package behavior;
48
+ - commit completed iteration work, but do not push or release;
49
+ - invoke `/wr-retrospective:run-retro` before the final response, commit any retro-owned briefing refresh through its governed path, and continue to the summary even if retro reports a non-blocking failure;
50
+ - end with one `ITERATION_SUMMARY` containing ticket, action, outcome, commit state, tests, risks, outstanding questions, remaining work, and notes.
51
+
52
+ Run the nested process in the outer session's installed Codex environment. Do not replace `CODEX_HOME` or ignore user configuration: the inherited plugin registry and hooks are the governance surface. Export the three AFK guards so pending interactive questions, oversight nudges, and machine-authored correction text do not leak into the isolated turn.
53
+
54
+ ```bash
55
+ ITERATION_CHECKOUT="$(git rev-parse --show-toplevel)"
56
+ ITERATION_JSONL="$(mktemp)"
57
+ ITERATION_FINAL="$(mktemp)"
58
+
59
+ export WR_SUPPRESS_PENDING_QUESTIONS=1
60
+ export WR_SUPPRESS_OVERSIGHT_NUDGE=1
61
+ export WR_SUPPRESS_CORRECTION_DETECT=1
62
+
63
+ codex exec \
64
+ --ephemeral \
65
+ --dangerously-bypass-approvals-and-sandbox \
66
+ --dangerously-bypass-hook-trust \
67
+ --cd "$ITERATION_CHECKOUT" \
68
+ --json \
69
+ --output-last-message "$ITERATION_FINAL" \
70
+ "$ITERATION_PROMPT" \
71
+ >"$ITERATION_JSONL" 2>&1
72
+ ITERATION_EXIT=$?
73
+ ```
74
+
75
+ The two output channels are load-bearing and must stay separate:
76
+
77
+ - `ITERATION_JSONL` carries progress and error metadata only. Parse it as JSONL; never scrape the final agent message from this stream.
78
+ - `ITERATION_FINAL` carries the final agent message. Read `ITERATION_SUMMARY` only from this file after the exit and metadata checks pass.
79
+
80
+ Always remove both temporary files after their contents have been classified and consumed.
81
+
82
+ ## Error classification and recovery
83
+
84
+ Classify in this order:
85
+
86
+ 1. A non-zero process exit halts the loop. Use the exit code plus JSONL error messages to report `quota exhausted`, `rate limited`, `authentication failed`, `service overloaded`, or `execution failed`; do not call a quota failure merely unavailable.
87
+ 2. Exit zero with a JSONL `error` or `turn.failed` event also halts before summary parsing. Apply the same message classification. A final-output file does not override an error event.
88
+ 3. Exit zero without an error event permits final-output parsing. The file must contain exactly one valid `ITERATION_SUMMARY` for the selected ticket; otherwise halt as `invalid iteration summary`.
89
+
90
+ After every exit, record the checkout delta against the pre-iteration status for diagnosis, without mutation. Recovery may begin only after exit zero, error-free JSONL, and exactly one valid `ITERATION_SUMMARY` for the selected ticket. Missing, multiple, or wrong-ticket summaries halt without recovery. Then compare the checkout with the recorded pre-iteration status:
91
+
92
+ - A clean checkout proceeds normally.
93
+ - A coherent commit named by the valid summary proceeds to inter-iteration verification.
94
+ - Coherent staged work attributable only to the selected ticket may be recovered only after its focused tests and governance gates pass again in the outer session.
95
+ - Ambiguous, unstaged, or unrelated changes hard-block recovery. Report their paths and halt without mutation.
96
+ - When a failed iteration created known disposable paths, restore only the explicit verified path list with path-scoped Git commands. Never use a broad reset, clean, checkout, restore, or stash operation.
97
+
45
98
  ## Fix Proposal Rule
46
99
 
47
100
  A fix proposal is a release row on an existing story map, never a new file under `docs/rfcs/`. The row has an identity from `<itil-plugin-root>/bin/wr-itil-next-rfc-id`, at least one story card, and a story whose `problems:` list names the driving problem. Creating a new map, activity column, job, or uncovered architectural choice requires a queued human decision rather than a silent edit.
@@ -50,9 +103,9 @@ A fix proposal is a release row on an existing story map, never a new file under
50
103
 
51
104
  - Batch outstanding questions at loop end with `request_user_input`, no more than four per call. Brief substance before IDs.
52
105
  - Continue past skipped tickets when another actionable ticket exists.
53
- - Stop only for an explicit user stop, a fully drained backlog, a governance dependency that blocks every remaining ticket, or an unrecoverable tool/repository failure.
54
- - Never describe a delayed native tool or subagent as unavailable, hung, or blocked without an actual error or terminal failure.
106
+ - Stop only for an explicit user stop, a fully drained backlog, a governance dependency that blocks every remaining ticket, confirmed quota exhaustion, or an unrecoverable process or repository failure.
107
+ - Never describe a delayed process as unavailable, hung, or blocked without an actual error or terminal failure.
55
108
 
56
109
  ## Final Report
57
110
 
58
- Report completed and skipped tickets, commits, tests, push/release outcomes, remaining backlog, and outstanding design questions. Preserve the distinction between committed, pushed, released, and production-verified states.
111
+ Report completed and skipped tickets, commits, tests, push and release outcomes, remaining backlog, and outstanding design questions. Preserve the distinction between committed, pushed, released, and production-verified states.