@codyswann/lisa 2.254.0 → 2.255.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/package.json +1 -1
  2. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  3. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  4. package/plugins/lisa/.codex-plugin/skills/lisa-exploratory-qa/SKILL.md +30 -0
  5. package/plugins/lisa/.codex-plugin/skills/lisa-intake/SKILL.md +40 -0
  6. package/plugins/lisa/.codex-plugin/skills/lisa-learnings-audit/SKILL.md +46 -10
  7. package/plugins/lisa/.codex-plugin/skills/lisa-monitor/SKILL.md +36 -0
  8. package/plugins/lisa/.codex-plugin/skills/lisa-project-ideation/SKILL.md +36 -0
  9. package/plugins/lisa/.codex-plugin/skills/lisa-repair-intake/SKILL.md +34 -0
  10. package/plugins/lisa/scripts/automation-run-record.mjs +110 -0
  11. package/plugins/lisa/skills/lisa-exploratory-qa/SKILL.md +30 -0
  12. package/plugins/lisa/skills/lisa-intake/SKILL.md +40 -0
  13. package/plugins/lisa/skills/lisa-learnings-audit/SKILL.md +46 -10
  14. package/plugins/lisa/skills/lisa-monitor/SKILL.md +36 -0
  15. package/plugins/lisa/skills/lisa-project-ideation/SKILL.md +36 -0
  16. package/plugins/lisa/skills/lisa-repair-intake/SKILL.md +34 -0
  17. package/plugins/lisa-agy/plugin.json +1 -1
  18. package/plugins/lisa-agy/scripts/automation-run-record.mjs +110 -0
  19. package/plugins/lisa-agy/skills/lisa-exploratory-qa/SKILL.md +30 -0
  20. package/plugins/lisa-agy/skills/lisa-intake/SKILL.md +40 -0
  21. package/plugins/lisa-agy/skills/lisa-learnings-audit/SKILL.md +46 -10
  22. package/plugins/lisa-agy/skills/lisa-monitor/SKILL.md +36 -0
  23. package/plugins/lisa-agy/skills/lisa-project-ideation/SKILL.md +36 -0
  24. package/plugins/lisa-agy/skills/lisa-repair-intake/SKILL.md +34 -0
  25. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  27. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  28. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-copilot/scripts/automation-run-record.mjs +110 -0
  32. package/plugins/lisa-copilot/skills/lisa-exploratory-qa/SKILL.md +30 -0
  33. package/plugins/lisa-copilot/skills/lisa-intake/SKILL.md +40 -0
  34. package/plugins/lisa-copilot/skills/lisa-learnings-audit/SKILL.md +46 -10
  35. package/plugins/lisa-copilot/skills/lisa-monitor/SKILL.md +36 -0
  36. package/plugins/lisa-copilot/skills/lisa-project-ideation/SKILL.md +36 -0
  37. package/plugins/lisa-copilot/skills/lisa-repair-intake/SKILL.md +34 -0
  38. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-cursor/scripts/automation-run-record.mjs +110 -0
  40. package/plugins/lisa-cursor/skills/lisa-exploratory-qa/SKILL.md +30 -0
  41. package/plugins/lisa-cursor/skills/lisa-intake/SKILL.md +40 -0
  42. package/plugins/lisa-cursor/skills/lisa-learnings-audit/SKILL.md +46 -10
  43. package/plugins/lisa-cursor/skills/lisa-monitor/SKILL.md +36 -0
  44. package/plugins/lisa-cursor/skills/lisa-project-ideation/SKILL.md +36 -0
  45. package/plugins/lisa-cursor/skills/lisa-repair-intake/SKILL.md +34 -0
  46. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  48. package/plugins/lisa-expo-agy/plugin.json +1 -1
  49. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  53. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  54. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  58. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  59. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  63. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  64. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  68. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  69. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  73. package/plugins/lisa-rails-agy/plugin.json +1 -1
  74. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  75. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  78. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  79. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  80. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  81. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  83. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  84. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  85. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  86. package/plugins/src/base/scripts/automation-run-record.mjs +110 -0
  87. package/plugins/src/base/skills/lisa-exploratory-qa/SKILL.md +30 -0
  88. package/plugins/src/base/skills/lisa-intake/SKILL.md +40 -0
  89. package/plugins/src/base/skills/lisa-learnings-audit/SKILL.md +46 -10
  90. package/plugins/src/base/skills/lisa-monitor/SKILL.md +36 -0
  91. package/plugins/src/base/skills/lisa-project-ideation/SKILL.md +36 -0
  92. package/plugins/src/base/skills/lisa-repair-intake/SKILL.md +34 -0
