@mgiles/perk 3.2.0 → 3.3.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 (202) hide show
  1. package/README.md +5 -0
  2. package/extension/authoring/gist/draft.ts +198 -0
  3. package/extension/authoring/gist/prose.ts +46 -0
  4. package/extension/authoring/gist/review.ts +133 -0
  5. package/extension/authoring/gist/save.ts +118 -0
  6. package/extension/authoring/objective/draft.ts +345 -0
  7. package/extension/{factories/objectiveDreamReport.ts → authoring/objective/dreamReportGate.ts} +74 -131
  8. package/extension/authoring/objective/planning.ts +124 -0
  9. package/extension/authoring/objective/prose.ts +103 -0
  10. package/extension/authoring/objective/review.ts +128 -0
  11. package/extension/authoring/objective/save.ts +224 -0
  12. package/extension/authoring/plan/draft.ts +84 -0
  13. package/extension/authoring/plan/prose.ts +41 -0
  14. package/extension/authoring/plan/review.ts +269 -0
  15. package/extension/authoring/plan/save.ts +256 -0
  16. package/extension/authoring/plan/source.ts +82 -0
  17. package/extension/authoring/refinement/context.ts +468 -0
  18. package/extension/authoring/refinement/draft.ts +261 -0
  19. package/extension/authoring/refinement/prose.ts +79 -0
  20. package/extension/authoring/refinement/review.ts +111 -0
  21. package/extension/authoring/refinement/save.ts +119 -0
  22. package/extension/authoring/review/approvalGate.ts +34 -0
  23. package/extension/authoring/review/draftContext.ts +68 -0
  24. package/extension/codeReview/automated.ts +352 -0
  25. package/extension/codeReview/submission.ts +229 -0
  26. package/extension/delivery/address.ts +295 -0
  27. package/extension/delivery/ci.ts +355 -0
  28. package/extension/delivery/commitCompact.ts +93 -0
  29. package/extension/delivery/conflictResolution.ts +247 -0
  30. package/extension/delivery/ready.ts +193 -0
  31. package/extension/delivery/stackConflict.ts +361 -0
  32. package/extension/delivery/stackObjective.ts +16 -0
  33. package/extension/delivery/stackReconcile.ts +165 -0
  34. package/extension/delivery/submit.ts +171 -0
  35. package/extension/index.ts +365 -380
  36. package/extension/learning/analystWave.ts +324 -0
  37. package/extension/learning/audit.ts +667 -0
  38. package/extension/learning/capture.ts +92 -0
  39. package/extension/learning/containment.ts +104 -0
  40. package/extension/{waves/dreamWave.ts → learning/dream.ts} +112 -94
  41. package/extension/learning/dreamAnalysis.ts +435 -0
  42. package/extension/{waves/dreamReducerWave.ts → learning/dreamReducer.ts} +46 -41
  43. package/extension/{waves → learning}/dreamReport.ts +35 -31
  44. package/extension/learning/harvest.ts +491 -0
  45. package/extension/learning/prose.ts +66 -0
  46. package/extension/learning/routing.ts +79 -0
  47. package/extension/pi/v1/bashScanTimeout.ts +64 -0
  48. package/extension/{doors/prReview.ts → pi/v1/codeReview/automated.ts} +215 -311
  49. package/extension/{doors/prReviewBrowser.ts → pi/v1/codeReview/browser.ts} +53 -33
  50. package/extension/{doors/hunkHandoff.ts → pi/v1/codeReview/checkout.ts} +12 -8
  51. package/extension/{doors/reviewWaveTools.ts → pi/v1/codeReview/reviewWave.ts} +146 -114
  52. package/extension/{doors/stackReviewBrowser.ts → pi/v1/codeReview/stack.ts} +62 -29
  53. package/extension/pi/v1/codeReview/submit.ts +354 -0
  54. package/extension/{doors/prReviewTerminal.ts → pi/v1/codeReview/terminal.ts} +32 -27
  55. package/extension/pi/v1/contextEvidence.ts +80 -0
  56. package/extension/pi/v1/contextInjection.ts +207 -0
  57. package/extension/{doors → pi/v1/delivery}/address.ts +154 -267
  58. package/extension/pi/v1/delivery/ci.ts +570 -0
  59. package/extension/pi/v1/delivery/commitCompact.ts +201 -0
  60. package/extension/pi/v1/delivery/conflictResolverEngine.ts +425 -0
  61. package/extension/{doors → pi/v1/delivery}/land.ts +123 -61
  62. package/extension/pi/v1/delivery/ready.ts +322 -0
  63. package/extension/pi/v1/delivery/stackConflictResolver.ts +172 -0
  64. package/extension/pi/v1/delivery/stackDrive.ts +120 -0
  65. package/extension/pi/v1/delivery/stackLand.ts +223 -0
  66. package/extension/pi/v1/delivery/stackRecover.ts +265 -0
  67. package/extension/pi/v1/delivery/stackStatus.ts +237 -0
  68. package/extension/pi/v1/delivery/stackSync.ts +658 -0
  69. package/extension/pi/v1/delivery/submit.ts +389 -0
  70. package/extension/pi/v1/delivery/submitConflict.ts +186 -0
  71. package/extension/pi/v1/draftReview.ts +431 -0
  72. package/extension/{doors → pi/v1}/draftReviewWaveTools.ts +141 -151
  73. package/extension/pi/v1/gist.ts +794 -0
  74. package/extension/pi/v1/learning/audit.ts +186 -0
  75. package/extension/pi/v1/learning/dream.ts +207 -0
  76. package/extension/{doors/learnFactory.ts → pi/v1/learning/factory.ts} +18 -65
  77. package/extension/{doors/harvestWaveTools.ts → pi/v1/learning/harvest.ts} +46 -100
  78. package/extension/pi/v1/learning/learn.ts +585 -0
  79. package/extension/pi/v1/lifecycleGates.ts +127 -0
  80. package/extension/{factories → pi/v1}/objective.ts +53 -33
  81. package/extension/pi/v1/objectiveAuthoring.ts +672 -0
  82. package/extension/pi/v1/objectiveDreamGate.ts +160 -0
  83. package/extension/{factories/objectivePlan.ts → pi/v1/objectivePlanning.ts} +328 -533
  84. package/extension/pi/v1/objectiveRefinement.ts +1320 -0
  85. package/extension/pi/v1/objectiveReview.ts +451 -0
  86. package/extension/{doors → pi/v1}/objectiveReviewBrowser.ts +259 -172
  87. package/extension/pi/v1/plan.ts +812 -0
  88. package/extension/pi/v1/planReview.ts +820 -0
  89. package/extension/{doors → pi/v1}/planReviewBrowser.ts +228 -152
  90. package/extension/{doors/annotationPush.ts → pi/v1/providers/annotations.ts} +158 -89
  91. package/extension/pi/v1/providers/plannotator.ts +487 -0
  92. package/extension/{doors → pi/v1/providers}/plannotatorHandoff.ts +73 -27
  93. package/extension/pi/v1/providers/selection.ts +43 -0
  94. package/extension/{adapters/planAdapterTombell.ts → pi/v1/providers/tombell.ts} +43 -72
  95. package/extension/pi/v1/review.ts +538 -0
  96. package/extension/pi/v1/reviewOutcome.ts +9 -0
  97. package/extension/pi/v1/scoutWave.ts +318 -0
  98. package/extension/{doors → pi/v1}/selfcheck.ts +4 -4
  99. package/extension/session/branchWorkflowSession.ts +60 -0
  100. package/extension/session/lifecycle.ts +644 -0
  101. package/extension/session/lifecycleGates.ts +64 -0
  102. package/extension/session/saveDestination.ts +87 -0
  103. package/extension/session/workflowSession.ts +971 -0
  104. package/extension/substrate/agentScratch.ts +27 -54
  105. package/extension/substrate/bashScanTimeout.ts +181 -0
  106. package/extension/substrate/bindingDelivery.ts +38 -30
  107. package/extension/substrate/bindings.ts +4 -5
  108. package/extension/substrate/cache.ts +64 -12
  109. package/extension/substrate/childRestrictions.ts +39 -0
  110. package/extension/substrate/coldDoor.ts +17 -1
  111. package/extension/substrate/config.ts +157 -21
  112. package/extension/substrate/git.ts +88 -6
  113. package/extension/substrate/modelVisible.ts +53 -0
  114. package/extension/substrate/prompts.ts +22 -0
  115. package/extension/substrate/registry.ts +2 -0
  116. package/extension/substrate/resolverLease.ts +5 -4
  117. package/extension/substrate/sessionData.ts +85 -152
  118. package/extension/substrate/toolGating.ts +263 -84
  119. package/extension/substrate/unifiedDiff.ts +1 -1
  120. package/extension/substrate/workflowState.ts +178 -163
  121. package/extension/substrate/worktreeResolverLock.ts +261 -0
  122. package/extension/surfaces/surfaces.ts +79 -27
  123. package/extension/waves/adversarialReviewWave.ts +87 -46
  124. package/extension/waves/blockedReports.ts +59 -0
  125. package/extension/waves/draftReviewWave.ts +42 -42
  126. package/extension/waves/laneIdentity.ts +77 -0
  127. package/extension/waves/objectiveExplorerWave.ts +24 -24
  128. package/extension/waves/prReviewWave.ts +89 -77
  129. package/extension/waves/reportWave.ts +438 -578
  130. package/extension/waves/reviewClassifierWave.ts +22 -22
  131. package/extension/waves/rpcAdapter.ts +100 -15
  132. package/extension/waves/scoutWave.ts +192 -0
  133. package/extension/waves/transport.ts +480 -0
  134. package/extension/worker/sdkAdapter.ts +494 -0
  135. package/extension/worker/stageExecution.ts +679 -0
  136. package/extension/workerMain.ts +18 -19
  137. package/package.json +6 -4
  138. package/prompts/_fixtures/live.yaml +43 -18
  139. package/prompts/contexts/adapters/plannotator-gist.md +6 -0
  140. package/prompts/contexts/adapters/plannotator-objective.md +6 -0
  141. package/prompts/contexts/adapters/plannotator-plan.md +8 -1
  142. package/prompts/contexts/adapters/plannotator-refinement.md +22 -0
  143. package/prompts/contexts/objective-refinement.md +17 -0
  144. package/prompts/contexts/read-only.md +1 -1
  145. package/prompts/stages/conflict-resolution-continuation.md +9 -6
  146. package/prompts/stages/conflict-resolution.md +4 -4
  147. package/prompts/stages/objective-plan/guidance.md +2 -2
  148. package/prompts/stages/objective-plan/seed.md +9 -1
  149. package/prompts/stages/objective-reconcile-ready.md +1 -1
  150. package/prompts/stages/objective-reconcile.md +1 -1
  151. package/prompts/stages/objective-refine/seed.md +18 -0
  152. package/prompts/stages/objective-review-browser.md +4 -4
  153. package/prompts/stages/objective-sync.md +1 -1
  154. package/prompts/stages/plan-review-browser.md +4 -4
  155. package/prompts/stages/pr-review-browser/active.md +3 -4
  156. package/prompts/stages/pr-review-browser/foreign.md +3 -4
  157. package/prompts/stages/pr-review-terminal/active.md +3 -3
  158. package/prompts/stages/pr-review-terminal/foreign.md +3 -3
  159. package/prompts/stages/pr-review.md +3 -3
  160. package/prompts/stages/stack-review-browser/stack.md +5 -6
  161. package/shared/README.md +8 -0
  162. package/shared/bindings.yaml +3 -3
  163. package/shared/contracts.md +2601 -506
  164. package/shared/fixtures/issues-table.json +130 -0
  165. package/shared/registry.yaml +13 -0
  166. package/shared/schemas/outputs/objective-node-engagement.schema.json +318 -0
  167. package/shared/schemas/outputs/objective-stack-status.schema.json +6 -1
  168. package/shared/schemas/outputs/pr-review-context.schema.json +54 -9
  169. package/shared/schemas/outputs/pr-review-stack-context.schema.json +196 -0
  170. package/extension/adapters/planAdapterPlannotator.ts +0 -362
  171. package/extension/doors/auditWaveTools.ts +0 -352
  172. package/extension/doors/ciExecutor.ts +0 -756
  173. package/extension/doors/commitCompact.ts +0 -251
  174. package/extension/doors/dreamWaveTools.ts +0 -489
  175. package/extension/doors/learn.ts +0 -668
  176. package/extension/doors/lifecycleGates.ts +0 -207
  177. package/extension/doors/objectiveStack.ts +0 -1543
  178. package/extension/doors/prReviewDynamic.ts +0 -276
  179. package/extension/doors/ready.ts +0 -279
  180. package/extension/doors/submit.ts +0 -373
  181. package/extension/doors/submitPrReview.ts +0 -505
  182. package/extension/factories/gistAuthor.ts +0 -94
  183. package/extension/factories/gistDraft.ts +0 -265
  184. package/extension/factories/gistSave.ts +0 -251
  185. package/extension/factories/implementHere.ts +0 -116
  186. package/extension/factories/objectiveAuthor.ts +0 -98
  187. package/extension/factories/objectiveDraft.ts +0 -466
  188. package/extension/factories/objectiveSave.ts +0 -366
  189. package/extension/factories/planDraft.ts +0 -140
  190. package/extension/factories/planMode.ts +0 -205
  191. package/extension/factories/planReview.ts +0 -1237
  192. package/extension/factories/planSave.ts +0 -604
  193. package/extension/factories/planTitle.ts +0 -141
  194. package/extension/substrate/structuredOutput.ts +0 -202
  195. package/extension/waves/auditWave.ts +0 -312
  196. package/extension/waves/harvestWave.ts +0 -399
  197. package/extension/waves/learnWave.ts +0 -155
  198. package/extension/waves/memoryAdapter.ts +0 -139
  199. package/extension/waves/prReviewDynamicWave.ts +0 -777
  200. package/extension/worker/readOnlySession.ts +0 -294
  201. package/extension/worker/worker.ts +0 -899
  202. package/prompts/stages/pr-review-dynamic.md +0 -7
