@windyroad/retrospective 0.27.4 → 0.28.0-preview.1121

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.
@@ -0,0 +1 @@
1
+ {"name":"windyroad-retrospective-local","interface":{"displayName":"Windy Road Retrospective"},"plugins":[{"name":"wr-retrospective","source":{"source":"local","path":"."},"policy":{"installation":"AVAILABLE","authentication":"ON_INSTALL"},"category":"Developer Tools"}]}
@@ -78,5 +78,5 @@
78
78
  }
79
79
  },
80
80
  "name": "wr-retrospective",
81
- "version": "0.27.4"
81
+ "version": "0.28.0"
82
82
  }
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "wr-retrospective",
3
+ "version": "0.28.0",
4
+ "description": "Session retrospectives, context analysis, and briefing maintenance",
5
+ "author": {
6
+ "name": "Windy Road Technology",
7
+ "url": "https://windyroad.com.au"
8
+ },
9
+ "homepage": "https://github.com/windyroad/agent-plugins/tree/main/packages/retrospective",
10
+ "repository": "https://github.com/windyroad/agent-plugins",
11
+ "license": "MIT",
12
+ "keywords": [
13
+ "retrospective",
14
+ "briefing",
15
+ "context",
16
+ "codex",
17
+ "claude-code"
18
+ ],
19
+ "skills": "./skills/",
20
+ "interface": {
21
+ "displayName": "Windy Road Retrospective",
22
+ "shortDescription": "Run retrospectives and maintain briefings",
23
+ "longDescription": "Analyse session context, run evidence-based retrospectives, maintain project briefings, and capture improvement work.",
24
+ "developerName": "Windy Road Technology",
25
+ "category": "Developer Tools",
26
+ "capabilities": [
27
+ "Interactive",
28
+ "Read",
29
+ "Write"
30
+ ],
31
+ "websiteURL": "https://windyroad.com.au",
32
+ "privacyPolicyURL": "https://windyroad.com.au/privacy",
33
+ "termsOfServiceURL": "https://windyroad.com.au/terms",
34
+ "defaultPrompt": [
35
+ "Run a retrospective for this session",
36
+ "Analyse current context usage"
37
+ ],
38
+ "brandColor": "#0F766E",
39
+ "screenshots": []
40
+ }
41
+ }
package/bin/install.mjs CHANGED
@@ -8,6 +8,7 @@ const utils = await import(resolve(__dirname, "../lib/install-utils.mjs"));
8
8
 
9
9
  const PLUGIN = "wr-retrospective";
10
10
  const DEPS = ["wr-itil", "wr-risk-scorer"];
11
+ const AGENTS = [];
11
12
 
12
13
  const flags = utils.parseStandardArgs(process.argv);
13
14
 
@@ -21,6 +22,7 @@ Options:
21
22
  --update Update this plugin and its skills
22
23
  --uninstall Remove this plugin
23
24
  --scope Installation scope: project (default) or user
25
+ --runtime Runtime to install for: claude (default), codex, or both
24
26
  --dry-run Show what would be done without executing
25
27
  --help, -h Show this help
26
28
  `);
@@ -32,12 +34,12 @@ if (flags.dryRun) {
32
34
  console.log("[dry-run mode — no commands will be executed]\n");
33
35
  }
34
36
 
35
- utils.checkPrerequisites();
37
+ utils.checkPrerequisites({ runtime: flags.runtime });
36
38
 
37
39
  if (flags.uninstall) {
38
- utils.uninstallPackage(PLUGIN);
40
+ utils.uninstallPackage(PLUGIN, { agents: AGENTS, scope: flags.scope, runtime: flags.runtime });
39
41
  } else if (flags.update) {
40
- utils.updatePackage(PLUGIN, { scope: flags.scope });
42
+ utils.updatePackage(PLUGIN, { agents: AGENTS, scope: flags.scope, runtime: flags.runtime });
41
43
  } else {
42
- utils.installPackage(PLUGIN, { deps: DEPS, scope: flags.scope });
44
+ utils.installPackage(PLUGIN, { agents: AGENTS, deps: DEPS, scope: flags.scope, runtime: flags.runtime });
43
45
  }
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env bash
2
+ set -uo pipefail
3
+
4
+ target="$1"
5
+ input="$(cat)"
6
+ tool="$(printf '%s' "$input" | jq -r '.tool_name // empty')"
7
+
8
+ run_hook() {
9
+ printf '%s' "$1" | "$target"
10
+ }
11
+
12
+ if [ "$tool" = "apply_patch" ]; then
13
+ paths="$(printf '%s' "$input" | jq -r '.tool_input.command // empty' | sed -nE 's/^\*\*\* (Add|Update|Delete) File: (.*)$/\2/p')"
14
+ if [ -n "$paths" ]; then
15
+ while IFS= read -r path; do
16
+ payload="$(printf '%s' "$input" | jq --arg path "$path" '.tool_name = "Edit" | .tool_input.file_path = $path')"
17
+ run_hook "$payload" || exit $?
18
+ done <<< "$paths"
19
+ exit 0
20
+ fi
21
+ fi
22
+
23
+ if [ "$tool" = "spawn_agent" ] || [ "$tool" = "Agent" ]; then
24
+ input="$(printf '%s' "$input" | jq '.tool_name = "Agent" | .tool_input.subagent_type = (.tool_input.agent_type // .tool_input.subagent_type // "") | .tool_input.prompt = (.tool_input.message // .tool_input.prompt // "")')"
25
+ fi
26
+
27
+ run_hook "$input"
@@ -0,0 +1,53 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "hooks": [
6
+ {
7
+ "type": "command",
8
+ "command": "${CLAUDE_PLUGIN_ROOT}/bin/check-deps.sh wr-retrospective wr-itil wr-risk-scorer"
9
+ }
10
+ ]
11
+ },
12
+ {
13
+ "matcher": "startup",
14
+ "hooks": [
15
+ {
16
+ "type": "command",
17
+ "command": "${CLAUDE_PLUGIN_ROOT}/hooks/session-start-briefing.sh"
18
+ }
19
+ ]
20
+ },
21
+ {
22
+ "matcher": "startup",
23
+ "hooks": [
24
+ {
25
+ "type": "command",
26
+ "command": "${CLAUDE_PLUGIN_ROOT}/hooks/retrospective-deferral-census.sh"
27
+ }
28
+ ]
29
+ }
30
+ ],
31
+ "PreToolUse": [
32
+ {
33
+ "matcher": "Bash",
34
+ "hooks": [
35
+ {
36
+ "type": "command",
37
+ "command": "${CLAUDE_PLUGIN_ROOT}/hooks/retrospective-readme-jtbd-currency.sh"
38
+ }
39
+ ]
40
+ }
41
+ ],
42
+ "Stop": [
43
+ {
44
+ "hooks": [
45
+ {
46
+ "type": "command",
47
+ "command": "${CLAUDE_PLUGIN_ROOT}/hooks/retrospective-reminder.sh"
48
+ }
49
+ ]
50
+ }
51
+ ]
52
+ }
53
+ }
@@ -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,11 +1,15 @@
1
1
  {
2
2
  "name": "@windyroad/retrospective",
3
- "version": "0.27.4",
3
+ "version": "0.28.0-preview.1121",
4
4
  "description": "Session retrospectives that update briefings and create problem tickets",
5
5
  "bin": {
6
6
  "windyroad-retrospective": "./bin/install.mjs"
7
7
  },
8
8
  "type": "module",
9
+ "scripts": {
10
+ "prepack": "node ../../scripts/sync-codex-plugin-surfaces.mjs retrospective --pack",
11
+ "postpack": "node ../../scripts/sync-codex-plugin-surfaces.mjs retrospective --restore-pack"
12
+ },
9
13
  "license": "MIT",
10
14
  "repository": {
11
15
  "type": "git",
@@ -15,6 +19,7 @@
15
19
  "keywords": [
16
20
  "claude-code",
17
21
  "claude-code-plugin",
22
+ "codex",
18
23
  "ai-agent",
19
24
  "ai-coding"
20
25
  ],
@@ -23,8 +28,11 @@
23
28
  "agents/",
24
29
  "hooks/",
25
30
  "skills/",
31
+ "hooks-codex/",
26
32
  "scripts/",
27
33
  ".claude-plugin/",
34
+ ".agents/",
35
+ ".codex-plugin/",
28
36
  "lib/",
29
37
  "!skills/*/eval/",
30
38
  "!hooks/test/",
@@ -131,7 +131,7 @@ import sys, json
131
131
  data = json.load(sys.stdin)
132
132
  if not data:
133
133
  sys.exit(0)
134
- entry = data[0] if isinstance(data, list) else data
134
+ entry = data[0] if isinstance(data, list) else next(iter(data.values()))
135
135
  name = entry.get("name", "")
136
136
  files = entry.get("files", []) or []
137
137
  print("NAME " + name)
@@ -14,7 +14,7 @@ Source-decision provenance and cross-references for `/wr-retrospective:analyze-c
14
14
  - **ADR-043** (Progressive context-usage measurement) — this skill's source decision.
15
15
  - **ADR-026** (Agent output grounding) — `analyze-context/SKILL.md` is on the per-agent prompt amendments list (lines 94–101 of ADR-026, amended within reassessment window).
16
16
  - **ADR-014** (Governance skills commit own work) — `docs(retros): context analysis YYYY-MM-DD` row added to the Commit Message Convention table; this skill commits its own report per the amended convention.
17
- - **ADR-013** Rule 5 / Rule 6 — interactive AskUserQuestion path / AFK fallback.
17
+ - **ADR-013** Rule 5 / Rule 6 — interactive request_user_input path / AFK fallback.
18
18
  - **ADR-038** (Progressive disclosure) — the methodology mirrors ADR-038's tiered disclosure pattern; report rows obey ≤150-byte budget per row.
19
19
  - **ADR-040** (Session-start briefing surface) — HTML-comment trailer pattern precedent.
20
20
  - **ADR-022** (Verification Pending lifecycle) — P101's transition path on this skill landing.
@@ -4,6 +4,14 @@ description: Deep context-usage analyzer. Runs richer heuristics than run-retro
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, Skill
5
5
  ---
6
6
 
7
+ <!-- Generated from the runtime-neutral skill source. Do not edit. -->
8
+
9
+ > Codex runtime note: invoke installed skills directly, use
10
+ > `request_user_input` only when the contract requires a human decision, and
11
+ > use native Codex subagents for agent delegation. Resolve bundled files from
12
+ > this installed plugin instead of the adopter repository.
13
+
14
+
7
15
  # Analyze Context (Deep Layer)