@@ -260,3 +260,113 @@ async function writeJsonlAtomically(filePath, records) {
260
260
  await writeFile(tempPath, content, "utf8");
261
261
  await rename(tempPath, filePath);
262
262
  }
263
+
264
+ const CLI_USAGE = `Usage: node automation-run-record.mjs \\
265
+ --loop-id <slug> --outcome <${AUTOMATION_RUN_OUTCOMES.join("|")}> \\
266
+ --summary "<operator-readable one-liner>" --runbook <path> \\
267
+ [--ref <url>]... [--run-id <id>] [--project-root <dir>]`;
268
+
269
+ /**
270
+ * Translate a repeatable-flag argv into a {@link RecordAutomationRunInput}.
271
+ *
272
+ * Every flag takes a following value; `--ref` may repeat and accumulates into
273
+ * `refs`. Unknown flags and value-less flags throw so a typo never silently
274
+ * records the wrong thing.
275
+ *
276
+ * @param {readonly string[]} argv
277
+ * @returns {RecordAutomationRunInput}
278
+ */
279
+ function parseAutomationRunRecordArgv(argv) {
280
+ /** @type {Record<string, string>} */
281
+ const single = {};
282
+ /** @type {string[]} */
283
+ const refs = [];
284
+ const flags = {
285
+ "--loop-id": "loopId",
286
+ "--outcome": "outcome",
287
+ "--summary": "summary",
288
+ "--runbook": "runbook",
289
+ "--run-id": "runId",
290
+ "--project-root": "projectRoot",
291
+ };
292
+
293
+ for (let index = 0; index < argv.length; index += 1) {
294
+ const token = argv[index];
295
+ const eq = token.indexOf("=");
296
+ const flag = eq === -1 ? token : token.slice(0, eq);
297
+ const inlineValue = eq === -1 ? undefined : token.slice(eq + 1);
298
+ const takeValue = () => {
299
+ if (inlineValue !== undefined) {
300
+ return inlineValue;
301
+ }
302
+ index += 1;
303
+ if (index >= argv.length) {
304
+ throw new Error(`Missing value for ${flag}.`);
305
+ }
306
+ return argv[index];
307
+ };
308
+
309
+ if (flag === "--ref") {
310
+ refs.push(takeValue());
311
+ continue;
312
+ }
313
+ const key = flags[flag];
314
+ if (!key) {
315
+ throw new Error(`Unknown flag "${flag}".`);
316
+ }
317
+ single[key] = takeValue();
318
+ }
319
+
320
+ return { ...single, refs };
321
+ }
322
+
323
+ /**
324
+ * Argv-driven CLI wrapper so registered loop skills can record an outcome with
325
+ * one portable `node …/automation-run-record.mjs --outcome …` call. Delegates
326
+ * validation to {@link recordAutomationRun}; surfaces its errors verbatim.
327
+ *
328
+ * @param {readonly string[]} argv
329
+ * @returns {Promise<number>} process exit code
330
+ */
331
+ export async function runAutomationRunRecordCli(argv) {
332
+ if (argv.includes("--help") || argv.includes("-h")) {
333
+ process.stdout.write(`${CLI_USAGE}\n`);
334
+ return 0;
335
+ }
336
+ let input;
337
+ try {
338
+ input = parseAutomationRunRecordArgv(argv);
339
+ } catch (error) {
340
+ process.stderr.write(`${error.message}\n\n${CLI_USAGE}\n`);
341
+ return 2;
342
+ }
343
+ try {
344
+ const result = await recordAutomationRun(input);
345
+ process.stdout.write(
346
+ `${JSON.stringify({
347
+ path: result.path,
348
+ appended: result.appended,
349
+ outcome: result.record.outcome,
350
+ loop_id: result.record.loop_id,
351
+ run_id: result.record.run_id,
352
+ })}\n`
353
+ );
354
+ return 0;
355
+ } catch (error) {
356
+ process.stderr.write(`${error.message}\n`);
357
+ return 1;
358
+ }
359
+ }
360
+
361
+ // CLI entrypoint.
362
+ if (import.meta.url === `file://${process.argv[1]}`) {
363
+ runAutomationRunRecordCli(process.argv.slice(2)).then(
364
+ code => {
365
+ process.exitCode = code;
366
+ },
367
+ error => {
368
+ process.stderr.write(`${error?.message ?? error}\n`);
369
+ process.exitCode = 1;
370
+ }
371
+ );
372
+ }
@@ -85,6 +85,36 @@ No report file. Emit a concise in-session summary:
85
85
  - **Findings filed**, bucketed by type — each with its **created or referenced ticket ref** and **build-ready state**.