@@ -1,251 +0,0 @@
1
- // The warm `/commit-and-compact` door: commit the work so far, then compact the session.
2
- //
3
- // Human-only slash command (no model-facing tool twin, no cold door, no workflow-state field —
4
- // warm-plane only). The commit half needs the model (real staging judgment + a real commit
5
- // message), so the dirty arm DRIVES the session (`pi.sendUserMessage`, warm-door discipline);
6
- // the compaction half is deterministic extension work keyed on `agent_settled` (the one-shot
7
- // "the driven run fully settled" hook — `turn_end` would compact mid-run). Fail-safe posture:
8
- // never compact when uncommitted work might exist — the undeterminable-git-state and no-commit
9
- // arms skip compaction with a loud warning naming pi's builtin `/compact` escape hatch. Clean
10
- // and read-only trees compact immediately (the commit half is vacuous there).
11
- //
12
- // The pending record is in-memory by design (lost on `/reload` — the user re-runs the command);
13
- // re-invoking while a drive is in flight simply overwrites it.
14
-
15
- import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
16
- import { bindingSuffix } from "../substrate/bindingDelivery.ts";
17
- import type { PlanRef } from "../substrate/cache.ts";
18
- import { registerPerkCommand } from "../substrate/command.ts";
19
- import { commitsSince, headSha, worktreeDirty } from "../substrate/git.ts";
20
- import { render } from "../substrate/prompts.ts";
21
- import type { ToolGating } from "../substrate/toolGating.ts";
22
- import { branchOf, rebuildWorkflowState } from "../substrate/workflowState.ts";
23
- import { report, type Severity } from "../surfaces/report.ts";
24
- import { planReadInstruction } from "./lifecycleGates.ts";
25
-
26
- /** The driven-commit guidance (pure + exported for offline tests and the drive-coverage guard). */
27
- export function commitAndCompactGuidance(): string {
28
- return render("commit-and-compact.md", {});
29
- }
30
-
31
- /**
32
- * Compaction instructions for the arms with nothing to commit (read-only / clean tree). Inline,
33
- * not a `prompts/` template — compaction `customInstructions` stay inline (the objective
34
- * threshold-compaction precedent); only injected user-message prose goes to `prompts/`.
35
- */
36
- export const DIRECT_COMPACT_INSTRUCTIONS =
37
- "Preserve the current task's intent, progress so far, and the concrete next steps.";
38
-
39
- /**
40
- * Compaction instructions for the committed arm: embed the `git log --oneline` listing of the
41
- * new commit(s) so the summary references them. Pure + exported for offline tests.
42
- */
43
- export function compactInstructions(commits: string | null): string {
44
- return [
45
- "The work completed so far was just committed:",
46
- "",
47
- commits ?? "(commit list unavailable)",
48
- "",
49
- "Preserve in the summary: the task being implemented and its current progress, what the new " +
50
- "commit(s) contain, and the concrete next steps for the remaining work. The committed diff " +
51
- "is recoverable via git, so prefer intent and next steps over restating the diff.",
52
- ].join("\n");
53
- }
54
-
55
- /** The one-shot record the dirty/drive arm leaves for the `agent_settled` handler. */
56
- export interface PendingCompact {
57
- cwd: string;
58
- /** HEAD at invocation (null on an unborn HEAD) — the advance gate compares against this. */
59
- headBefore: string | null;
60
- }
61
-
62
- export type CommitCompactCompletion =
63
- | { outcome: "committed"; commits: string | null }
64
- | { outcome: "clean" }
65
- | { outcome: "read-only" };
66
-
67
- /** The door's side-effect surface — `ExtensionContext`-backed in wiring, recorder fakes in tests. */
68
- export interface CommitCompactIo {
69
- report(severity: Severity, message: string): void;
70
- send(guidance: string): void;
71
- compact(customInstructions: string, completion: CommitCompactCompletion): void;
72
- }
73
-
74
- function isNonEmptyString(value: unknown): value is string {
75
- return typeof value === "string" && value.trim() !== "";
76
- }
77
-
78
- /**
79
- * The command-specific active-plan resolver. Session-tier `active_plan_ref` is the only authority:
80
- * a checkout cache ref can select a future plan and is unrelated to this live session.
81
- */
82
- export function activeSessionPlanRef(ctx: ExtensionContext): PlanRef | null {
83
- try {
84
- const ref: unknown = rebuildWorkflowState(branchOf(ctx)).active_plan_ref;
85
- if (typeof ref !== "object" || ref === null) return null;
86
- const candidate = ref as Record<string, unknown>;
87
- if (
88
- !isNonEmptyString(candidate.provider) ||
89
- !isNonEmptyString(candidate.pr_id) ||
90
- !isNonEmptyString(candidate.url)
91
- ) {
92
- return null;
93
- }
94
- if (
95
- !Array.isArray(candidate.labels) ||
96
- !candidate.labels.every((label) => typeof label === "string")
97
- ) {
98
- return null;
99
- }
100
- if (candidate.objective_id !== null && typeof candidate.objective_id !== "string") return null;
101
- if (
102
- candidate.base !== undefined &&
103
- candidate.base !== null &&
104
- typeof candidate.base !== "string"
105
- ) {
106
- return null;
107
- }
108
- return {
109
- provider: candidate.provider,
110
- pr_id: candidate.pr_id,
111
- url: candidate.url,
112
- labels: candidate.labels,
113
- objective_id: candidate.objective_id,
114
- ...(candidate.base !== undefined ? { base: candidate.base } : {}),
115
- };
116
- } catch {
117
- return null;
118
- }
119
- }
120
-
121
- /** Render the completion-gated turn that reorients the resumed agent from repository evidence. */
122
- export function commitAndCompactContinuation(
123
- planRef: PlanRef | null,
124
- completion: CommitCompactCompletion,
125
- ): string {
126
- const provider = planRef?.provider ?? "";
127
- const planId = planRef?.pr_id ?? "";
128
- const planUrl = planRef?.url ?? "";
129
- const readCmd =
130
- planRef === null ? "" : planReadInstruction(planRef.provider, planRef.pr_id, planRef.url);
131
- return render("commit-and-compact-continuation.md", {
132
- provider,
133
- plan_id: planId,
134
- plan_url: planUrl,
135
- read_cmd: readCmd,
136
- is_github: provider === "github" ? "x" : "",
137
- committed: completion.outcome === "committed" ? "x" : "",
138
- clean: completion.outcome === "clean" ? "x" : "",
139
- read_only: completion.outcome === "read-only" ? "x" : "",
140
- commits: completion.outcome === "committed" ? (completion.commits ?? "") : "",
141
- });
142
- }
143
-
144
- /**
145
- * The invocation arms (gate → undeterminable → clean → dirty, in that order). Returns the
146
- * pending record only on the dirty/drive arm — every other arm resolves immediately.
147
- */
148
- export function startCommitAndCompact(
149
- cwd: string,
150
- gateActive: boolean,
151
- io: CommitCompactIo,
152
- ): PendingCompact | null {
153
- if (gateActive) {
154
- io.report("info", "read-only session — nothing to commit; compacting…");
155
- io.compact(DIRECT_COMPACT_INSTRUCTIONS, { outcome: "read-only" });
156
- return null;
157
- }
158
- const dirty = worktreeDirty(cwd);
159
- if (dirty === null) {
160
- // Fail-safe: never compact when uncommitted work might exist.
161
- io.report(
162
- "warning",
163
- "cannot determine the git worktree state — compaction skipped; run /compact to compact anyway.",
164
- );
165
- return null;
166
- }
167
- if (!dirty) {
168
- io.report("info", "worktree clean — nothing to commit; compacting…");
169
- io.compact(DIRECT_COMPACT_INSTRUCTIONS, { outcome: "clean" });
170
- return null;
171
- }
172
- io.report("info", "driving a commit of the work completed so far…");
173
- const headBefore = headSha(cwd);
174
- io.send(commitAndCompactGuidance());
175
- return { cwd, headBefore };
176
- }
177
-
178
- /**
179
- * The settle arms: compact only when HEAD actually advanced past the invocation-time sha;
180
- * otherwise (model declined / commit failed / HEAD unreadable) warn and skip — same fail-safe.
181
- */
182
- export function settleCommitAndCompact(pending: PendingCompact, io: CommitCompactIo): void {
183
- const headNow = headSha(pending.cwd);
184
- if (headNow === null || headNow === pending.headBefore) {
185
- io.report(
186
- "warning",
187
- "no commit was made — compaction skipped; run /compact to compact anyway.",
188
- );
189
- return;
190
- }
191
- io.report("info", "committed — compacting the session…");
192
- const commits = commitsSince(pending.cwd, pending.headBefore);
193
- io.compact(compactInstructions(commits), { outcome: "committed", commits });
194
- }
195
-
196
- /** Register the `/commit-and-compact` command + its one-shot `agent_settled` consumer. */
197
- export function registerCommitAndCompact(pi: ExtensionAPI, gating: ToolGating): void {
198
- let pending: PendingCompact | null = null;
199
-
200
- const ioFor = (ctx: ExtensionContext): CommitCompactIo => ({
201
- report: (severity, message) => {
202
- report(ctx, "commit-and-compact", severity, message);
203
- },
204
- send: (guidance) => {
205
- // The trigger lets repos bind a skill via `[[bindings]]`; drive unconditionally — report()
206
- // already carries the headless stderr fallback.
207
- pi.sendUserMessage(guidance + bindingSuffix(ctx.cwd, "command:commit-and-compact"));
208
- },
209
- compact: (customInstructions, completion) => {
210
- // Render while the command/event context is current. Manual compaction stays in the same
211
- // AgentSession + extension runner, so onComplete may use captured `pi`; it must not read
212
- // `ctx` or recompute session/filesystem state after compaction.
213
- const continuation = commitAndCompactContinuation(activeSessionPlanRef(ctx), completion);
214
- ctx.compact({
215
- customInstructions,
216
- onComplete: () => {
217
- try {
218
- // Optionless on purpose: resume immediately under the active stage's own bindings.
219
- pi.sendUserMessage(continuation);
220
- } catch (error) {
221
- console.error(`perk: commit-and-compact — continuation dispatch failed — ${error}`);
222
- }
223
- },
224
- onError: (error) => {
225
- console.error(`perk: commit-and-compact — compaction failed — ${error}`);
226
- },
227
- });
228
- },
229
- });
230
-
231
- pi.on("agent_settled", async (_event, ctx) => {
232
- if (pending === null) return;
233
- const record = pending;
234
- pending = null; // consume-then-clear: the record is strictly one-shot
235
- try {
236
- settleCommitAndCompact(record, ioFor(ctx));
237
- } catch (error) {
238
- console.error(`perk: commit-and-compact — settle handling failed — ${error}`);
239
- }
240
- });
241
-
242
- registerPerkCommand(pi, "commit-and-compact", {
243
- description:
244
- "Commit the work completed so far (a driven model turn stages and writes the message), " +
245
- "compact, then continue automatically after compaction succeeds. Clean or read-only " +
246
- "sessions compact immediately; a skipped or failed compaction never continues.",
247
- handler: async (_args, ctx) => {
248
- pending = startCommitAndCompact(ctx.cwd, gating.isActive(), ioFor(ctx));
249
- },
250
- });
251
- }