@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
@@ -0,0 +1,64 @@
1
+ // Pi-free session-lifecycle gate policy: the planning-stage lifecycle-door refusal (the shared
2
+ // first check of the warm /submit, /address, /land, and /learn doors) and the plan-read handoff
3
+ // priming for a fresh implement session. The Pi registration half (the session_before_fork/
4
+ // switch hooks + the guard-only `/implement` command) lives in `pi/v1/lifecycleGates.ts`; this
5
+ // module carries the policy those adapters apply.
6
+
7
+ import type { PlanRef } from "../substrate/cache.ts";
8
+ import { planReadInstruction, render } from "../substrate/prompts.ts";
9
+ import { type BranchSource, branchOf, rebuildWorkflowState } from "../substrate/workflowState.ts";
10
+
11
+ // The planning stages whose sessions never legitimately run lifecycle doors. After an approved
12
+ // save, a still-live planning session holds TWO plan identities — the cwd binding (a positioned
13
+ // stacked session's predecessor checkout, read via readPlanRef(ctx.cwd)) and the just-saved plan
14
+ // on active_plan_ref — so a door invocation there could act on the predecessor. At the repo root
15
+ // the same invocation fails confusingly today; the refusal is honest in both shapes.
16
+ const PLANNING_STAGES = new Set(["plan", "objective-plan"]);
17
+
18
+ /**
19
+ * The planning-stage lifecycle-door refusal (the shared first check of the warm /submit,
20
+ * /address, /land, and /learn doors): when this session's workflow-state `stage` is a planning
21
+ * stage, return the refusal message directing the human at the fresh-session implement door;
22
+ * `null` otherwise (non-planning stages — and stage-less sessions — are unaffected). Fail-CLOSED
23
+ * on an unreadable branch: without the state this guard cannot prove the session is not a
24
+ * positioned planning session (whose cwd binding is the PREDECESSOR — the exact target it
25
+ * protects), so an unreadable read refuses rather than letting the door act.
26
+ */
27
+ export function planningStageRefusal(ctx: BranchSource, door: string): string | null {
28
+ let stage: string | undefined;
29
+ try {
30
+ stage = rebuildWorkflowState(branchOf(ctx)).stage;
31
+ } catch (error) {
32
+ return (
33
+ `${door} is unavailable: the session's workflow state could not be read ` +
34
+ `(${String(error)}), so this cannot be proven not to be a planning session — ` +
35
+ "retry, or implement the saved plan with `perk impl <N>` in a fresh session."
36
+ );
37
+ }
38
+ if (stage === undefined || !PLANNING_STAGES.has(stage)) return null;
39
+ return (
40
+ `${door} is unavailable in a planning session (stage ${stage}): a planning session can ` +
41
+ "hold two plan identities (its checkout's own binding and the just-saved plan) — " +
42
+ "implement the saved plan with `perk impl <N>` in a fresh session instead."
43
+ );
44
+ }
45
+
46
+ /**
47
+ * The plan-read priming seed for a fresh implement session. The in-session twin of
48
+ * `perk/run/launch.py`'s `_implement_prompt`: carry the plan FORWARD (read it from its canonical
49
+ * source), never summarize it — the plan is the only artifact that crosses the boundary.
50
+ *
51
+ * The wording lives in the canonical template `prompts/stages/implement.md`, rendered by the shared
52
+ * seam (contracts.md §8.31); branching stays in code — only the `read_cmd` var differs. This warm
53
+ * handoff is now byte-identical to the cold/worker primer, so it carries the same "Progress
54
+ * tracking:" tail (the prior shorter near-copy omission is removed).
55
+ */
56
+ export function implementHandoffPrompt(ref: PlanRef): string {
57
+ const readCmd = planReadInstruction(ref.provider, String(ref.pr_id), ref.url);
58
+ return render("stages/implement.md", {
59
+ provider: ref.provider,
60
+ pr_id: String(ref.pr_id),
61
+ url: ref.url,
62
+ read_cmd: readCmd,
63
+ });
64
+ }
@@ -0,0 +1,87 @@
1
+ // The save-destination fence's capture: WHERE an approved draft would be written, reduced to
2
+ // per-component digests so a review can tell "the destination moved" from "unrelated config
3
+ // noise" without ever retaining or reporting a raw routing value (contracts.md §8.23).
4
+ //
5
+ // Exactly three inputs route a save — the committed `[issues] backend`/`team` (the Python
6
+ // resolver's whole vocabulary), the git `remote.*.url`/`remote.*.gh-resolved` entries `gh`
7
+ // resolves the repo from (GitHub backend only; Linear never reads remotes), and the objective
8
+ // node claim a plan save links to. Everything else (`branch.*`, `user.*`, `[workflow] base`,
9
+ // credentials, the process environment, the run handoff) is deliberately NOT a component: none
10
+ // of it decides where the artifact lands, so none of it may strand an approval.
11
+ //
12
+ // The `issues` component digests the two keys only while the extension's TOML subset reader
13
+ // provably reads them as Python's `tomllib` does; a spelling it cannot vouch for (dotted keys,
14
+ // an inline table, escapes …) widens the component to the whole committed document, so a
15
+ // routing edit the subset reader cannot see still moves the digest. Widening over-fences
16
+ // (an unrelated edit to that file then reads as "issues changed"); it never under-fences.
17
+ import { type IssueRouting, resolveIssueRouting } from "../substrate/config.ts";
18
+ import { remoteConfig } from "../substrate/git.ts";
19
+ import { digestSessionData } from "../substrate/sessionData.ts";
20
+
21
+ export const DESTINATION_COMPONENTS = ["issues", "remotes", "node_claim"] as const;
22
+ export type DestinationComponent = (typeof DESTINATION_COMPONENTS)[number];
23
+
24
+ /** Component name → `digestSessionData(value)`. No aggregate digest; no raw value retained. */
25
+ export type SaveDestination = Readonly<Partial<Record<DestinationComponent, string>>>;
26
+
27
+ /** The seams the capture shells through — injectable so tests can prove the Linear arm never forks git. */
28
+ export interface SaveDestinationPorts {
29
+ issues(cwd: string): IssueRouting;
30
+ remotes(cwd: string): string | null;
31
+ }
32
+
33
+ const PRODUCTION_PORTS: SaveDestinationPorts = {
34
+ issues: resolveIssueRouting,
35
+ remotes: remoteConfig,
36
+ };
37
+
38
+ /** The `issues` component's digest input: the proven keys, or the unproven document verbatim. */
39
+ function issuesComponent(issues: IssueRouting): string {
40
+ return issues.kind === "keys"
41
+ ? JSON.stringify({ backend: issues.backend, team: issues.team })
42
+ : JSON.stringify({ document: issues.text });
43
+ }
44
+
45
+ /**
46
+ * Capture the save destination at `cwd` for a review that would link `nodeClaim`. `issues` and
47
+ * `node_claim` are always present; `remotes` whenever the read backend is anything but exactly
48
+ * `"linear"` — GitHub, unset (the fail-safe default), unknown, or a value the reader cannot
49
+ * vouch for (an escaped `"\u0067ithub"` reads verbatim here while Python saves to GitHub):
50
+ * only a Linear save never consults git remotes, so only there does no git subprocess run. (The
51
+ * only way the subset reader reads `"linear"` is a bare `[issues]` table `tomllib` reads the
52
+ * same way.) Returns `null` when the destination cannot be verified (the GitHub arm's remotes
53
+ * read failed) — callers must treat that as "unverifiable", never as "unchanged".
54
+ */
55
+ export function captureSaveDestination(
56
+ cwd: string,
57
+ nodeClaim: { objective: string; node: string } | null,
58
+ ports: SaveDestinationPorts = PRODUCTION_PORTS,
59
+ ): SaveDestination | null {
60
+ const issues = ports.issues(cwd);
61
+ const destination: Partial<Record<DestinationComponent, string>> = {
62
+ issues: digestSessionData(issuesComponent(issues)),
63
+ node_claim: digestSessionData(
64
+ JSON.stringify(
65
+ nodeClaim === null ? null : { objective: nodeClaim.objective, node: nodeClaim.node },
66
+ ),
67
+ ),
68
+ };
69
+ if (issues.backend !== "linear") {
70
+ const remotes = ports.remotes(cwd);
71
+ if (remotes === null) return null;
72
+ destination.remotes = digestSessionData(remotes);
73
+ }
74
+ return destination;
75
+ }
76
+
77
+ /**
78
+ * The components whose digests differ between the reviewed and current captures, in
79
+ * `DESTINATION_COMPONENTS` order; a key present on one side only counts as changed. "Changed at
80
+ * all" is `changed.length > 0`.
81
+ */
82
+ export function changedDestinationComponents(
83
+ reviewed: SaveDestination,
84
+ current: SaveDestination,
85
+ ): DestinationComponent[] {
86
+ return DESTINATION_COMPONENTS.filter((component) => reviewed[component] !== current[component]);
87
+ }