86
86
  - **Observed but not filed:** anything noticed but intentionally not ticketed (including forbidden-mutation blocks), with why.
87
87
 
88
+ ## Run outcome
89
+
90
+ As the registered `exploratory-bugs` automation loop, this pass conforms to the
91
+ `automation-runbook-contract` rule: every invocation ends in **exactly one** of the six run outcomes
92
+ and records it, so a quiet run and a broken run are never mistaken for each other.
93
+
94
+ | This cycle's exit path | Run outcome |
95
+ |---|---|
96
+ | Findings filed — one or more `Bug` / `Improvement` tickets created or referenced (§6) | `candidate-proposed` |
97
+ | Clean pass — explored the personas and surfaces, nothing worth filing | `nothing-needed` |
98
+ | Tracker unconfigured — the §1 stop path; findings cannot be filed | `recovery-required` |
99
+ | A degradation that still let the pass explore (e.g. Kane unavailable, one persona unreachable) | the outcome it actually reached above, with the summary **leading with the degradation** — degradation never mints a seventh token |
100
+
101
+ Record **exactly one** outcome per invocation through the run-record CLI, naming this loop's runbook
102
+ (the `--summary` is the operator-readable one-liner in the contract's exemplar voice — plain,
103
+ specific, actionable, e.g. `Explored 4 personas; nothing confusing to file.` for `nothing-needed`):
104
+
105
+ ```bash
106
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/automation-run-record.mjs" \
107
+ --loop-id exploratory-bugs --outcome candidate-proposed \
108
+ --summary "Explored 4 personas; filed 3 findings from the checkout flow — awaiting your flip to ready." \
109
+ --runbook .lisa/automations/exploratory-bugs.runbook.md [--ref <ticket-url>]...
110
+ ```
111
+
112
+ If `${CLAUDE_PLUGIN_ROOT}` is unset, resolve the plugin scripts directory directly — the built copy
113
+ `plugins/lisa/scripts/automation-run-record.mjs` or the source
114
+ `plugins/src/base/scripts/automation-run-record.mjs`. If recording still fails, **degrade, never
115
+ abort** (per `automation-runbook-contract`): note the recording failure in the run output and finish
116
+ the cycle — a recording failure is a degradation to report, never a reason to block the loop.
117
+
88
118
  ## Quality bar
89
119
 
90
120
  - Explore as a true first-time user — judge clarity, not whether you (who can read the code) can figure it out.
@@ -116,6 +116,46 @@ The single-item skills (`lisa-plan`, `lisa-implement`) and the per-vendor batch
116
116
  5. **Stop after one item** — a claimed Ready item, a safe-blocked container, or a per-item error ends the *ready-claim* portion of the cycle. The per-vendor PRD scanner still runs its rollup and one verify-prd dispatch. Remaining Ready items stay untouched for later scheduler invocations.
117
117
  6. **Summary report** — the single processed/skipped/error item, total processed, total errors. Before returning, record intake usage on the persisted cycle-summary artifact via `lisa-usage-accounting` so the summary carries a direct `lisa-intake` entry in the canonical `## Lisa Usage` section. If the claimed / skipped work item's parent-child graph is already known, prefer `record_and_rollup` so ancestor totals refresh in the same cycle; otherwise still write the direct entry, and if runtime usage is unavailable, use `source: unavailable` with nullable token/cost fields instead of skipping the row.