8
16
 
9
17
  On-demand deep analysis of session context-usage — per-turn attribution, per-plugin decomposition, suggestion generation. Produces a committed markdown report at `docs/retros/<date>-context-analysis.md` whose HTML-comment trailer is the snapshot subsequent runs of `run-retro` Step 2c (cheap layer) compare against.
@@ -17,7 +25,7 @@ This skill is the **deep layer** of the two-layer design in **ADR-043** (Progres
17
25
  - The user is preparing to trim context — e.g. before a release that introduces new hooks or skills, or after observing early compaction in long-running AFK loops.
18
26
  - The user wants a baseline snapshot at a known-good moment (e.g. immediately after a P091-cluster fix lands).
19
27
 
20
- **Auto-fires from run-retro Step 2c, silent in interactive and AFK modes.** Per ADR-043 Amendment 2026-06-08 + ADR-044 framework-resolution boundary, this skill auto-fires from the cheap layer when the combined trigger condition holds (calendar-elapse OR a delta breach clearing both the 20% and the 10 KB absolute floor, capped at once per day). The skill never invokes `AskUserQuestion` — it writes a committed `docs/retros/<TODAY>-context-analysis.md` report and exits. AFK orchestrators read the resulting report on iteration close; the user reviews on return.
28
+ **Auto-fires from run-retro Step 2c, silent in interactive and AFK modes.** Per ADR-043 Amendment 2026-06-08 + ADR-044 framework-resolution boundary, this skill auto-fires from the cheap layer when the combined trigger condition holds (calendar-elapse OR a delta breach clearing both the 20% and the 10 KB absolute floor, capped at once per day). The skill never invokes `request_user_input` — it writes a committed `docs/retros/<TODAY>-context-analysis.md` report and exits. AFK orchestrators read the resulting report on iteration close; the user reviews on return.
21
29
 
22
30
  ## Output Formatting
23
31
 
@@ -211,11 +219,11 @@ Stage and commit per the ADR-014 commit-message convention added by ADR-043:
211
219
 
212
220
  1. `git add docs/retros/<TODAY>-context-analysis.md` plus, if newly created, `docs/retros/README.md`.
213
221
  2. Satisfy the commit gate — two paths are valid:
214
- - **Primary**: delegate to the `wr-risk-scorer:pipeline` subagent-type via the Agent tool.
215
- - **Fallback**: invoke `/wr-risk-scorer:assess-release` via the Skill tool. Per ADR-015 it wraps the same pipeline subagent and produces an equivalent bypass marker.
222
+ - **Primary**: delegate to the `wr-risk-scorer:pipeline` subagent-type via the native Codex subagent tool.
223
+ - **Fallback**: invoke `/wr-risk-scorer:assess-release` via the installed skill invocation. Per ADR-015 it wraps the same pipeline subagent and produces an equivalent bypass marker.
216
224
  3. `git commit -m "docs(retros): context analysis YYYY-MM-DD"` per ADR-014's amended Commit Message Convention table.
217
225
 
218
- If risk is above appetite per ADR-013 Rule 5 + ADR-042: do NOT commit; report the uncommitted state and let the user resolve. Do NOT call `AskUserQuestion` as a shortcut out of the auto-apply loop.
226
+ If risk is above appetite per ADR-013 Rule 5 + ADR-042: do NOT commit; report the uncommitted state and let the user resolve. Do NOT call `request_user_input` as a shortcut out of the auto-apply loop.
219
227
 
220
228
  ### 8. Report
221
229
 
@@ -229,7 +237,7 @@ After the commit lands, report:
229
237
 
230
238
  ## Non-interactive / AFK behaviour (ADR-013 Rule 6 + ADR-043 Amendment 2026-06-08)
231
239
 
232
- This skill is **auto-invoked from run-retro Step 2c** when the combined trigger holds (calendar-elapse >14 days OR delta >20% any bucket, once-per-day guard) per ADR-043 Amendment 2026-06-08 (P295 settlement). The skill is silent (never invokes `AskUserQuestion`) and produces a committed `docs/retros/<TODAY>-context-analysis.md` report; identical behaviour in interactive and AFK modes per ADR-044 framework-resolution boundary — auto-invocation is framework-resolved mechanical action, not a user-decided surface.
240
+ This skill is **auto-invoked from run-retro Step 2c** when the combined trigger holds (calendar-elapse >14 days OR delta >20% any bucket, once-per-day guard) per ADR-043 Amendment 2026-06-08 (P295 settlement). The skill is silent (never invokes `request_user_input`) and produces a committed `docs/retros/<TODAY>-context-analysis.md` report; identical behaviour in interactive and AFK modes per ADR-044 framework-resolution boundary — auto-invocation is framework-resolved mechanical action, not a user-decided surface.
233
241
 
234
242
  If invoked in a non-interactive context AND the commit gate flags above-appetite risk: skip the commit, report the uncommitted report path clearly, and let the user resolve on return. The report file itself is still written — it is the evidence the user reviews.
235
243
 
@@ -0,0 +1,3 @@
1
+ interface:
2
+ display_name: "WR Retrospective: Analyze Context"
3
+ short_description: "Analyse session context usage"
@@ -4,6 +4,14 @@ description: Migrate a legacy single-file `docs/BRIEFING.md` into the per-topic
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
5
  ---
6
6
 
7
+ <!-- Generated from the runtime-neutral skill source. Do not edit. -->
8
+
9
+ > Codex runtime note: invoke installed skills directly, use
10
+ > `request_user_input` only when the contract requires a human decision, and
11
+ > use native Codex subagents for agent delegation. Resolve bundled files from
12
+ > this installed plugin instead of the adopter repository.
13
+
14
+
7
15
  # Migrate Briefing — Legacy Single-File → Per-Topic Tree
8
16
 
9
17
  Adopters who carried a legacy monolithic `docs/BRIEFING.md` from an older `@windyroad/retrospective` release have no automation path to the per-topic `docs/briefing/` tree the current Tier-3 rotation contract (ADR-040) expects. The dual-tolerant SessionStart hook (`packages/retrospective/hooks/session-start-briefing.sh`) keeps adopters working while the legacy file remains, but per-topic-rotation only fires once the tree exists. This skill closes the loop.
@@ -110,9 +118,9 @@ with a `RISK_BYPASS: legacy-briefing-migration` trailer if the project's risk-sc
110
118
 
111
119
  ## Rule 6 audit (ADR-013)
112
120
 
113
- This skill emits **no** `AskUserQuestion` calls. Every decision is mechanical (idempotency detection, slug derivation, file write). Per ADR-032 + ADR-013 Rule 5, mechanical / policy-authorised stages own silent classification and MUST NOT surface consent gates (P132 inverse-P078).
121
+ This skill emits **no** `request_user_input` calls. Every decision is mechanical (idempotency detection, slug derivation, file write). Per ADR-032 + ADR-013 Rule 5, mechanical / policy-authorised stages own silent classification and MUST NOT surface consent gates (P132 inverse-P078).
114
122
 
115
- If a future enhancement adds direction-setting choices (e.g. user-supplied topic-grouping), that surface routes through `AskUserQuestion` per ADR-013 Rule 1 with the 4-option cap. The non-interactive / AFK fallback is the queue-and-continue default per ADR-013 Rule 6 (P352 universal default) — never auto-decide direction-setters.
123
+ If a future enhancement adds direction-setting choices (e.g. user-supplied topic-grouping), that surface routes through `request_user_input` per ADR-013 Rule 1 with the 4-option cap. The non-interactive / AFK fallback is the queue-and-continue default per ADR-013 Rule 6 (P352 universal default) — never auto-decide direction-setters.
116
124
 
117
125
  ## When to invoke
118
126
 
@@ -0,0 +1,3 @@
1
+ interface:
2
+ display_name: "WR Retrospective: Migrate Briefing"
3
+ short_description: "Migrate a project briefing format"
@@ -1,9 +1,17 @@
1
1
  ---
2
2
  name: wr-retrospective:run-retro
3
3
  description: Run a session retrospective. Updates docs/BRIEFING.md with learnings and creates problem tickets for failures and friction.
4
- allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Skill
4
+ allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input, Skill
5
5
  ---
6
6
 
7
+ <!-- Generated from the runtime-neutral skill source. Do not edit. -->
8
+
9
+ > Codex runtime note: invoke installed skills directly, use
10
+ > `request_user_input` only when the contract requires a human decision, and
11
+ > use native Codex subagents for agent delegation. Resolve bundled files from
12
+ > this installed plugin instead of the adopter repository.
13
+
14
+
7
15
  # Session Retrospective
8
16
 
9
17
  Reflect on the current session, update the project briefing, and create problem tickets for failures and friction.
@@ -13,21 +21,21 @@ Reflect on the current session, update the project briefing, and create problem
13
21
  ### Supported invocation surfaces
14
22
 
15
23
  - **Foreground `/wr-retrospective:run-retro`** — the canonical invocation. The user types the slash command in their parent session; the retro runs with full visibility of the session's tool-call history. This is the only invocation surface every other use case falls back to.
16
- - **`claude -p` subprocess invocation** — supported per **P086** (the AFK `/wr-itil:work-problems` iteration subprocess invokes run-retro before emitting `ITERATION_SUMMARY`). The subprocess has the iteration's tool-call history naturally; retro runs with iteration-bounded scope and produces correct findings for that scope. ADR-032 subprocess-boundary variant covers this surface.
24
+ - **`native Codex subagent` subprocess invocation** — supported per **P086** (the AFK `/wr-itil:work-problems` iteration subprocess invokes run-retro before emitting `ITERATION_SUMMARY`). The subprocess has the iteration's tool-call history naturally; retro runs with iteration-bounded scope and produces correct findings for that scope. ADR-032 subprocess-boundary variant covers this surface.
17
25
 
18
26
  ### Anti-pattern: Never invoke as a background agent
19
27
 
20
- Do **NOT** invoke run-retro via `Agent(run_in_background: true)` or any background-subagent surface (the deferred ADR-032 `capture-retro` sibling). Background subagents have isolated context at spawn — they cannot see the parent session's tool-call history, which is run-retro's primary input. A background retro would either produce empty findings, require explicit context-marshalling at spawn (the "shenanigans" the user direction rejected), or post-hoc parse session logs (out of scope today).
28
+ Do **NOT** invoke run-retro via `background native Codex subagent` or any background-subagent surface (the deferred ADR-032 `capture-retro` sibling). Background subagents have isolated context at spawn — they cannot see the parent session's tool-call history, which is run-retro's primary input. A background retro would either produce empty findings, require explicit context-marshalling at spawn (the "shenanigans" the user direction rejected), or post-hoc parse session logs (out of scope today).
21
29
 
22
30
  The `/wr-retrospective:capture-retro` background sibling listed in early ADR-032 drafts is **deferred pending resolution of the context-marshalling problem** (P088, 2026-04-21 user direction: *"run-retro cannot be done as a subagent, because it won't have the context"*). The other ADR-032 background siblings (`capture-problem`, `capture-adr`) are unaffected — their inputs are self-contained aside payloads, not whole-session histories. See **ADR-032** in-scope-list amendment and **P088** ticket for the full settlement.
23
31
 
24
- This anti-pattern clause does NOT forbid retro inside an AFK iteration subprocess (P086) — that surface is the `claude -p` row above, not the background-agent row. Those two surfaces are distinct: `claude -p` is a fresh main Claude Code session that loads its own context naturally; `Agent(run_in_background: true)` is a subagent spawned inside an existing session whose context is isolated from the parent.
32
+ This anti-pattern clause does NOT forbid retro inside an AFK iteration subprocess (P086) — that surface is the `native Codex subagent` row above, not the background-agent row. Those two surfaces are distinct: `native Codex subagent` is a fresh main Codex session that loads its own context naturally; `background native Codex subagent` is a subagent spawned inside an existing session whose context is isolated from the parent.
25
33
 
26
34
  ## Output Formatting
27
35
 
28
36
  When referencing problem IDs, ADR IDs, JTBD IDs, or RFC IDs in prose output (the retro report, the briefing rotation summary, the captured-problem dispatch advisories), always include the human-readable title on first mention. Use the format `P350 (Empathy gap on opaque IDs)`, not bare `P350`.
29
37
 
30
- **Brief-before-ID discipline at every `AskUserQuestion` surface this skill emits (P350).** Step 3 (briefing curation), Step 4a (verification-close-on-evidence), Step 4b (problem-capture from session-observed signal), and any other interactive surface MUST inline what each referenced artefact is and what is at stake BEFORE naming it by ID. The user reads the retro prompt without project filesystem access (mobile clients, accessibility tooling, notification surfaces) and cannot open the cited tickets/ADRs/briefing files to recall the substance. Acceptable: *"Close-on-evidence: the verification ticket about 'agent forgets to refresh the marketplace cache after release' — evidence is the new shared helper landed two releases ago and no recurrence observed. Close?"* Unacceptable: *"Close P289?"*. Every option's substance MUST be self-contained in the briefing prose + option `label` and `description`; IDs may appear ONLY after a self-contained explanation. Mirrors the canonical `/wr-architect:create-adr` Step 5 § 5a Rule 3 ("No IDs as explainers"). See also session memory `feedback_brief_before_id.md`.
38
+ **Brief-before-ID discipline at every `request_user_input` surface this skill emits (P350).** Step 3 (briefing curation), Step 4a (verification-close-on-evidence), Step 4b (problem-capture from session-observed signal), and any other interactive surface MUST inline what each referenced artefact is and what is at stake BEFORE naming it by ID. The user reads the retro prompt without project filesystem access (mobile clients, accessibility tooling, notification surfaces) and cannot open the cited tickets/ADRs/briefing files to recall the substance. Acceptable: *"Close-on-evidence: the verification ticket about 'agent forgets to refresh the marketplace cache after release' — evidence is the new shared helper landed two releases ago and no recurrence observed. Close?"* Unacceptable: *"Close P289?"*. Every option's substance MUST be self-contained in the briefing prose + option `label` and `description`; IDs may appear ONLY after a self-contained explanation. Mirrors the canonical `/wr-architect:create-adr` Step 5 § 5a Rule 3 ("No IDs as explainers"). See also session memory `feedback_brief_before_id.md`.
31
39
 
32
40
  ## Steps
33
41
 
@@ -55,7 +63,7 @@ After reading the briefing tree, score every entry in `docs/briefing/*.md` to de
55
63
  |-------------|--------|
56
64
  | >= +3 | Promote to Critical Points candidate. The agent adds the entry to the Critical Points roll-up in `docs/briefing/README.md` during Step 3. |
57
65
  | 0 .. +2 | Keep in the topic file. No roll-up change. |
58
- | <= -3 | **Silent removal** — no `AskUserQuestion`. The agent removes / trims the entry as part of Step 3 briefing curation and surfaces each removal in the Step 5 retro summary's Signal-vs-Noise Pass table with its score + ADR-026 citation; the user audits there and corrects via P078 authentic-correction if a removal was wrong (removals are reversible from git). See **Delete handling** below. |
66
+ | <= -3 | **Silent removal** — no `request_user_input`. The agent removes / trims the entry as part of Step 3 briefing curation and surfaces each removal in the Step 5 retro summary's Signal-vs-Noise Pass table with its score + ADR-026 citation; the user audits there and corrects via P078 authentic-correction if a removal was wrong (removals are reversible from git). See **Delete handling** below. |
59
67
 
60
68
  **Per-entry persistence format**: each briefing entry carries a trailing HTML comment block:
61
69
 
@@ -66,15 +74,15 @@ After reading the briefing tree, score every entry in `docs/briefing/*.md` to de
66
74
 
67
75
  The comment block is appended to the list item (or heading) that contains the entry text. `first-written` is set when the entry is created and never changed; `last-classified` and `signal-score` are updated each retro. If an entry lacks a comment block, treat `signal-score` as `0` and set `first-written` to today.
68
76
 
69
- **Classification ownership (policy-authorised per ADR-013 Rule 5)**: the agent owns silent classification. No `AskUserQuestion` is fired for individual entry promotions, demotions, or keep decisions. The agent applies the ADR-026 heuristic directly: entry cited in a tool call (or paraphrased in reasoning) during the session = signal; never loaded or loaded-but-unused = noise; ambiguous cases still classify but with a tentative flag the next retro resolves.
77
+ **Classification ownership (policy-authorised per ADR-013 Rule 5)**: the agent owns silent classification. No `request_user_input` is fired for individual entry promotions, demotions, or keep decisions. The agent applies the ADR-026 heuristic directly: entry cited in a tool call (or paraphrased in reasoning) during the session = signal; never loaded or loaded-but-unused = noise; ambiguous cases still classify but with a tentative flag the next retro resolves.
70
78
 
71
- **Delete handling — silent (no `AskUserQuestion`)**: entries scored <= -3 are handled SILENTLY. NO `AskUserQuestion` fires to confirm deletes, at any score band, in interactive OR AFK mode. This is the load-bearing direction every other authority already states: ADR-044's framework-resolution boundary lists "Briefing add / remove / rotate" as a framework-mediated NOT-an-`AskUserQuestion` surface; Step 3's "Removals are silent (P135 / ADR-044)" clause; CLAUDE.md MANDATORY P132 worked-example list (which names "run-retro Step 1.5 silent classification, Step 3 briefing removals"); and ADR-013 Rules 1/5. The agent classifies, the deletes are applied during Step 3 briefing curation, and each removal surfaces in the Step 5 retro summary's "Signal-vs-Noise Pass" table (each candidate with its score + the ADR-026 citation that led to the noise classification). The user audits the Step 5 table and corrects via P078 authentic-correction if a removal was wrong (removals are reversible from git). The AFK queue-and-continue surfacing is specified in the fallback paragraph below (P352).
79
+ **Delete handling — silent (no `request_user_input`)**: entries scored <= -3 are handled SILENTLY. NO `request_user_input` fires to confirm deletes, at any score band, in interactive OR AFK mode. This is the load-bearing direction every other authority already states: ADR-044's framework-resolution boundary lists "Briefing add / remove / rotate" as a framework-mediated NOT-an-`request_user_input` surface; Step 3's "Removals are silent (P135 / ADR-044)" clause; CLAUDE.md MANDATORY P132 worked-example list (which names "run-retro Step 1.5 silent classification, Step 3 briefing removals"); and ADR-013 Rules 1/5. The agent classifies, the deletes are applied during Step 3 briefing curation, and each removal surfaces in the Step 5 retro summary's "Signal-vs-Noise Pass" table (each candidate with its score + the ADR-026 citation that led to the noise classification). The user audits the Step 5 table and corrects via P078 authentic-correction if a removal was wrong (removals are reversible from git). The AFK queue-and-continue surfacing is specified in the fallback paragraph below (P352).
72
80
 
73
- Firing a batched `AskUserQuestion` to confirm deletes is the inverse-P078 lazy-deferral trap — sub-contracting a framework-resolved decision back to the user (lazy classification per the Step 2d Ask Hygiene Pass). It is superseded prose; do NOT reintroduce it.
81
+ Firing a batched `request_user_input` to confirm deletes is the inverse-P078 lazy-deferral trap — sub-contracting a framework-resolved decision back to the user (lazy classification per the Step 2d Ask Hygiene Pass). It is superseded prose; do NOT reintroduce it.
74
82
 
75
83
  **Tier 1 budget guard**: if promoting all score >= +3 entries would breach the 2 KB / ~10-bullet Critical Points budget (ADR-040), promote only the highest-scored entries until the budget is met and surface the remainder as a budget-overflow advisory in the retro summary.
76
84
 
77
- **Non-interactive / AFK fallback (ADR-013 Rule 6)**: when `AskUserQuestion` is unavailable, classify silently and defer the delete queue to the retro summary (Step 5). Do NOT auto-delete entries in AFK mode. The retro summary's "Signal-vs-Noise Pass" section lists each delete candidate with score and citation so the user can review on return. Same trust-boundary shape as Step 2b and Step 4a. **ADR-013 Rule 6 universal default (P352, 2026-06-06 amendment)**: this IS queue-and-continue — the Step 5 retro summary section is the queued surface; classification proceeds, deletion is queued for user review. Not a carve-out — canonical default shape.
85
+ **Non-interactive / AFK fallback (ADR-013 Rule 6)**: when `request_user_input` is unavailable, classify silently and defer the delete queue to the retro summary (Step 5). Do NOT auto-delete entries in AFK mode. The retro summary's "Signal-vs-Noise Pass" section lists each delete candidate with score and citation so the user can review on return. Same trust-boundary shape as Step 2b and Step 4a. **ADR-013 Rule 6 universal default (P352, 2026-06-06 amendment)**: this IS queue-and-continue — the Step 5 retro summary section is the queued surface; classification proceeds, deletion is queued for user review. Not a carve-out — canonical default shape.
78
86
 
79
87
  **Anti-pattern: Do NOT skip the signal-vs-noise pass under any of the following rationalisations** (P332 / P148-class, 2026-05-30):
80
88
 
@@ -103,21 +111,21 @@ Consider the work done in this session and identify:
103
111
 
104
112
  **What recurring pattern did I (or the assistant) observe that would be better codified?** — a pattern that (a) was invoked multiple times in one session or across sessions, (b) has a deterministic action order or a clear invariant, and (c) is reusable beyond one project. These are **codification candidates** and route through Step 4b below. Do not treat them as problem tickets unless the user explicitly picks that routing option.
105
113
 
106
- **What existing skill, agent, hook, ADR, guide, or other codifiable showed a flaw, gap, or friction this session that a targeted edit would fix?** — the **improvement axis** of the codification surface. Criteria: (a) the flaw is reproducible and specific, (b) the fix is a bounded edit to an existing file, (c) no new concept is being invented. Improvement observations flow through the same Step 4b `AskUserQuestion` call as creation candidates, but their options name the improvement shape (e.g. `Skill — improvement stub`, `ADR — supersede or amend`) and the resulting Step 5 row records `Kind: improve` rather than `Kind: create`. An improvement that touches multiple unrelated concerns must be split using the P016 / P017 concern-boundary pattern before routing. If a single output accumulates ≥ 3 improvements in one session, prefer a single coordinating problem ticket over N separate tickets.
114
+ **What existing skill, agent, hook, ADR, guide, or other codifiable showed a flaw, gap, or friction this session that a targeted edit would fix?** — the **improvement axis** of the codification surface. Criteria: (a) the flaw is reproducible and specific, (b) the fix is a bounded edit to an existing file, (c) no new concept is being invented. Improvement observations flow through the same Step 4b `request_user_input` call as creation candidates, but their options name the improvement shape (e.g. `Skill — improvement stub`, `ADR — supersede or amend`) and the resulting Step 5 row records `Kind: improve` rather than `Kind: create`. An improvement that touches multiple unrelated concerns must be split using the P016 / P017 concern-boundary pattern before routing. If a single output accumulates ≥ 3 improvements in one session, prefer a single coordinating problem ticket over N separate tickets.
107
115
 
108
116
  For each codification candidate, also identify the **Kind** (`create` for a new output, `improve` for a targeted edit to an existing output) and the **best shape** for the codification. The Windy Road suite supports many shapes — pick the one that fits the pattern, not the one you happened to learn first:
109
117
 
110
118
  - **Skill** — deterministic multi-step sequence the user invokes by name (e.g. `wr-itil:ship-fix`). Worked example: `fetch origin → check changesets → score risk → commit → push → release → sync manifest → mark Fix Released`.
111
119
  - **Agent** — bounded investigation or review the main agent should delegate to (e.g. a performance-specialist the architect calls in for runtime-path changes). Place under `packages/<plugin>/agents/`.
112
120
  - **Hook** — event-driven enforcement or prompt injection (PreToolUse, PostToolUse, UserPromptSubmit). Use when "I keep forgetting to X before Y" — hooks make X unmissable without adding memory load.
113
- - **Settings entry** — `.claude/settings.json` changes: allowlisted commands, env vars, hook wiring. Best fit when a session repeatedly hits permission prompts for the same benign tool.
121
+ - **Settings entry** — `.codex/settings.json` changes: allowlisted commands, env vars, hook wiring. Best fit when a session repeatedly hits permission prompts for the same benign tool.
114
122
  - **Shell or Node script** — reusable repo-level tooling in `scripts/` (e.g. `sync-install-utils.sh`, `sync-plugin-manifests.mjs`). Best fit for multi-step shell sequences worth scripting.
115
123
  - **CI step** — `.github/workflows/*.yml` insertion. Best fit for "we'd have caught that earlier with a CI check".
116
124
  - **ADR** — architectural decision worth recording. Route to `/wr-architect:create-adr`.
117
125
  - **JTBD** — job-to-be-done record for a persona. Route to `/wr-jtbd:update-guide`.
118
126
  - **Guide** — voice, style, or risk policy edit. Route to `/wr-voice-tone:update-guide`, `/wr-style-guide:update-guide`, or `/wr-risk-scorer:update-policy`.
119
127
  - **Test fixture** — regression test for a recurring failure pattern (bats fixture, unit test). Best fit when the observation is "this kept breaking the same way".
120
- - **Memory** — per-user or per-project memory note in `~/.claude/.../memory/`. Best fit for short, user-habit observations that aren't a codifiable sequence (e.g. "I always forget to run `npm run verify` before pushing").
128
+ - **Memory** — per-user or per-project memory note in `~/.codex/.../memory/`. Best fit for short, user-habit observations that aren't a codifiable sequence (e.g. "I always forget to run `npm run verify` before pushing").
121
129
 
122
130
  **Note (P075)**: the shape list enumerates **codification outputs** — not ticketing. Every codifiable observation becomes a problem ticket in Step 4b Stage 1 regardless of shape. The shape choice is recorded as the ticket's proposed fix strategy (Stage 2), not as an alternative to ticketing. The legacy `Problem ticket` shape row has been removed; it represented a foregone decision (every observation is ticket-worthy) that is now mechanical in Stage 1.
123
131
 
@@ -131,14 +139,14 @@ Counter-examples (what does **not** become a codification candidate):
131
139
 
132
140
  Step 2's reflection prompts are framed around the product-code work the session was trying to do. They under-report **pipeline-level instability** — bugs, regressions, or friction in the tools the session itself relied on (hooks, skills, subagent protocols, release scripts, TTL / marker contracts). Agents read the prompts and list "what I was trying to build" instead of "what was in the way of building it". Step 2b is a dedicated evidence-scan step that recovers those observations before Step 4's ticketing flow fires, so pipeline friction reaches the WSJF queue instead of accumulating off-ledger across sessions.
133
141
 
134
- The shape mirrors P068's Step 4a Verification-close housekeeping: glob / evidence-scan / categorise / dedup / prompt. The ownership boundary is the same — run-retro surfaces the detection and delegates ticket creation to `/wr-itil:manage-problem` via the Skill tool; run-retro does not rename, edit, or commit problem-ticket files on its own (per ADR-014).
142
+ The shape mirrors P068's Step 4a Verification-close housekeeping: glob / evidence-scan / categorise / dedup / prompt. The ownership boundary is the same — run-retro surfaces the detection and delegates ticket creation to `/wr-itil:manage-problem` via the installed skill invocation; run-retro does not rename, edit, or commit problem-ticket files on its own (per ADR-014).
135
143
 
136
- **Ownership boundary**: run-retro surfaces the detection and its specific citations; `/wr-itil:manage-problem` creates or updates the ticket and commits per ADR-014. run-retro does not write `.open.md` files directly — it delegates through the ticketing skill so the audit trail, WSJF scoring, and concern-boundary analysis all apply consistently. This matches Step 4a's boundary to manage-problem Step 7 and Step 4b Stage 1's boundary to manage-problem creation.
144
+ **Ownership boundary**: run-retro surfaces the detection and its specific citations; `/wr-itil:manage-problem` creates or updates the ticket and commits per ADR-014. run-retro does not write `.open.md` files directly — it delegates through the ticketing skill so the audit trail, WSJF scoring, and concern-boundary analysis all apply consistently. This matches Step 4a's boundary to `/wr-itil:transition-problem`, the ADR-010 P093 authoritative executor and Step 4b Stage 1's boundary to manage-problem creation.
137
145
 
138
146
  **Signal categories** — each detection is tagged with the primary category. A detection may match multiple categories; pick the one whose fix path is most concrete.
139
147
 
140
148
  1. **Hook-protocol friction** — gate-marker TTL expiries mid-work (e.g. architect-hook 3600s TTL per ADR-009 expiring while drafting a very long file — was 1800s before P107), marker-vs-file deadlocks (a gate demands PASS before a Write; the agent refuses to PASS on a file that doesn't exist yet), hook-exemption scope gaps, hooks firing on paths they shouldn't, hooks silently skipping paths they should.
141
- 2. **Skill-contract violations** — skill steps that collide (e.g. ADR-027 Step 0 colliding with ADR-031 auto-migration Step 0), skills that return empty on paths they should handle (e.g. work-problems false-zero-bail on flat-layout adopter repos), skills whose AskUserQuestion options exceed the 4-option cap (per P061), skills that silently swallow error states the contract says should halt.
149
+ 2. **Skill-contract violations** — skill steps that collide (e.g. ADR-027 Step 0 colliding with ADR-031 auto-migration Step 0), skills that return empty on paths they should handle (e.g. work-problems false-zero-bail on flat-layout adopter repos), skills whose request_user_input options exceed the 4-option cap (per P061), skills that silently swallow error states the contract says should halt.
142
150
  3. **Release-path instability** — `push:watch` / `release:watch` misbehaviour (P054, P060 class — reporting success on a stale SHA's workflow run), changeset authoring defects (P073), release-PR body issues, npm publish failing on metadata mismatch.
143
151
  4. **Subagent-delegation friction** — architect / jtbd / risk-scorer / style-guide / voice-tone agents returning `DEFERRED` or `ISSUES FOUND` that block progress, PASS markers failing to write, agent prompts timing out, agent outputs missing the specific citations ADR-026 requires.
144
152
  5. **Repeat-work friction** — the same workaround applied ≥ 3 times in one session (each application is signal; the third triggers a ticket candidate). Includes: the same `git add` re-stage after `git mv` (P057), the same marker-refresh pattern after an agent returns DEFERRED, the same hook-bypass incantation.
@@ -159,13 +167,13 @@ The shape mirrors P068's Step 4a Verification-close housekeeping: glob / evidenc
159
167
 
160
168
  4. **Dedup against existing tickets**: for each detection, search `docs/problems/*.open.md` and `docs/problems/*.known-error.md` for tickets whose description or symptoms match the detection's category + signal pattern. If a matching ticket exists: route the detection through Step 4 as an **update** (append new evidence to the existing ticket's `## Symptoms` or `## Root Cause Analysis` section via the manage-problem update path). If no match: route as a **new ticket** with the detection's category, citations, and a suggested title. The matching heuristic is category + signal-pattern keyword overlap — LLM-based dup classification (as discussed in P070) is not required here; local-ticket dedup runs against a small enough corpus that keyword overlap on the category + primary signal word is acceptable.
161
169
 
162
- 5. **Interactive path (ADR-013 Rule 1)**: for each detection, invoke `AskUserQuestion` with the detection summary + specific citations inline so the user can decide without reading session logs. Options (exactly four, per ADR-013 Rule 1 cap):
170
+ 5. **Interactive path (ADR-013 Rule 1)**: for each detection, invoke `request_user_input` with the detection summary + specific citations inline so the user can decide without reading session logs. Options (exactly four, per ADR-013 Rule 1 cap):
163
171
  1. `Create new ticket` — description: "Delegate to /wr-itil:manage-problem to create a problem ticket with the detection's category, citations, and suggested title."
164
172
  2. `Append to P<NNN>` — description: "An existing ticket covers this signal; delegate to /wr-itil:manage-problem to append new evidence to its Root Cause Analysis section."
165
173
  3. `Record in retro report only (not ticket-worthy)` — description: "The detection is session-local friction that does not warrant a persistent ticket; record it in the Pipeline Instability section of the retro summary only."
166
174
  4. `Skip — false positive` — description: "The evidence-scan matched on a false positive; the observed behaviour was correct. Do not record."
167
175
 
168
- 6. **Non-interactive / AFK fallback (ADR-013 Rule 6)**: when `AskUserQuestion` is unavailable (autonomous retro, batch session-wrap), do NOT auto-create tickets — record each detection in the retro summary's new **Pipeline Instability** section with its category, citations, and dedup status (`new` or `matches P<NNN>`). The user reviews on return and runs `/wr-itil:manage-problem` per accepted detection. Same trust-boundary shape as Step 4a's AFK deferral: surface the evidence, defer the decision. This matches the user's documented preference (feedback_verify_from_own_observation.md memory): surface observations from the agent's own in-session activity, but ticket-creation decisions remain user-confirmed.
176
+ 6. **Non-interactive / AFK fallback (ADR-013 Rule 6)**: when `request_user_input` is unavailable (autonomous retro, batch session-wrap), do NOT auto-create tickets — record each detection in the retro summary's new **Pipeline Instability** section with its category, citations, and dedup status (`new` or `matches P<NNN>`). The user reviews on return and runs `/wr-itil:manage-problem` per accepted detection. Same trust-boundary shape as Step 4a's AFK deferral: surface the evidence, defer the decision. This matches the user's documented preference (feedback_verify_from_own_observation.md memory): surface observations from the agent's own in-session activity, but ticket-creation decisions remain user-confirmed.
169
177
 
170
178
  **README inventory currency advisory (ADR-069, P294).** Beyond the categorical pipeline-instability detection above, Step 2b also runs the README inventory-currency detector on every retro to surface drift between each plugin's shipped skills and the skills its README names. (Under superseded ADR-051 this detector also flagged JTBD-ID-citation drift; ADR-069 superseded that — READMEs market the persona's problem derived FROM the JTBD but MUST NOT cite IDs — so the detector is now skill-inventory-only.) The surfacing channel is the retro summary's Pipeline Instability section.
171
179
 
@@ -242,7 +250,7 @@ Per **ADR-043** (Progressive context-usage measurement and reporting for retrosp
242
250
  - **Delta-breach**: any bucket's byte total in the just-rendered report has BOTH (a) changed by more than 20% versus the prior snapshot (HTML-comment trailer from step 2) AND (b) changed by more than the absolute minimum-delta floor of 10 KB — i.e. `|current − prior| > 10240` bytes. Both conditions are required. The absolute floor suppresses negligible-delta noise: a small bucket (`project-claude-md`, `jtbd`) can trip the 20% rule on a sub-2 KB edit (e.g. `project-claude-md` 4277→5897 bytes = +37.9% but only +1620 absolute), which does not warrant the deep layer's committed-report + subagent cost. The 10 KB floor is `not estimated — chosen as initial value, reassess after 6 months of cross-project use` per ADR-026, symmetric with the 14-day / 20% grounding (ADR-043 Amendment 2026-06-17). The calendar-elapse axis still re-fires a large-but-stable bucket every 14 days regardless of delta, so the floor loses no coverage of the dominant context cost.
243
251
  - **Once-per-day guard**: if `docs/retros/<TODAY>-context-analysis.md` already exists (where `<TODAY>` is the current ISO date), treat the trigger as already-satisfied and skip auto-invocation. The snapshot artefact itself is the state; no new persistent state file is needed.
244
252
 
245
- When the trigger holds AND the once-per-day guard is not satisfied, invoke `/wr-retrospective:analyze-context` via the Skill tool. The deep layer is silent (never invokes `AskUserQuestion`) and produces a committed `docs/retros/<TODAY>-context-analysis.md` report. Record the auto-invocation outcome in the cheap-layer section: `Deep analysis auto-fired — see docs/retros/<TODAY>-context-analysis.md.` Identical behaviour in interactive and AFK modes per ADR-013 Rule 6 + ADR-044 framework-resolution boundary — auto-invocation is framework-resolved mechanical action, not a user-decided surface.
253
+ When the trigger holds AND the once-per-day guard is not satisfied, invoke `/wr-retrospective:analyze-context` via the installed skill invocation. The deep layer is silent (never invokes `request_user_input`) and produces a committed `docs/retros/<TODAY>-context-analysis.md` report. Record the auto-invocation outcome in the cheap-layer section: `Deep analysis auto-fired — see docs/retros/<TODAY>-context-analysis.md.` Identical behaviour in interactive and AFK modes per ADR-013 Rule 6 + ADR-044 framework-resolution boundary — auto-invocation is framework-resolved mechanical action, not a user-decided surface.
246
254
 
247
255
  When the trigger does NOT hold (no calendar elapse AND no qualifying delta breach — a delta breach qualifies only when it clears BOTH the 20% and the 10 KB floor), emit a one-line note: `Cadence trigger inactive — next auto-fire when calendar-elapse >14 days OR a bucket changes >20% AND >10 KB.` This is non-blocking and never a prompt.
248
256
 
@@ -252,7 +260,7 @@ Per **ADR-043** (Progressive context-usage measurement and reporting for retrosp
252
260
 
253
261
  6. **Defensive trip (fail-open)**: if the script exits non-zero or the rendered report exceeds the `THRESHOLD bytes=<N>` ceiling at runtime, skip the bucket table and emit the one-line pointer `cheap layer disabled — invoke /wr-retrospective:analyze-context for context measurement`. Log the trip in Step 2b's Pipeline Instability section so the regression is captured as a ticket candidate per the existing flow.
254
262
 
255
- 7. **AFK behaviour (ADR-013 Rule 6)**: identical to interactive mode. The cheap layer is silent (no `AskUserQuestion`); the bucket table + the auto-fire / cadence-trigger line ride the retro summary. The deep layer (when auto-fired per step 4) is also silent and produces a committed report — never blocks. AFK orchestrators read the summary on iteration close.
263
+ 7. **AFK behaviour (ADR-013 Rule 6)**: identical to interactive mode. The cheap layer is silent (no `request_user_input`); the bucket table + the auto-fire / cadence-trigger line ride the retro summary. The deep layer (when auto-fired per step 4) is also silent and produces a committed report — never blocks. AFK orchestrators read the summary on iteration close.
256
264
 
257
265
  **Interaction with other surfaces:**
258
266
 
@@ -264,13 +272,13 @@ Per **ADR-043** (Progressive context-usage measurement and reporting for retrosp
264
272
 
265
273
  ### 2d. Ask Hygiene Pass (P135 Phase 5 / ADR-044)
266
274
 
267
- Per **ADR-044** (Decision-Delegation Contract — framework-resolution boundary), every retro emits a per-session classification of the agent's `AskUserQuestion` calls so the **lazy-AskUserQuestion-count** regression metric is visible at session-time rather than after the user notices the friction. The pass runs unconditionally in every retro (interactive and AFK). Output is a structured table in the Step 5 retro summary; persistence is a one-shot trail file consumed by `packages/retrospective/scripts/check-ask-hygiene.sh` for cross-session trend analysis.
275
+ Per **ADR-044** (Decision-Delegation Contract — framework-resolution boundary), every retro emits a per-session classification of the agent's `request_user_input` calls so the **lazy-request_user_input-count** regression metric is visible at session-time rather than after the user notices the friction. The pass runs unconditionally in every retro (interactive and AFK). Output is a structured table in the Step 5 retro summary; persistence is a one-shot trail file consumed by `packages/retrospective/scripts/check-ask-hygiene.sh` for cross-session trend analysis.
268
276
 
269
- **Ownership boundary**: this step measures and surfaces; it does NOT block, gate, or auto-correct any AskUserQuestion call. The lazy-count metric is the regression signal; correction is the user's call (via direction-setting / deviation-approval / authentic-correction per ADR-044 categories).
277
+ **Ownership boundary**: this step measures and surfaces; it does NOT block, gate, or auto-correct any request_user_input call. The lazy-count metric is the regression signal; correction is the user's call (via direction-setting / deviation-approval / authentic-correction per ADR-044 categories).
270
278
 
271
279
  **Steps:**
272
280
 
273
- 1. **Enumerate AskUserQuestion calls** in the session's tool-use history. For each call, capture: the `header` field, the `question` text, the call ordinal (1..N), and the session-position marker (turn / commit / artefact reference per ADR-026 grounding).
281
+ 1. **Enumerate request_user_input calls** in the session's tool-use history. For each call, capture: the `header` field, the `question` text, the call ordinal (1..N), and the session-position marker (turn / commit / artefact reference per ADR-026 grounding).
274
282
 
275
283
  2. **Classify each call** per ADR-044's 6-class authority taxonomy:
276
284
 
@@ -284,7 +292,7 @@ Per **ADR-044** (Decision-Delegation Contract — framework-resolution boundary)
284
292
  | **correction-followup** | Clarifying a user-issued correction (P078 surface) | NO |
285
293
  | **lazy** | Framework resolves the decision; ask is sub-contracting agent work back to user | **YES (regression metric)** |
286
294
 
287
- Classification ownership is silent agent judgement (per ADR-044 mechanical-stage discipline — no AskUserQuestion-about-AskUserQuestion meta-loop). The agent applies the framework-resolution heuristic: for each call, can the framework (ADR / JTBD / policy / WSJF / SKILL contract) resolve the decision? If yes → lazy. If no AND the call falls into one of the 5 non-lazy categories → that category. Borderline cases default to lazy (conservative — prefer false-positive lazy classification over silently underreporting friction).
295
+ Classification ownership is silent agent judgement (per ADR-044 mechanical-stage discipline — no request_user_input-about-request_user_input meta-loop). The agent applies the framework-resolution heuristic: for each call, can the framework (ADR / JTBD / policy / WSJF / SKILL contract) resolve the decision? If yes → lazy. If no AND the call falls into one of the 5 non-lazy categories → that category. Borderline cases default to lazy (conservative — prefer false-positive lazy classification over silently underreporting friction).
288
296
 
289
297
  **ADR-074 exclusion (substance-confirm-before-build).** A `substance-confirm-before-build` ask — surfacing the SUBSTANTIVE chosen option of a genuine ≥2-option decision the framework cannot resolve, before any dependent work is built on it — classifies as **direction** (cat-1), NOT lazy. The framework deliberately does NOT resolve such a decision (it is the user's to own); the ask is the correct behaviour ADR-074 mandates, not sub-contracting. Grounding: `Gap: genuine ≥2-option decision, framework cannot resolve, about to be built on (ADR-074)`. Do not let the conservative "borderline → lazy" default mis-score it — the trigger is narrow (a decision about to be BUILT ON), so it is unambiguously direction, never lazy. Counting it as lazy would pressure the agent back toward the P315 under-ask failure.
290
298
 
@@ -296,7 +304,7 @@ Per **ADR-044** (Decision-Delegation Contract — framework-resolution boundary)
296
304
 
297
305
  6. **Defensive trip (fail-open)**: if classification produces ambiguous results OR the trail file write fails, skip the persistence step but ALWAYS emit the in-session table (even if classifications are flagged as `unclear`). Better to surface partial data than no data.
298
306
 
299
- 7. **AFK behaviour (ADR-013 Rule 6 / ADR-044)**: identical to interactive mode. The pass is silent (no AskUserQuestion-about-the-classifications); the table + trail entry ride the retro summary; AFK orchestrators read the summary on iteration close.
307
+ 7. **AFK behaviour (ADR-013 Rule 6 / ADR-044)**: identical to interactive mode. The pass is silent (no request_user_input-about-the-classifications); the table + trail entry ride the retro summary; AFK orchestrators read the summary on iteration close.
300
308
 
301
309
  8. **R6 numeric gate auto-flag** (P135 / ADR-044 Reassessment Trigger): after computing this retro's lazy count, invoke `wr-retrospective-check-ask-hygiene` (ADR-049 PATH shim → `packages/retrospective/scripts/check-ask-hygiene.sh`) to read the cross-session trail and detect the R6 condition (lazy count remains **≥2 across 3 consecutive retros** including this one). When the gate fires, **auto-queue a deviation-candidate** in the orchestrator's `outstanding_questions` queue (per the AFK loop's Phase 3 schema in `packages/itil/skills/work-problems/SKILL.md` ITERATION_SUMMARY contract):
302
310
  ```
@@ -309,7 +317,7 @@ Per **ADR-044** (Decision-Delegation Contract — framework-resolution boundary)
309
317
  ticket_id: "P135"
310
318
  }
311
319
  ```
312
- The deviation-candidate surfaces at loop end (Step 2.5) with the standard 5-option `AskUserQuestion` (Approve+amend / Approve+supersede / Approve+one-time / Reject / Defer). The framework reminds itself; no manual remembering required. When this retro is invoked outside an AFK loop (interactive `/wr-retrospective:run-retro`), the same auto-queue logic surfaces the candidate via the orchestrator's main turn AskUserQuestion at retro end — same shape.
320
+ The deviation-candidate surfaces at loop end (Step 2.5) with the standard 5-option `request_user_input` (Approve+amend / Approve+supersede / Approve+one-time / Reject / Defer). The framework reminds itself; no manual remembering required. When this retro is invoked outside an AFK loop (interactive `/wr-retrospective:run-retro`), the same auto-queue logic surfaces the candidate via the orchestrator's main turn request_user_input at retro end — same shape.
313
321
 
314
322
  **Forbidden phrases (anti-friction)**: the in-session table MUST NOT include qualitative-only phrases on the lazy count. Banned: `lazy count is acceptable`, `within tolerance`, `improving`, `regression contained`. Concrete numbers + the trend script's TREND line are the truth surface.
315
323
 
@@ -318,7 +326,7 @@ Per **ADR-044** (Decision-Delegation Contract — framework-resolution boundary)
318
326
  - **`P099` Tier 3 advisory** (`check-briefing-budgets.sh`) and **`P101` cheap-layer measurement** (`check-context-budget.sh`) follow the same advisory-script pattern that `check-ask-hygiene.sh` adopts. Reusable triplet (script + bats + ADR-tier-policy precedent).
319
327
  - **`P132` enforcement hook** (Phase 4 of the P135 plan, gated on Phase 1-3 declarative being insufficient — R6 numeric gate: lazy count ≥2 across 3 consecutive retros after Phase 2/3 land) consumes the same lazy-count trail to decide whether to fire.
320
328
  - **`P078` capture-on-correction** is the inverse pattern; ADR-044 category 6 (`correction-followup`) is the surface where P078 catches operate. Bounded — should be rare.
321
- - **`/wr-retrospective:analyze-context` deep layer** — separate measurement surface (context bytes, not AskUserQuestion calls). Both share the `docs/retros/` trail directory; no double-counting because file naming differs (`<date>-ask-hygiene.md` vs `<date>-context-analysis.md`).
329
+ - **`/wr-retrospective:analyze-context` deep layer** — separate measurement surface (context bytes, not request_user_input calls). Both share the `docs/retros/` trail directory; no double-counting because file naming differs (`<date>-ask-hygiene.md` vs `<date>-context-analysis.md`).
322
330
 
323
331
  ### 3. Update the briefing tree
324
332
 
@@ -339,7 +347,7 @@ After editing topic files, update `docs/briefing/README.md`:
339
347
  - Refresh per-file summaries in the Topic Index if the topic file's character changed.
340
348
  - Promote an entry into the Critical Points section when its signal-score is >= +3 (agent-driven per Step 1.5). The session-start surface is small and curated; the agent promotes the highest-scored entries first, respecting the Tier 1 budget guard. Demotion from Critical Points happens automatically when an entry's score drops below +3 after decay. The remaining user-interactive boundary is the delete queue (score <= -3), which is resolved per Step 1.5's silent-classification model — the agent applies the signal-vs-noise heuristic and removes / trims / compresses without asking, surfacing the chosen actions in the Step 5 retro summary so the user can correct via the P078 capture-on-correction surface if a removal was wrong.
341
349
 
342
- **Removals are silent (P135 / ADR-044)**: per the ADR-044 framework-resolution boundary, removals follow Step 1.5's silent-classification model — agent owns the remove / trim / compress decision; user reads the Step 5 summary and corrects via authentic-correction (ADR-044 category 6) if an entry was removed in error. Per-removal `AskUserQuestion` is sub-contracting framework-resolved decisions back to the user (lazy deferral per Step 2d Ask Hygiene Pass classification).
350
+ **Removals are silent (P135 / ADR-044)**: per the ADR-044 framework-resolution boundary, removals follow Step 1.5's silent-classification model — agent owns the remove / trim / compress decision; user reads the Step 5 summary and corrects via authentic-correction (ADR-044 category 6) if an entry was removed in error. Per-removal `request_user_input` is sub-contracting framework-resolved decisions back to the user (lazy deferral per Step 2d Ask Hygiene Pass classification).
343
351
 
344
352
  **Anti-pattern: Do NOT emit "Added: none / Removed: none / Updated: none" without actually scanning the session for briefing-worthy observations** (P332 / P148-class, 2026-05-30):
345
353
 
@@ -369,7 +377,7 @@ The script's threshold defaults to `5120` bytes (the upper bound of ADR-040's Ti
369
377
 
370
378
  **Ordering**: this pass runs as the FINAL action of Step 3, after edits + Step 1.5 delete-queue persistence + README refresh. It must observe post-edit byte counts so the deletes the user confirmed in Step 1.5 are reflected in the measurement.
371
379
 
372
- **Silent agent-picked rotation (P135 / ADR-044)** — per the ADR-044 framework-resolution boundary, rotation is silent agent judgement applied to each `OVER` line. The agent has all the inputs needed: file mtimes (split-by-date), Step 1.5 signal scores per entry (trim-noise), header structure within the file (split-by-subtopic). No `AskUserQuestion` per file; surfacing 4 options × 6 over-budget files trains the user to pick "defer" 6 times to escape the cascade — worse than no rotation.
380
+ **Silent agent-picked rotation (P135 / ADR-044)** — per the ADR-044 framework-resolution boundary, rotation is silent agent judgement applied to each `OVER` line. The agent has all the inputs needed: file mtimes (split-by-date), Step 1.5 signal scores per entry (trim-noise), header structure within the file (split-by-subtopic). No `request_user_input` per file; surfacing 4 options × 6 over-budget files trains the user to pick "defer" 6 times to escape the cascade — worse than no rotation.
373
381
 
374
382
  **Two heuristic branches** depending on whether the file's `OVER` line is accompanied by a `MUST_SPLIT` line:
375
383
 
@@ -383,11 +391,11 @@ The script's threshold defaults to `5120` bytes (the upper bound of ADR-040's Ti
383
391
  - If a coherent sub-topic boundary exists (≥1 KB sub-section): **split-by-subtopic** — extract to `docs/briefing/<sub-topic>.md`, update README Topic Index.
384
392
  - Else if the file has clear date-stratified entries (HTML-comment `first-written` fields per Step 1.5) AND ≥30% of bytes are entries older than the median age: **split-by-date** — archive oldest entries to `docs/briefing/<topic>-archive.md`.
385
393
  - Else if Step 1.5 surfaced ≥3 noise-classified entries in this file this retro: **trim-noise** — apply the Step 1.5 noise-trim decisions inline; if the trim alone brings the file below threshold, record `trim-noise` as the rotation action with the per-entry deltas in the Step 5 summary. If the file is still OVER after trim, fall through to split-by-date in the same retro turn — do NOT defer.
386
- - Else (no subtopic boundary AND no date stratification AND no ≥3 noise entries): **split-by-date (safe default)** — mtime-sort entries, archive the oldest half to `docs/briefing/<topic>-archive.md`. This is the same safe-default Branch A uses when its boundary is unclear; the fall-through here aligns Branch B with Branch A's evidence-based rotation discipline. Per ADR-013 Rule 5 (policy-authorised silent proceed) + ADR-044 framework-mediated surface ("Briefing add / remove / rotate" line 77), the rotation is silent agent judgement — no per-file `AskUserQuestion`.
394
+ - Else (no subtopic boundary AND no date stratification AND no ≥3 noise entries): **split-by-date (safe default)** — mtime-sort entries, archive the oldest half to `docs/briefing/<topic>-archive.md`. This is the same safe-default Branch A uses when its boundary is unclear; the fall-through here aligns Branch B with Branch A's evidence-based rotation discipline. Per ADR-013 Rule 5 (policy-authorised silent proceed) + ADR-044 framework-mediated surface ("Briefing add / remove / rotate" line 77), the rotation is silent agent judgement — no per-file `request_user_input`.
387
395
 
388
396
  Apply the chosen rotation; record the choice + rationale + per-file delta (`bytes before` → `bytes after`) in the Step 5 summary `Topic File Rotation` section. User reads the summary and corrects via authentic-correction (ADR-044 category 6) if the rotation was wrong (rotations are reversible — `git mv` the archive sibling back; restore deletions from git).
389
397
 
390
- This is the same silent-classification model as Step 1.5 delete-queue removals (P135 lesson: removals + rotations both follow Step 1.5 ownership; per-file `AskUserQuestion` is sub-contracting framework-resolved decisions back to the user — lazy deferral per Step 2d Ask Hygiene Pass classification). AFK and interactive modes use identical behaviour — no `AskUserQuestion` differentiation needed.
398
+ This is the same silent-classification model as Step 1.5 delete-queue removals (P135 lesson: removals + rotations both follow Step 1.5 ownership; per-file `request_user_input` is sub-contracting framework-resolved decisions back to the user — lazy deferral per Step 2d Ask Hygiene Pass classification). AFK and interactive modes use identical behaviour — no `request_user_input` differentiation needed.
391
399
 
392
400
  **Why advisory, not fail-closed**: the rotation is a judgment call (which sub-topic to extract, which archive shape to use). A CI-fail-on-overflow would block routine retros mid-session, directly violating JTBD-001 ("enforce governance without slowing down"). The advisory shape mirrors ADR-038's chosen response to the analogous honour-system byte-budget problem: bats catch script-contract drift; the script itself surfaces signal at runtime without halting.
393
401
 
@@ -403,9 +411,9 @@ For each item identified in "What was harder than it should have been", "What fa
403
411
 
404
412
  ### 4a. Verification-close housekeeping (P068)
405
413
 
406
- Problems whose fix shipped but whose closure is still pending (`docs/problems/*.verifying.md` per ADR-022) accumulate across sessions. When this session's activity exercised a pending fix successfully, run-retro surfaces the evidence so the user can close on observed fact rather than by calendar age (P048's `Likely verified` heuristic) or deferred user review (manage-problem Step 9d's baseline user-initiated path). This step extends those paths with **session-context evidence**; the close decision remains the user's.
414
+ Problems whose fix shipped but whose closure is still pending (`docs/problems/*.verifying.md` per ADR-022) accumulate across sessions. When this session's activity exercised a pending fix successfully, run-retro surfaces the evidence so the user can close on observed fact rather than by calendar age (P048's `Likely verified` heuristic) or deferred user review (manage-problem Step 9d's baseline user-initiated path). This step extends those paths with **session-context evidence**. Closing on that evidence is the agent's call, not a question for the user — sub-step 5 below closes silently, in AFK too, and has since P135 (see P519 for the sweep that removed the contradictory prose this sentence used to carry). What stays the user's are the cases evidence does not settle: no citation collected (absence of evidence is not evidence — the ticket simply stays Verification Pending), contested evidence, a fix covering only part of the ticket, and any ticket a recorded do-not-close marker blocks (`wr-itil-is-close-blocked <NNN> docs/problems` exits 0).
407
415
 
408
- **Ownership boundary**: run-retro surfaces evidence and asks; `/wr-itil:manage-problem` Step 7 Verification Pending Closed transition (rename + Status edit + P057 re-stage + ADR-014 commit per ADR-022) is invoked via the Skill tool to perform the actual file rename and commit. run-retro does **not** rename, edit the Status field, or commit — those remain `manage-problem`'s responsibility. ADR-014 lists run-retro as out of scope for its own commits; the delegated manage-problem call commits per ADR-014 + ADR-022 and that boundary is preserved.
416
+ **Ownership boundary**: run-retro gathers the evidence and decides; `/wr-itil:transition-problem <NNN> close` the authoritative VC executor per ADR-010 amended P093 is invoked via the installed skill invocation to perform the rename + Status edit + P057 re-stage + README refresh + ADR-014 commit. run-retro does **not** rename, edit the Status field, or commit — those remain the transition skill's responsibility. (Corrected 2026-08-24 per P519: this used to say run-retro "surfaces evidence and asks" and named `manage-problem` Step 7, both of which the sub-steps below have contradicted since P135.) ADR-014 lists run-retro as out of scope for its own commits; the delegated manage-problem call commits per ADR-014 + ADR-022 and that boundary is preserved.
409
417
 
410
418
  **Steps:**
411
419
 
@@ -418,14 +426,20 @@ Problems whose fix shipped but whose closure is still pending (`docs/problems/*.
418
426
  - **Commits** whose diff covered the fix's source path (cite the commit SHA and path).
419
427
  - **Skill invocations** that rely on the fix (e.g. `manage-problem` using P056's corrected next-ID lookup; cite the invocation and the observable that the fix contract held — "ID 072 computed without origin_max blob-SHA false-match").
420
428
  - **Hook firings** on gate paths the fix established (cite the tool call that triggered the hook and the hook's observed behaviour).
421
- - **Release cycles** (`push:watch` / `release:watch`) that shipped a commit dependent on the fix (cite the workflow run ID and exit status).
429
+ - **Release cycles** (`push:watch` / `release:watch`) that shipped a commit dependent on the fix (cite the workflow run ID and exit status). Narrow: the shipping alone is not the observation — a ticket is in `verifying` *because* a fix was released, so "it shipped" is true of every row by construction and would collapse the bucket. What counts is that the shipped artefact was then **invoked** and behaved as the fix contracts. Sub-step 8's same-session exclusion stops the degenerate reading here, but state it rather than rely on it (P519).
422
430
 
423
431
  4. **Categorise** each `.verifying.md` ticket into one of three buckets:
424
432
  - **Exercised successfully in-session** — at least one citation from step 3. Record the ticket as a close-candidate. Citations MUST be specific (tool invocation + observable outcome), not bare counts — per ADR-026 grounding. If no specific citation can be produced, the ticket does NOT go in this bucket regardless of how often the fix's area was touched.
425
433
  - **Not exercised in-session** — no citation collected. Leave as Verification Pending; nothing surfaces for this ticket.
426
434
  - **Exercised with regression** — the fix's contract observably failed (test red, hook misfired, skill produced incorrect output). This is a distinct problem, not a closure candidate. Flag it in the retro report as a new problem ticket (route via Step 4) with the regression evidence, and leave the `.verifying.md` file alone.
427
435
 
428
- 5. **Close-on-evidence (silent agent action per P135 / ADR-044)** — for each close-candidate in the "Exercised successfully in-session" bucket, the agent delegates to `/wr-itil:transition-problem <NNN> close` (per ADR-014 commit grain) WITHOUT firing `AskUserQuestion`. The framework has resolved this decision: `.verifying.md` files with specific in-session evidence (test invocation + observable outcome per ADR-026 grounding) ARE verified per ADR-022's evidence semantics. Per-candidate `AskUserQuestion` is sub-contracting the framework-resolved decision back to the user (lazy deferral per Step 2d Ask Hygiene Pass classification).
436
+ 5. **Close-on-evidence (silent agent action per P135 / ADR-044)** — for each close-candidate in the "Exercised successfully in-session" bucket, first run the do-not-close guard:
437
+
438
+ ```bash
439
+ wr-itil-is-close-blocked <NNN> docs/problems && close_blocked=1
440
+ ```
441
+
442
+ Exit 0 → **drop the candidate**; the ticket carries a recorded do-not-close marker, which outranks any evidence. Record the matched marker line as the reason in the Step 5 summary rather than dropping it silently. Exit 1 → proceed. Exit 2 → the ref did not resolve; drop and record a pre-flight failure. For each surviving candidate the agent delegates to `/wr-itil:transition-problem <NNN> close` (per ADR-014 commit grain) WITHOUT firing `request_user_input`. The framework has resolved this decision: `.verifying.md` files with specific in-session evidence (test invocation + observable outcome per ADR-026 grounding) ARE verified per ADR-022's evidence semantics. Per-candidate `request_user_input` is sub-contracting the framework-resolved decision back to the user (lazy deferral per Step 2d Ask Hygiene Pass classification).
429
443
 
430
444
  The Step 5 retro summary's `## Verification Candidates` table records each close action with the citation that triggered it AND a documented recovery path (per the cross-plugin dispatch + recovery-path bats coverage in P135 Phase 2 — `run-retro-step-4a-cross-plugin-dispatch.bats` + `run-retro-step-4a-recovery-path.bats`). User reads the summary; if a close was wrong, user invokes the recovery path: `/wr-itil:transition-problem <NNN> known-error` (or equivalent) — closes are reversible. User disagreement surfaces via authentic-correction (ADR-044 category 6 / P078 capture-on-correction surface) — the agent does not need permission per-close because the recovery path is cheap and reversible.
431
445
 
@@ -450,7 +464,7 @@ Problems whose fix shipped but whose closure is still pending (`docs/problems/*.
450
464
 
451
465
  c. **Same-session exclusion (inherited from sub-step 8)**: skip rows whose `.verifying.md` rename was committed in the current session. Detect via `git log --since=<session-start> --diff-filter=R --name-status` filtered to renames into `docs/problems/verifying/`. A ticket whose `yes — observed:` cell was written in the current session has its rename in the current session's git log and is excluded from the drain — sub-steps 5-7 already handled it via the in-session evidence flow.
452
466
 
453
- d. **Dispatch close** per the same cross-plugin contract as sub-step 5: invoke `/wr-itil:transition-problem <NNN> close` via the Skill tool. The dispatch success / failure / unavailable outcomes are recorded in the Step 5 Verification Candidates table per sub-step 7's contract — uniform treatment regardless of evidence source.
467
+ d. **Dispatch close** per the same cross-plugin contract as sub-step 5: invoke `/wr-itil:transition-problem <NNN> close` via the installed skill invocation. The dispatch success / failure / unavailable outcomes are recorded in the Step 5 Verification Candidates table per sub-step 7's contract — uniform treatment regardless of evidence source.
454
468
 
455
469
  e. **Record source distinction** in the Decision column: append `(prior-session README cell)` to the Decision text. The Citations column carries the README cell's `yes — observed: <citations>` text verbatim so the user can audit the evidence that drove the close.
456
470
 
@@ -468,11 +482,11 @@ Problems whose fix shipped but whose closure is still pending (`docs/problems/*.
468
482
 
469
483
  ### 4b. Two-stage codification — ticket first, fix strategy second (P075)
470
484
 
471
- Every codification candidate identified in Step 2 flows through a **two-stage flow**. Stage 1 is mechanical — every candidate becomes a problem ticket; ticketing is not a user decision. Stage 2 is a per-ticket `AskUserQuestion` recording the **proposed fix strategy** as the codification shape.
485
+ Every codification candidate identified in Step 2 flows through a **two-stage flow**. Stage 1 is mechanical — every candidate becomes a problem ticket; ticketing is not a user decision. Stage 2 is a per-ticket `request_user_input` recording the **proposed fix strategy** as the codification shape.
472
486
 
473
487
  **User rationale (P075)**: the legacy 19-option flat list presented a ticket-this-or-pick-another-shape choice as one option among many, but in practice the ticketing axis has a foregone answer — every codify-worthy observation is also problem-worthy. Re-asking the ticketing question is redundant. Flipping the flow collapses the redundant decision: ticket first (mechanical), fix strategy second (user-interactive).
474
488
 
475
- **Skill candidate / Codification candidate backward compatibility**: the legacy `Skill candidate` and `Codification candidate` AskUserQuestion headers are superseded by Stage 2's `Proposed fix` header. The P044 / P050 / P051 enforcement intents are preserved — they now ride in Stage 2 Options 1–3 on a per-ticket basis rather than as one option among many for a single batch prompt.
489
+ **Skill candidate / Codification candidate backward compatibility**: the legacy `Skill candidate` and `Codification candidate` request_user_input headers are superseded by Stage 2's `Proposed fix` header. The P044 / P050 / P051 enforcement intents are preserved — they now ride in Stage 2 Options 1–3 on a per-ticket basis rather than as one option among many for a single batch prompt.
476
490
 
477
491
  #### Stage 1: Ticket every codify-worthy observation (mechanical — no user decision)
478
492
 
@@ -484,8 +498,8 @@ For every codifiable observation identified in Step 2:
484
498
  - **Direction-setting observation** (genuine user-judgment-bound question — design choice, deviation-approval, framework boundary): route to `outstanding_questions` queue when retro runs inside an AFK iter (via the `ITERATION_SUMMARY.outstanding_questions` schema documented in `packages/itil/skills/work-problems/SKILL.md` Step 5); surface at retro-end interactively when retro runs standalone in main turn. These observations preserve the user's authority surface and MUST NOT auto-ticket.
485
499
  - **Ambiguous** (retro cannot cleanly distinguish recurring-class from direction-setting): **default to mechanical-auto-ticket** per the P342 trust-boundary asymmetry. The ticket lifecycle (`/wr-itil:manage-problem` Step 9d / `/wr-itil:review-problems` Step 4) will surface any embedded direction-setting question through the standard problem-review flow. Defaulting to queue would re-introduce the silent-queue-accumulation hazard P342 closes; defaulting to ticket has zero observation-drop risk.
486
500
 
487
- This is silent agent judgement — no `AskUserQuestion` per observation. The classification taxonomy is framework-resolved per ADR-044; per-observation `AskUserQuestion` would re-route mechanical decisions back to the user (lazy-deferral surface per Step 2d Ask Hygiene Pass). The work-problems Step 5 iter-prompt body carries the symmetric mirror — both surfaces use the same taxonomy.
488
- 3. **Invoke `/wr-itil:manage-problem`** via the Skill tool to create a problem ticket. The observation text becomes the ticket Description; the retro narrative populates the Root Cause Analysis; the `## Related` section cites this retro run. (Once the ADR-032 `capture-*` background sibling ships for manage-problem, Stage 1 can delegate to `/wr-itil:capture-problem` instead so ticketing runs out of the foreground turn; same contract, different invocation mode.)
501
+ This is silent agent judgement — no `request_user_input` per observation. The classification taxonomy is framework-resolved per ADR-044; per-observation `request_user_input` would re-route mechanical decisions back to the user (lazy-deferral surface per Step 2d Ask Hygiene Pass). The work-problems Step 5 iter-prompt body carries the symmetric mirror — both surfaces use the same taxonomy.
502
+ 3. **Invoke `/wr-itil:manage-problem`** via the installed skill invocation to create a problem ticket. The observation text becomes the ticket Description; the retro narrative populates the Root Cause Analysis; the `## Related` section cites this retro run. (Once the ADR-032 `capture-*` background sibling ships for manage-problem, Stage 1 can delegate to `/wr-itil:capture-problem` instead so ticketing runs out of the foreground turn; same contract, different invocation mode.)
489
503
 
490
504
  **ADR-032 note**: Stage 1 is a legitimate **foreground-spawns-N-background fanout** pattern — run-retro's foreground context spawns one background capture invocation per observation (when the background sibling exists). ADR-032's Confirmation section must carry this case; cite `ADR-032` (`docs/decisions/032-governance-skill-invocation-patterns.proposed.md`) explicitly when the background path lands.
491
505
 
@@ -495,7 +509,7 @@ For every codifiable observation identified in Step 2:
495
509
 
496
510
  **Valid fallback gates** — the ONLY conditions under which an observation may be recorded in the retro summary's "Tickets Deferred" section instead of ticketed via `/wr-itil:manage-problem`:
497
511
 
498
- - `cause: skill_unavailable` — the Skill tool is gated out of the current tool surface, OR `/wr-itil:manage-problem` is not registered in this project's plugin set, OR a structural prerequisite (git access, `docs/problems/` directory) is unreachable. The fallback is a graceful-degradation branch when the mechanical action is physically impossible.
512
+ - `cause: skill_unavailable` — the installed skill invocation is gated out of the current tool surface, OR `/wr-itil:manage-problem` is not registered in this project's plugin set, OR a structural prerequisite (git access, `docs/problems/` directory) is unreachable. The fallback is a graceful-degradation branch when the mechanical action is physically impossible.
499
513
 
500
514
  Every "Tickets Deferred" entry MUST carry an explicit `cause:` field naming one of the valid gates. Entries without `cause:`, or with a cause not in the allowlist, are Step 4b Stage 1 violations and are surfaced by `packages/retrospective/scripts/check-tickets-deferred-cause.sh` (advisory; advisory-only initial mode per ADR-040 declarative-first). If the script reports violations, the retro summary renders them under a labelled `Step 4b Stage 1 violations — observations dropped without skill-unavailability cause` subsection.
501
515
 
@@ -512,7 +526,7 @@ Every "Tickets Deferred" entry MUST carry an explicit `cause:` field naming one
512
526
 
513
527
  #### Stage 2: Record proposed fix strategy on each ticket (silent agent action per P135 / ADR-044)
514
528
 
515
- For each ticket created in Stage 1, the agent picks the obvious-fit codification shape from the catalog below and writes it to the ticket's `## Fix Strategy` section WITHOUT firing `AskUserQuestion`. The framework has resolved the catalog (skill / agent / hook / settings / script / CI / ADR / JTBD / guide / test fixture / memory / internal-code); applying that catalog per observation is a mechanical decision, not a human-value question. Per-ticket `AskUserQuestion` is sub-contracting framework-resolved decisions back to the user (lazy deferral per Step 2d Ask Hygiene Pass classification).
529
+ For each ticket created in Stage 1, the agent picks the obvious-fit codification shape from the catalog below and writes it to the ticket's `## Fix Strategy` section WITHOUT firing `request_user_input`. The framework has resolved the catalog (skill / agent / hook / settings / script / CI / ADR / JTBD / guide / test fixture / memory / internal-code); applying that catalog per observation is a mechanical decision, not a human-value question. Per-ticket `request_user_input` is sub-contracting framework-resolved decisions back to the user (lazy deferral per Step 2d Ask Hygiene Pass classification).
516
530
 
517
531
  The four shape choices remain (see Stub templates below for what each one writes), but the AGENT picks based on the observation's signal:
518
532
 
@@ -525,7 +539,7 @@ The four shape choices remain (see Stub templates below for what each one writes
525
539
 
526
540
  **User correction surface**: if the agent picks the wrong shape, the user edits the ticket's `## Fix Strategy` section directly (no orchestrator turn-around needed) — the per-ticket correction is cheap. The Step 5 retro summary's `Codification Candidates` table records each picked shape so the user can scan all picks at once and correct any wrong ones in one editing pass.
527
541
 
528
- **Reversibility note**: shape choices are reversible (just re-edit the ticket); per-ticket `AskUserQuestion` is the inverse-correctness anti-pattern P132 + ADR-044 capture (high friction for low decision-irreversibility).
542
+ **Reversibility note**: shape choices are reversible (just re-edit the ticket); per-ticket `request_user_input` is the inverse-correctness anti-pattern P132 + ADR-044 capture (high friction for low decision-irreversibility).
529
543
 
530
544
  #### Stub templates by Option
531
545
 
@@ -578,7 +592,7 @@ Present a summary to the user:
578
592
 
579
593
  ### Signal-vs-Noise Pass (P105)
580
594
 
581
- (Emitted only when Step 1.5 scored briefing entries. Always present when run-retro is invoked — the pass runs regardless of other outcomes. In non-interactive / AFK mode, the delete queue is surfaced here instead of firing `AskUserQuestion`.)
595
+ (Emitted only when Step 1.5 scored briefing entries. Always present when run-retro is invoked — the pass runs regardless of other outcomes. In non-interactive / AFK mode, the delete queue is surfaced here instead of firing `request_user_input`.)
582
596
 
583
597
  | Entry | Topic file | Old score | New score | Classification | Citation |
584
598
  |-------|-----------|-----------|-----------|----------------|----------|
@@ -0,0 +1,3 @@
1
+ interface:
2
+ display_name: "WR Retrospective: Run Retro"
3
+ short_description: "Run an evidence-based session retrospective"