@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.
- package/README.md +5 -0
- package/extension/authoring/gist/draft.ts +198 -0
- package/extension/authoring/gist/prose.ts +46 -0
- package/extension/authoring/gist/review.ts +133 -0
- package/extension/authoring/gist/save.ts +118 -0
- package/extension/authoring/objective/draft.ts +345 -0
- package/extension/{factories/objectiveDreamReport.ts → authoring/objective/dreamReportGate.ts} +74 -131
- package/extension/authoring/objective/planning.ts +124 -0
- package/extension/authoring/objective/prose.ts +103 -0
- package/extension/authoring/objective/review.ts +128 -0
- package/extension/authoring/objective/save.ts +224 -0
- package/extension/authoring/plan/draft.ts +84 -0
- package/extension/authoring/plan/prose.ts +41 -0
- package/extension/authoring/plan/review.ts +269 -0
- package/extension/authoring/plan/save.ts +256 -0
- package/extension/authoring/plan/source.ts +82 -0
- package/extension/authoring/refinement/context.ts +468 -0
- package/extension/authoring/refinement/draft.ts +261 -0
- package/extension/authoring/refinement/prose.ts +79 -0
- package/extension/authoring/refinement/review.ts +111 -0
- package/extension/authoring/refinement/save.ts +119 -0
- package/extension/authoring/review/approvalGate.ts +34 -0
- package/extension/authoring/review/draftContext.ts +68 -0
- package/extension/codeReview/automated.ts +352 -0
- package/extension/codeReview/submission.ts +229 -0
- package/extension/delivery/address.ts +295 -0
- package/extension/delivery/ci.ts +355 -0
- package/extension/delivery/commitCompact.ts +93 -0
- package/extension/delivery/conflictResolution.ts +247 -0
- package/extension/delivery/ready.ts +193 -0
- package/extension/delivery/stackConflict.ts +361 -0
- package/extension/delivery/stackObjective.ts +16 -0
- package/extension/delivery/stackReconcile.ts +165 -0
- package/extension/delivery/submit.ts +171 -0
- package/extension/index.ts +365 -380
- package/extension/learning/analystWave.ts +324 -0
- package/extension/learning/audit.ts +667 -0
- package/extension/learning/capture.ts +92 -0
- package/extension/learning/containment.ts +104 -0
- package/extension/{waves/dreamWave.ts → learning/dream.ts} +112 -94
- package/extension/learning/dreamAnalysis.ts +435 -0
- package/extension/{waves/dreamReducerWave.ts → learning/dreamReducer.ts} +46 -41
- package/extension/{waves → learning}/dreamReport.ts +35 -31
- package/extension/learning/harvest.ts +491 -0
- package/extension/learning/prose.ts +66 -0
- package/extension/learning/routing.ts +79 -0
- package/extension/pi/v1/bashScanTimeout.ts +64 -0
- package/extension/{doors/prReview.ts → pi/v1/codeReview/automated.ts} +215 -311
- package/extension/{doors/prReviewBrowser.ts → pi/v1/codeReview/browser.ts} +53 -33
- package/extension/{doors/hunkHandoff.ts → pi/v1/codeReview/checkout.ts} +12 -8
- package/extension/{doors/reviewWaveTools.ts → pi/v1/codeReview/reviewWave.ts} +146 -114
- package/extension/{doors/stackReviewBrowser.ts → pi/v1/codeReview/stack.ts} +62 -29
- package/extension/pi/v1/codeReview/submit.ts +354 -0
- package/extension/{doors/prReviewTerminal.ts → pi/v1/codeReview/terminal.ts} +32 -27
- package/extension/pi/v1/contextEvidence.ts +80 -0
- package/extension/pi/v1/contextInjection.ts +207 -0
- package/extension/{doors → pi/v1/delivery}/address.ts +154 -267
- package/extension/pi/v1/delivery/ci.ts +570 -0
- package/extension/pi/v1/delivery/commitCompact.ts +201 -0
- package/extension/pi/v1/delivery/conflictResolverEngine.ts +425 -0
- package/extension/{doors → pi/v1/delivery}/land.ts +123 -61
- package/extension/pi/v1/delivery/ready.ts +322 -0
- package/extension/pi/v1/delivery/stackConflictResolver.ts +172 -0
- package/extension/pi/v1/delivery/stackDrive.ts +120 -0
- package/extension/pi/v1/delivery/stackLand.ts +223 -0
- package/extension/pi/v1/delivery/stackRecover.ts +265 -0
- package/extension/pi/v1/delivery/stackStatus.ts +237 -0
- package/extension/pi/v1/delivery/stackSync.ts +658 -0
- package/extension/pi/v1/delivery/submit.ts +389 -0
- package/extension/pi/v1/delivery/submitConflict.ts +186 -0
- package/extension/pi/v1/draftReview.ts +431 -0
- package/extension/{doors → pi/v1}/draftReviewWaveTools.ts +141 -151
- package/extension/pi/v1/gist.ts +794 -0
- package/extension/pi/v1/learning/audit.ts +186 -0
- package/extension/pi/v1/learning/dream.ts +207 -0
- package/extension/{doors/learnFactory.ts → pi/v1/learning/factory.ts} +18 -65
- package/extension/{doors/harvestWaveTools.ts → pi/v1/learning/harvest.ts} +46 -100
- package/extension/pi/v1/learning/learn.ts +585 -0
- package/extension/pi/v1/lifecycleGates.ts +127 -0
- package/extension/{factories → pi/v1}/objective.ts +53 -33
- package/extension/pi/v1/objectiveAuthoring.ts +672 -0
- package/extension/pi/v1/objectiveDreamGate.ts +160 -0
- package/extension/{factories/objectivePlan.ts → pi/v1/objectivePlanning.ts} +328 -533
- package/extension/pi/v1/objectiveRefinement.ts +1320 -0
- package/extension/pi/v1/objectiveReview.ts +451 -0
- package/extension/{doors → pi/v1}/objectiveReviewBrowser.ts +259 -172
- package/extension/pi/v1/plan.ts +812 -0
- package/extension/pi/v1/planReview.ts +820 -0
- package/extension/{doors → pi/v1}/planReviewBrowser.ts +228 -152
- package/extension/{doors/annotationPush.ts → pi/v1/providers/annotations.ts} +158 -89
- package/extension/pi/v1/providers/plannotator.ts +487 -0
- package/extension/{doors → pi/v1/providers}/plannotatorHandoff.ts +73 -27
- package/extension/pi/v1/providers/selection.ts +43 -0
- package/extension/{adapters/planAdapterTombell.ts → pi/v1/providers/tombell.ts} +43 -72
- package/extension/pi/v1/review.ts +538 -0
- package/extension/pi/v1/reviewOutcome.ts +9 -0
- package/extension/pi/v1/scoutWave.ts +318 -0
- package/extension/{doors → pi/v1}/selfcheck.ts +4 -4
- package/extension/session/branchWorkflowSession.ts +60 -0
- package/extension/session/lifecycle.ts +644 -0
- package/extension/session/lifecycleGates.ts +64 -0
- package/extension/session/saveDestination.ts +87 -0
- package/extension/session/workflowSession.ts +971 -0
- package/extension/substrate/agentScratch.ts +27 -54
- package/extension/substrate/bashScanTimeout.ts +181 -0
- package/extension/substrate/bindingDelivery.ts +38 -30
- package/extension/substrate/bindings.ts +4 -5
- package/extension/substrate/cache.ts +64 -12
- package/extension/substrate/childRestrictions.ts +39 -0
- package/extension/substrate/coldDoor.ts +17 -1
- package/extension/substrate/config.ts +157 -21
- package/extension/substrate/git.ts +88 -6
- package/extension/substrate/modelVisible.ts +53 -0
- package/extension/substrate/prompts.ts +22 -0
- package/extension/substrate/registry.ts +2 -0
- package/extension/substrate/resolverLease.ts +5 -4
- package/extension/substrate/sessionData.ts +85 -152
- package/extension/substrate/toolGating.ts +263 -84
- package/extension/substrate/unifiedDiff.ts +1 -1
- package/extension/substrate/workflowState.ts +178 -163
- package/extension/substrate/worktreeResolverLock.ts +261 -0
- package/extension/surfaces/surfaces.ts +79 -27
- package/extension/waves/adversarialReviewWave.ts +87 -46
- package/extension/waves/blockedReports.ts +59 -0
- package/extension/waves/draftReviewWave.ts +42 -42
- package/extension/waves/laneIdentity.ts +77 -0
- package/extension/waves/objectiveExplorerWave.ts +24 -24
- package/extension/waves/prReviewWave.ts +89 -77
- package/extension/waves/reportWave.ts +438 -578
- package/extension/waves/reviewClassifierWave.ts +22 -22
- package/extension/waves/rpcAdapter.ts +100 -15
- package/extension/waves/scoutWave.ts +192 -0
- package/extension/waves/transport.ts +480 -0
- package/extension/worker/sdkAdapter.ts +494 -0
- package/extension/worker/stageExecution.ts +679 -0
- package/extension/workerMain.ts +18 -19
- package/package.json +6 -4
- package/prompts/_fixtures/live.yaml +43 -18
- package/prompts/contexts/adapters/plannotator-gist.md +6 -0
- package/prompts/contexts/adapters/plannotator-objective.md +6 -0
- package/prompts/contexts/adapters/plannotator-plan.md +8 -1
- package/prompts/contexts/adapters/plannotator-refinement.md +22 -0
- package/prompts/contexts/objective-refinement.md +17 -0
- package/prompts/contexts/read-only.md +1 -1
- package/prompts/stages/conflict-resolution-continuation.md +9 -6
- package/prompts/stages/conflict-resolution.md +4 -4
- package/prompts/stages/objective-plan/guidance.md +2 -2
- package/prompts/stages/objective-plan/seed.md +9 -1
- package/prompts/stages/objective-reconcile-ready.md +1 -1
- package/prompts/stages/objective-reconcile.md +1 -1
- package/prompts/stages/objective-refine/seed.md +18 -0
- package/prompts/stages/objective-review-browser.md +4 -4
- package/prompts/stages/objective-sync.md +1 -1
- package/prompts/stages/plan-review-browser.md +4 -4
- package/prompts/stages/pr-review-browser/active.md +3 -4
- package/prompts/stages/pr-review-browser/foreign.md +3 -4
- package/prompts/stages/pr-review-terminal/active.md +3 -3
- package/prompts/stages/pr-review-terminal/foreign.md +3 -3
- package/prompts/stages/pr-review.md +3 -3
- package/prompts/stages/stack-review-browser/stack.md +5 -6
- package/shared/README.md +8 -0
- package/shared/bindings.yaml +3 -3
- package/shared/contracts.md +2601 -506
- package/shared/fixtures/issues-table.json +130 -0
- package/shared/registry.yaml +13 -0
- package/shared/schemas/outputs/objective-node-engagement.schema.json +318 -0
- package/shared/schemas/outputs/objective-stack-status.schema.json +6 -1
- package/shared/schemas/outputs/pr-review-context.schema.json +54 -9
- package/shared/schemas/outputs/pr-review-stack-context.schema.json +196 -0
- package/extension/adapters/planAdapterPlannotator.ts +0 -362
- package/extension/doors/auditWaveTools.ts +0 -352
- package/extension/doors/ciExecutor.ts +0 -756
- package/extension/doors/commitCompact.ts +0 -251
- package/extension/doors/dreamWaveTools.ts +0 -489
- package/extension/doors/learn.ts +0 -668
- package/extension/doors/lifecycleGates.ts +0 -207
- package/extension/doors/objectiveStack.ts +0 -1543
- package/extension/doors/prReviewDynamic.ts +0 -276
- package/extension/doors/ready.ts +0 -279
- package/extension/doors/submit.ts +0 -373
- package/extension/doors/submitPrReview.ts +0 -505
- package/extension/factories/gistAuthor.ts +0 -94
- package/extension/factories/gistDraft.ts +0 -265
- package/extension/factories/gistSave.ts +0 -251
- package/extension/factories/implementHere.ts +0 -116
- package/extension/factories/objectiveAuthor.ts +0 -98
- package/extension/factories/objectiveDraft.ts +0 -466
- package/extension/factories/objectiveSave.ts +0 -366
- package/extension/factories/planDraft.ts +0 -140
- package/extension/factories/planMode.ts +0 -205
- package/extension/factories/planReview.ts +0 -1237
- package/extension/factories/planSave.ts +0 -604
- package/extension/factories/planTitle.ts +0 -141
- package/extension/substrate/structuredOutput.ts +0 -202
- package/extension/waves/auditWave.ts +0 -312
- package/extension/waves/harvestWave.ts +0 -399
- package/extension/waves/learnWave.ts +0 -155
- package/extension/waves/memoryAdapter.ts +0 -139
- package/extension/waves/prReviewDynamicWave.ts +0 -777
- package/extension/worker/readOnlySession.ts +0 -294
- package/extension/worker/worker.ts +0 -899
- 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
|
-
}
|