118
118
 
119
+ ## Run outcome
120
+
121
+ As a registered automation loop, each Intake cycle conforms to the `automation-runbook-contract`
122
+ rule: it ends in **exactly one** of the six run outcomes and records it, so a quiet queue and a
123
+ broken loop never look alike. Intake backs **two** registered loop-ids — record under the one that
124
+ matches the mode this cycle ran in: **`intake-prd`** (PRD-side dispatch) or **`intake-tickets`**
125
+ (build-queue dispatch).
126
+
127
+ | This cycle's exit path | Run outcome |
128
+ |---|---|
129
+ | Empty `Ready` set — the idle case (step 3), nothing to claim | `nothing-needed` |
130
+ | A PRD routed to `Blocked` (clarifying questions) or `Ticketed`; a build ticket claimed and dispatched | `candidate-proposed` |
131
+ | A build cycle that shipped and verified (merged PR + evidence), or a shipped PRD moved to `verified` | `change-proved` |
132
+ | A protected deployment (or other autonomy boundary the lifecycle hits) waiting on a human approval | `approval-requested` |
133
+ | The queue itself is misconfigured or unreadable — missing required input (step 1) or an unreachable Status/workflow (step 2/`3` misconfig) so the cycle could not run | `recovery-required` |
134
+
135
+ **Seam warning (the #1 misread in this ticket).** A run outcome describes this *cycle*; `Blocked` is
136
+ a *work item's* lifecycle terminal state — the two never merge in the summary. When Intake correctly
137
+ routes to `Blocked` (an item whose requirements are unresolvable, carrying clarifying questions), the
138
+ cycle **produced something**, so it is a successful run — `candidate-proposed`, and **never
139
+ `recovery-required`** (the machinery is not broken) and **never `nothing-needed`** (the run did not
140
+ find nothing). The summary must say both plainly: the item was blocked *and* the run succeeded.
141
+
142
+ Record **exactly one** outcome per invocation through the run-record CLI, naming this loop's runbook
143
+ (the `--summary` is the operator-readable one-liner in the contract's exemplar voice — plain,
144
+ specific, actionable, e.g. `Scanned 12 ready items; nothing to propose.` for `nothing-needed`):
145
+
146
+ ```bash
147
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/automation-run-record.mjs" \
148
+ --loop-id intake-tickets --outcome candidate-proposed \
149
+ --summary "Routed PRD #1810 to Blocked with clarifying questions; the run succeeded." \
150
+ --runbook .lisa/automations/intake-tickets.runbook.md [--ref <item-url>]...
151
+ ```
152
+
153
+ If `${CLAUDE_PLUGIN_ROOT}` is unset, resolve the plugin scripts directory directly — the built copy
154
+ `plugins/lisa/scripts/automation-run-record.mjs` or the source
155
+ `plugins/src/base/scripts/automation-run-record.mjs`. If recording still fails, **degrade, never
156
+ abort** (per `automation-runbook-contract`): note the recording failure in the run output and finish
157
+ the cycle — a recording failure is a degradation to report, never a reason to block the loop.
158
+
119
159
  ## Schedule examples
120
160
 
121
161
  ```text
@@ -124,7 +124,10 @@ audits the auditor without re-running it.
124
124
  `drafted_artifact`; the gardener decides whether the evidence clears the
125
125
  filing bar and attaches the router's draft to the ticket.
126
126
  4. **Emit** (see Ticket emission).
127
- 5. **Report** the terminal state and one-line summary.
127
+ 5. **Report and record** the run outcome and one-line summary — post the
128
+ outcome, then record **exactly one** run-record line through the CLI (see
129
+ Run outcomes), including the escalation path when it ends
130
+ `recovery-required`.
128
131
 
129
132
  ## Ticket emission
130
133
 
@@ -280,17 +283,50 @@ marker-recoverable per-item tickets and a missing (not half-filled) batch:
280
283
  the most recoverable state. Never attempt to "roll back" filed tickets —
281
284
  close-out decisions belong to humans.
282
285
 
283
- ## Terminal states
286
+ ## Run outcomes
287
+
288
+ Exactly one per run, from the closed six-value vocabulary of the
289
+ `automation-runbook-contract` rule:
290
+ **`nothing-needed | candidate-proposed | change-proved | approval-requested | recovery-required | policy-obsolete`**.
291
+
292
+ This section supersedes the gardener's earlier three-value *terminal states*
293
+ vocabulary (`nothing-needed | candidates-proposed | blocked`); the mapping is
294
+ exact so nothing regresses:
295
+
296
+ - `candidates-proposed` → **`candidate-proposed`** — per-item and/or batch
297
+ tickets filed. Report each ticket URL, its recommendation (PROMOTE/DEMOTE +
298
+ rung), and the batch ticket URL with its row count.
299
+ - `nothing-needed` → **`nothing-needed`** (unchanged) — no candidate met any
300
+ recommendation threshold. Report one line: surfaces scanned, entries seen,
301
+ "nothing to propose".
302
+ - `blocked` → **`recovery-required`** when the loop itself could not complete
303
+ (tracker unreachable, contradictory config, a ledger-contract parse error) —
304
+ escalated per Escalation with the operator-readable reason; **or**
305
+ **`approval-requested`** when the run finished and is waiting on a human gate
306
+ rather than being broken.
307
+
308
+ The gardener also newly reaches **`policy-obsolete`** — the Retirement
309
+ condition below tripped and it filed its own teardown proposal. It never
310
+ produces **`change-proved`**: the gardener only files tickets and ships no
311
+ change itself, so proving a change is the implementing factory run's job.
312
+
313
+ Record exactly one outcome per run through the run-record CLI, naming this
314
+ loop's runbook (the `--summary` is the operator-readable one-liner in the
315
+ contract's exemplar voice — plain, specific, actionable):
284
316
 
285
- Exactly one per run: **`nothing-needed | candidates-proposed | blocked`**
317
+ ```bash
318
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/automation-run-record.mjs" \
319
+ --loop-id learnings-audit --outcome candidate-proposed \
320
+ --summary "Proposed 2 promotions and 1 batch confirm; awaiting your flip to ready." \
321
+ --runbook .lisa/automations/learnings-audit.runbook.md [--ref <ticket-url>]...
322
+ ```
286
323
 
287
- - `nothing-needed` no candidate met any recommendation threshold. Healthy.
288
- Report one line: surfaces scanned, entries seen, "nothing to propose".
289
- - `candidates-proposed` — tickets filed. Report each ticket URL, its
290
- recommendation (PROMOTE/DEMOTE + rung), and the batch ticket URL with its
291
- row count.
292
- - `blocked` could not complete; escalated per Escalation with the
293
- operator-readable reason.
324
+ If `${CLAUDE_PLUGIN_ROOT}` is unset, resolve the plugin scripts directory
325
+ directly the built copy `plugins/lisa/scripts/automation-run-record.mjs` or
326
+ the source `plugins/src/base/scripts/automation-run-record.mjs`. If recording
327
+ still fails, **degrade, never abort** (per `automation-runbook-contract`): note
328
+ the recording failure in the run output and finish the run — a recording
329
+ failure is a degradation to report, never a reason to block the loop.
294
330
 
295
331
  ## Retirement condition
296
332
 
@@ -139,3 +139,39 @@ After report, file what was found — **only when run standalone**, never under
139
139
  ## Output
140
140
 
141
141
  A single report: the health/anomaly summary (failures, warnings, no-issue confirmations) + the observability audit table (each in-scope dimension as `OK` / `WARN` / `MISSING` / `PRESENT (unverified)`) + the filing summary (tickets filed with refs + fingerprints, duplicates skipped, dropped count if the cap truncated; or would-file tickets under `--dry-run`). For post-deploy verification (when called from `lisa-verify`), the report-only summary becomes evidence on the originating work item.
142
+
143
+ ## Run outcome
144
+
145
+ As the registered `monitor` automation loop, the **standalone** cron run conforms to the
146
+ `automation-runbook-contract` rule: it ends in **exactly one** of the six run outcomes and records it,
147
+ so a quiet monitoring run and a broken one never look identical.
148
+
149
+ | This cycle's exit path | Run outcome |
150
+ |---|---|
151
+ | Anomalies or in-scope gaps filed — one or more `Bug` / `Task` / `Improvement` leaves created or referenced | `candidate-proposed` |
152
+ | Clean sweep — health/audit ran end to end, nothing over the bar and no in-scope gaps | `nothing-needed` |
153
+ | Provider/threshold resolution failure — threshold collection fails (a present-but-uninspectable config, an invalid configured threshold) or a signal provider is unreachable so the sweep could not run | `recovery-required` |
154
+ | A degradation that still let the sweep run (an optional `ops-specialist` overlay absent, Kane unavailable) | the outcome it actually reached above, with the summary **leading with the degradation** — degradation never mints a seventh token |
155
+
156
+ Only the **standalone** run records. The nested report-only modes do their own job and do not file or
157
+ record: `--report-only` (including the `lisa-verify` post-deploy call, whose summary is evidence on
158
+ the originating item) and `--dry-run` (a preview that creates nothing) are not registered-loop
159
+ invocations.
160
+
161
+ Record **exactly one** outcome per standalone invocation through the run-record CLI, naming this
162
+ loop's runbook (the `--summary` is the operator-readable one-liner in the contract's exemplar voice —
163
+ plain, specific, actionable, e.g. `Health green; audit clean — nothing to propose.` for
164
+ `nothing-needed`):
165
+
166
+ ```bash
167
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/automation-run-record.mjs" \
168
+ --loop-id monitor --outcome candidate-proposed \
169
+ --summary "Filed #1810 for the p99 latency spike; awaiting your flip to ready." \
170
+ --runbook .lisa/automations/monitor.runbook.md [--ref <ticket-url>]...
171
+ ```
172
+
173
+ If `${CLAUDE_PLUGIN_ROOT}` is unset, resolve the plugin scripts directory directly — the built copy
174
+ `plugins/lisa/scripts/automation-run-record.mjs` or the source
175
+ `plugins/src/base/scripts/automation-run-record.mjs`. If recording still fails, **degrade, never
176
+ abort** (per `automation-runbook-contract`): note the recording failure in the run output and finish
177
+ the cycle — a recording failure is a degradation to report, never a reason to block the loop.
@@ -275,6 +275,42 @@ Emit two distinct in-session sections (do not write a report file):
275
275
  Always include the **Personas**, **What Already Exists**, **Discovery Spikes**, and **Rejected**
276
276
  sections (even if empty) so the user sees what was considered and filtered out.
277
277
 
278
+ ## Run outcome
279
+
280
+ As the registered `exploratory-prds` automation loop, this run conforms to the
281
+ `automation-runbook-contract` rule: it ends in **exactly one** of the six run outcomes and records it,
282
+ so a quiet ideation run and a broken one are never confused.
283
+
284
+ | This run's exit path | Run outcome |
285
+ |---|---|
286
+ | PRD(s) created or reused this run (Step 6/7 **PRDs Created**) | `candidate-proposed` |
287
+ | Nothing to ideate — no Practical Idea cleared the bar; nothing created | `nothing-needed` |
288
+ | The Step 5.5 **PRD-queue-pressure gate** blocked auto-ready creation — a human must drain the queue before another auto-ready PRD is added | `approval-requested` |
289
+ | The loop itself could not run — the PRD source reader failed or the queue is misconfigured (a source-reader failure snapshot, not queue pressure) | `recovery-required` |
290
+ | A degradation that still let ideation run (optional Codex automation memory unavailable, an inspiration source unreachable) | the outcome it actually reached above, with the summary **leading with the degradation** — degradation never mints a seventh token |
291
+
292
+ The pressure gate is `approval-requested`, **not** `recovery-required`: the loop ran fine and
293
+ correctly declined to add queue pressure — it is asking a human to drain the queue, not reporting a
294
+ broken machine. `recovery-required` is reserved for the loop failing to run at all.
295
+
296
+ Record **exactly one** outcome per invocation through the run-record CLI, naming this loop's runbook
297
+ (the `--summary` is the operator-readable one-liner in the contract's exemplar voice — plain,
298
+ specific, actionable, e.g. `Reviewed evidence; no practical idea cleared the bar — nothing to
299
+ propose.` for `nothing-needed`):
300
+
301
+ ```bash
302
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/automation-run-record.mjs" \
303
+ --loop-id exploratory-prds --outcome candidate-proposed \
304
+ --summary "Created PRD #1810 for offline export; awaiting your flip to ready." \
305
+ --runbook .lisa/automations/exploratory-prds.runbook.md [--ref <prd-url>]...
306
+ ```
307
+
308
+ If `${CLAUDE_PLUGIN_ROOT}` is unset, resolve the plugin scripts directory directly — the built copy
309
+ `plugins/lisa/scripts/automation-run-record.mjs` or the source
310
+ `plugins/src/base/scripts/automation-run-record.mjs`. If recording still fails, **degrade, never
311
+ abort** (per `automation-runbook-contract`): note the recording failure in the run output and finish
312
+ the run — a recording failure is a degradation to report, never a reason to block the loop.
313
+
278
314
  ## Out of scope (hard rules)
279
315
 
280
316
  - **No fabricated personas.** No evidence citation → no persona; generic roles banned without
@@ -975,6 +975,40 @@ Report outcomes in these buckets:
975
975
  State every item repaired this cycle and the action taken. If the output would be long, group by
976
976
  bucket and show compact refs plus counts.
977
977
 
978
+ ## Run outcome
979
+
980
+ As the registered `intake-repair` automation loop, each cycle conforms to the
981
+ `automation-runbook-contract` rule: it ends in **exactly one** of the six run outcomes and records it,
982
+ so a cycle that found nothing stuck and a cycle where the repair machinery itself broke never look
983
+ alike. A run outcome describes this *cycle*; the Summary-report buckets above describe *what happened
984
+ to each item* — the two never merge in the one-line summary.
985
+
986
+ | This cycle's exit path | Run outcome |
987
+ |---|---|
988
+ | Nothing actionable — the idle case (walk step 5): examined N, all active or in backoff | `nothing-needed` |
989
+ | Repairs applied **and confirmed** this cycle — `resumed` / `resynced` / `recovered` / `unblocked` / `closed_out` / `rolled_up` / `relinked` / `normalized_ready` | `change-proved` |
990
+ | Repair produced new work for a human to pick up — e.g. an unmergeable PR or failed deploy filed as a **build-ready fix ticket** and left `blocked` | `candidate-proposed` |
991
+ | A repair reached an autonomy boundary needing a human (a protected-deploy approval before it can proceed) | `approval-requested` |
992
+ | The loop itself could not run — the queue is unreadable or tracker credentials are revoked | `recovery-required` |
993
+
994
+ Record **exactly one** outcome per invocation through the run-record CLI, naming this loop's runbook
995
+ (the `--summary` is the operator-readable one-liner in the contract's exemplar voice — plain,
996
+ specific, actionable, e.g. `Examined 14 items; all active or in backoff — nothing to repair.` for
997
+ `nothing-needed`):
998
+
999
+ ```bash
1000
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/automation-run-record.mjs" \
1001
+ --loop-id intake-repair --outcome change-proved \
1002
+ --summary "Recovered 3 stalled builds and closed out 2 rollups; all confirmed." \
1003
+ --runbook .lisa/automations/intake-repair.runbook.md [--ref <item-url>]...
1004
+ ```
1005
+
1006
+ If `${CLAUDE_PLUGIN_ROOT}` is unset, resolve the plugin scripts directory directly — the built copy
1007
+ `plugins/lisa/scripts/automation-run-record.mjs` or the source
1008
+ `plugins/src/base/scripts/automation-run-record.mjs`. If recording still fails, **degrade, never
1009
+ abort** (per `automation-runbook-contract`): note the recording failure in the run output and finish
1010
+ the cycle — a recording failure is a degradation to report, never a reason to block the loop.
1011
+
978
1012
  ## Schedule examples
979
1013
 
980
1014
  ```text