@mgiles/perk 2.3.0 → 3.0.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 +1 -1
- package/extension/adapters/planAdapterPlannotator.ts +132 -91
- package/extension/adapters/planAdapterTombell.ts +5 -3
- package/extension/doors/address.ts +235 -37
- package/extension/doors/annotationPush.ts +924 -0
- package/extension/doors/auditWaveTools.ts +352 -0
- package/extension/doors/ciExecutor.ts +220 -55
- package/extension/doors/draftReviewWaveTools.ts +384 -0
- package/extension/doors/harvestWaveTools.ts +279 -0
- package/extension/doors/land.ts +1 -0
- package/extension/doors/learn.ts +24 -6
- package/extension/doors/learnFactory.ts +33 -7
- package/extension/doors/lifecycleGates.ts +1 -1
- package/extension/doors/objectiveReviewBrowser.ts +514 -0
- package/extension/doors/objectiveStack.ts +1143 -0
- package/extension/doors/planReviewBrowser.ts +453 -0
- package/extension/doors/plannotatorHandoff.ts +120 -49
- package/extension/doors/prReview.ts +26 -16
- package/extension/doors/prReviewBrowser.ts +31 -23
- package/extension/doors/prReviewDynamic.ts +25 -18
- package/extension/doors/prReviewTerminal.ts +6 -11
- package/extension/doors/reviewWaveTools.ts +374 -0
- package/extension/doors/selfcheck.ts +1 -1
- package/extension/doors/submit.ts +82 -7
- package/extension/factories/gistAuthor.ts +4 -4
- package/extension/factories/gistDraft.ts +1 -1
- package/extension/factories/gistSave.ts +2 -2
- package/extension/factories/objective.ts +7 -7
- package/extension/factories/objectiveAuthor.ts +5 -4
- package/extension/factories/objectiveDraft.ts +61 -6
- package/extension/factories/objectivePlan.ts +163 -9
- package/extension/factories/objectiveSave.ts +16 -1
- package/extension/factories/planMode.ts +5 -3
- package/extension/factories/planReview.ts +131 -36
- package/extension/factories/planTitle.ts +27 -9
- package/extension/hunkFeedback/inbox.ts +389 -0
- package/extension/hunkFeedback/perkFeedback.ts +364 -0
- package/extension/hunkFeedback/receiver.ts +296 -0
- package/extension/hunkFeedback/store.ts +533 -0
- package/extension/index.ts +109 -44
- package/extension/substrate/cache.ts +75 -22
- package/extension/substrate/coldDoor.ts +2 -3
- package/extension/substrate/config.ts +36 -12
- package/extension/substrate/git.ts +10 -0
- package/extension/substrate/providers.ts +4 -33
- package/extension/substrate/resources.ts +11 -0
- package/extension/substrate/result.ts +13 -5
- package/extension/substrate/sessionData.ts +3 -3
- package/extension/substrate/sessionPointers.ts +3 -3
- package/extension/substrate/structuredOutput.ts +78 -19
- package/extension/substrate/toolGating.ts +170 -23
- package/extension/substrate/workflowState.ts +6 -0
- package/extension/surfaces/footerProvider.ts +6 -6
- package/extension/surfaces/surfaces.ts +98 -282
- package/extension/vendor/btw/btw.ts +57 -12
- package/extension/waves/adversarialReviewWave.ts +164 -0
- package/extension/waves/auditWave.ts +312 -0
- package/extension/waves/draftReviewWave.ts +189 -0
- package/extension/waves/harvestWave.ts +399 -0
- package/extension/waves/memoryAdapter.ts +14 -1
- package/extension/waves/objectiveExplorerWave.ts +120 -0
- package/extension/waves/prReviewDynamicWave.ts +291 -61
- package/extension/waves/prReviewWave.ts +58 -13
- package/extension/waves/reportWave.ts +406 -106
- package/extension/waves/reviewClassifierWave.ts +109 -0
- package/extension/waves/rpcAdapter.ts +65 -2
- package/extension/worker/readOnlySession.ts +3 -3
- package/extension/worker/worker.ts +71 -93
- package/extension/workerMain.ts +4 -6
- package/package.json +15 -5
- package/prompts/README.md +19 -0
- package/prompts/_fixtures/live.yaml +66 -65
- package/prompts/common/resume-advisory.md +1 -0
- package/prompts/contexts/adapters/plannotator-gist.md +13 -0
- package/prompts/contexts/adapters/plannotator-objective.md +1 -2
- package/prompts/contexts/adapters/plannotator-plan.md +1 -2
- package/prompts/contexts/gist-authoring.md +6 -20
- package/prompts/contexts/objective-authoring.md +6 -18
- package/prompts/stages/address/action.md +3 -14
- package/prompts/stages/address/preview.md +2 -13
- package/prompts/stages/audit.md +18 -0
- package/prompts/stages/gist-author/seed.md +4 -4
- package/prompts/stages/gist-save.md +1 -1
- package/prompts/stages/implement.md +3 -1
- package/prompts/stages/learn-code.md +1 -1
- package/prompts/stages/learn-docs.md +2 -2
- package/prompts/stages/learn-harvest.md +15 -0
- package/prompts/stages/learn-orchestrate.md +1 -1
- package/prompts/stages/objective-author/adopt.md +5 -3
- package/prompts/stages/objective-author/file.md +5 -4
- package/prompts/stages/objective-author/seed.md +5 -4
- package/prompts/stages/objective-land.md +7 -0
- package/prompts/stages/objective-plan/guidance.md +2 -13
- package/prompts/stages/objective-plan/seed.md +5 -12
- package/prompts/stages/objective-recover.md +8 -0
- package/prompts/stages/objective-replan.md +4 -2
- package/prompts/stages/objective-review-browser.md +9 -0
- package/prompts/stages/objective-sync.md +6 -0
- package/prompts/stages/plan-from/adopt.md +2 -2
- package/prompts/stages/plan-from/file.md +2 -2
- package/prompts/stages/plan-review-browser.md +9 -0
- package/prompts/stages/pr-review-browser/active.md +6 -14
- package/prompts/stages/pr-review-browser/foreign.md +6 -14
- package/prompts/stages/pr-review-dynamic.md +3 -3
- package/prompts/stages/pr-review-terminal/active.md +7 -15
- package/prompts/stages/pr-review-terminal/foreign.md +7 -15
- package/prompts/stages/pr-review.md +2 -2
- package/prompts/stages/replan.md +3 -3
- package/shared/README.md +2 -2
- package/shared/bindings.yaml +12 -0
- package/shared/contracts-history.md +11 -0
- package/shared/contracts.md +3652 -236
- package/shared/providers.yaml +27 -60
- package/shared/registry.yaml +32 -8
- package/shared/schemas/outputs/objective-doctor.schema.json +449 -0
- package/shared/schemas/outputs/objective-stack-land.schema.json +732 -0
- package/shared/schemas/outputs/objective-stack-recover.schema.json +397 -0
- package/shared/schemas/outputs/objective-stack-status.schema.json +577 -0
- package/shared/schemas/outputs/objective-stack-sync.schema.json +184 -0
- package/shared/schemas/outputs/plan-save.schema.json +12 -0
- package/shared/schemas/outputs/pr-submit.schema.json +177 -1
- package/extension/adapters/todoAdapterJuicesharp.ts +0 -102
- package/extension/checkpoints/checkpoints.ts +0 -550
- package/extension/checkpoints/planSteps.ts +0 -108
- package/extension/doors/askUser.ts +0 -198
- package/prompts/common/output-schemas/objective-explorer.md +0 -36
- package/prompts/common/output-schemas/review-classifier.md +0 -47
- package/prompts/contexts/adapters/juicesharp-todo.md +0 -7
package/extension/doors/learn.ts
CHANGED
|
@@ -53,7 +53,7 @@ import {
|
|
|
53
53
|
stringField,
|
|
54
54
|
} from "../substrate/coldDoor.ts";
|
|
55
55
|
import { registerPerkCommand } from "../substrate/command.ts";
|
|
56
|
-
import {
|
|
56
|
+
import { subagentModel } from "../substrate/config.ts";
|
|
57
57
|
import { render } from "../substrate/prompts.ts";
|
|
58
58
|
import { failFor, ok, type Result } from "../substrate/result.ts";
|
|
59
59
|
import { arrayParam, paramsOf, stringParam } from "../substrate/toolParams.ts";
|
|
@@ -65,7 +65,11 @@ import {
|
|
|
65
65
|
type LearnAngleSelection,
|
|
66
66
|
runLearnWave,
|
|
67
67
|
} from "../waves/learnWave.ts";
|
|
68
|
-
import
|
|
68
|
+
import {
|
|
69
|
+
toAttemptReceipt,
|
|
70
|
+
type WaveAdapter,
|
|
71
|
+
type WaveAttemptReceipt,
|
|
72
|
+
} from "../waves/reportWave.ts";
|
|
69
73
|
import { createRpcWaveAdapter } from "../waves/rpcAdapter.ts";
|
|
70
74
|
import { planReadInstruction } from "./lifecycleGates.ts";
|
|
71
75
|
|
|
@@ -301,9 +305,12 @@ export function learnOrchestrateGuidance(opts: {
|
|
|
301
305
|
export interface LearnWaveOk {
|
|
302
306
|
reports: { angle: string; report: unknown }[];
|
|
303
307
|
skipped: { angle: string; reason: string; detail: string }[];
|
|
308
|
+
/** The single launch's output-free attempt receipt (observability only — details, not prose). */
|
|
309
|
+
attempts: WaveAttemptReceipt[];
|
|
304
310
|
}
|
|
305
311
|
|
|
306
|
-
|
|
312
|
+
/** The fail arm retains any receipt known before the failure (the `failFor` extras hook). */
|
|
313
|
+
export type LearnWaveResult = Result<LearnWaveOk, { attempts: WaveAttemptReceipt[] }>;
|
|
307
314
|
|
|
308
315
|
/**
|
|
309
316
|
* The `run_learn_wave` execute core, extracted for testability with the adapter as the injected
|
|
@@ -326,7 +333,7 @@ export async function executeLearnWave(
|
|
|
326
333
|
signal?: AbortSignal;
|
|
327
334
|
},
|
|
328
335
|
): Promise<LearnWaveResult> {
|
|
329
|
-
const fail = failFor(target, "run_learn_wave");
|
|
336
|
+
const fail = failFor<{ attempts: WaveAttemptReceipt[] }>(target, "run_learn_wave");
|
|
330
337
|
const manifestPath = join(opts.bundleDir, "manifest.json");
|
|
331
338
|
const result = await runLearnWave(
|
|
332
339
|
adapter,
|
|
@@ -338,12 +345,23 @@ export async function executeLearnWave(
|
|
|
338
345
|
},
|
|
339
346
|
opts.signal,
|
|
340
347
|
);
|
|
348
|
+
// The learn flow has no retry — ONE attempt over the validated selection.
|
|
349
|
+
const attempts = [
|
|
350
|
+
toAttemptReceipt(
|
|
351
|
+
"learn",
|
|
352
|
+
1,
|
|
353
|
+
opts.selections.map((s) => s.angle),
|
|
354
|
+
result.receipt,
|
|
355
|
+
),
|
|
356
|
+
];
|
|
341
357
|
|
|
342
358
|
if (!result.complete) {
|
|
343
359
|
const waveFailure = result.failures.find((f) => f.key === null);
|
|
360
|
+
// The receipt known before the failure rides the fail details (never the prose).
|
|
344
361
|
return fail(
|
|
345
362
|
waveFailure?.detail ?? "the analyst wave failed without detail",
|
|
346
363
|
waveFailure?.reason ?? "run-failed",
|
|
364
|
+
{ attempts },
|
|
347
365
|
);
|
|
348
366
|
}
|
|
349
367
|
|
|
@@ -368,7 +386,7 @@ export async function executeLearnWave(
|
|
|
368
386
|
.join("\n")}`,
|
|
369
387
|
);
|
|
370
388
|
}
|
|
371
|
-
return ok(parts.join("\n\n"), { reports, skipped });
|
|
389
|
+
return ok(parts.join("\n\n"), { reports, skipped, attempts });
|
|
372
390
|
}
|
|
373
391
|
|
|
374
392
|
const WAVE_TOOL_GUIDELINES = [
|
|
@@ -533,7 +551,7 @@ export function registerLearn(pi: ExtensionAPI): void {
|
|
|
533
551
|
}
|
|
534
552
|
// Model resolution lives here (not in the guidance): `[models.subagents] learn-analyst`
|
|
535
553
|
// rides the wave as the workflow-level `model` default.
|
|
536
|
-
const model =
|
|
554
|
+
const model = subagentModel(ctx.cwd, "learn-analyst");
|
|
537
555
|
return executeLearnWave(createRpcWaveAdapter(pi.events), ctx, {
|
|
538
556
|
bundleDir,
|
|
539
557
|
selections,
|
|
@@ -6,21 +6,27 @@
|
|
|
6
6
|
// Each door DELEGATES the gather to the Python plane (`perk learn <kind> --gather --json` via the
|
|
7
7
|
// shared cold-door client `runColdDoor` — gate-safe, not subject to the read-only bash allowlist),
|
|
8
8
|
// decodes `{ inbox_path, learn_numbers }`, then injects the factory guidance via
|
|
9
|
-
// `pi.sendUserMessage` so the model reads the inbox, authors the plan, and saves it. The
|
|
10
|
-
//
|
|
11
|
-
// the
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
9
|
+
// `pi.sendUserMessage` so the model reads the inbox, authors the plan, and saves it. The warm
|
|
10
|
+
// gather is side-effect-free and writes NO handoff carrier, so `plan_save` passing
|
|
11
|
+
// `consumed_learn` explicitly is the ONLY surface that can carry the consumed numbers here — the
|
|
12
|
+
// interactive host guard (contracts.md §8.2) enforces it: an interactive session where the
|
|
13
|
+
// `plan_save` tool is not currently active (`pi.getActiveTools()` — the authority, reflecting the
|
|
14
|
+
// read-only gate, worktree stage scoping, AND foreign providers' `setActiveTools` restrictions
|
|
15
|
+
// that write no perk workflow-state) is refused BEFORE the gather, pointing at the cold door
|
|
16
|
+
// (`perk learn docs` / `perk learn code`), whose handoff carrier supplies `consumed_learn` on the
|
|
17
|
+
// review-first save path. Workflow-state only flavors the refusal message, never decides it. No
|
|
18
|
+
// model tool is registered here.
|
|
15
19
|
//
|
|
16
20
|
// Headless-safe: rich UI is guarded by `ctx.hasUI`; without a UI it logs to stderr and returns
|
|
17
|
-
// (the gather still runs so the inbox is materialized, but no turn is driven
|
|
21
|
+
// (the gather still runs so the inbox is materialized, but no turn is driven — the save hazard
|
|
22
|
+
// cannot occur, so the guard is interactive-only).
|
|
18
23
|
|
|
19
24
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
20
25
|
import { bindingSuffix } from "../substrate/bindingDelivery.ts";
|
|
21
26
|
import { type ColdJson, runColdDoor, stringField } from "../substrate/coldDoor.ts";
|
|
22
27
|
import { registerPerkCommand } from "../substrate/command.ts";
|
|
23
28
|
import { render } from "../substrate/prompts.ts";
|
|
29
|
+
import { branchOf, rebuildWorkflowState } from "../substrate/workflowState.ts";
|
|
24
30
|
import { report } from "../surfaces/report.ts";
|
|
25
31
|
|
|
26
32
|
/**
|
|
@@ -106,6 +112,26 @@ export function registerLearnFactoryDoor(pi: ExtensionAPI, kind: LearnFactoryDoo
|
|
|
106
112
|
registerPerkCommand(pi, kind.name, {
|
|
107
113
|
description: kind.description,
|
|
108
114
|
handler: async (_args, ctx: ExtensionContext) => {
|
|
115
|
+
// The interactive host guard (see the header): refuse BEFORE the gather when `plan_save`
|
|
116
|
+
// is not currently active — `pi.getActiveTools()` is the authoritative predicate;
|
|
117
|
+
// workflow-state only flavors the message (it cannot see foreign restrictions).
|
|
118
|
+
if (ctx.hasUI && !pi.getActiveTools().includes("plan_save")) {
|
|
119
|
+
const state = rebuildWorkflowState(branchOf(ctx));
|
|
120
|
+
const why =
|
|
121
|
+
state.mode === "read-only"
|
|
122
|
+
? "this session is read-only"
|
|
123
|
+
: state.stage !== undefined
|
|
124
|
+
? `this session is scoped to the ${state.stage} stage`
|
|
125
|
+
: "a provider restriction hides it";
|
|
126
|
+
report(
|
|
127
|
+
ctx,
|
|
128
|
+
kind.name,
|
|
129
|
+
"error",
|
|
130
|
+
`the plan_save tool is not active here (${why}), so this session cannot save a plan ` +
|
|
131
|
+
`carrying consumed_learn — use the cold door instead: perk learn ${kind.subcommand}.`,
|
|
132
|
+
);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
109
135
|
// Report-only door (no Result type): branch on `errorType` directly (the coldDoor header
|
|
110
136
|
// convention). A clean empty inbox exits non-zero with error_type=no_learn_issues — the
|
|
111
137
|
// client's envelope-aware arm surfaces it gently.
|
|
@@ -81,7 +81,7 @@ export function planReadInstruction(provider: string, prId: string, url: string)
|
|
|
81
81
|
* The wording lives in the canonical template `prompts/stages/implement.md`, rendered by the shared
|
|
82
82
|
* seam (contracts.md §8.31); branching stays in code — only the `read_cmd` var differs. This warm
|
|
83
83
|
* handoff is now byte-identical to the cold/worker primer, so it carries the same "Progress
|
|
84
|
-
*
|
|
84
|
+
* tracking:" tail (the prior shorter near-copy omission is removed).
|
|
85
85
|
*/
|
|
86
86
|
export function implementHandoffPrompt(ref: PlanRef): string {
|
|
87
87
|
const readCmd = planReadInstruction(ref.provider, String(ref.pr_id), ref.url);
|