@mgiles/perk 3.1.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 (211) 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 +369 -359
  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 -310
  49. package/extension/{doors/prReviewBrowser.ts → pi/v1/codeReview/browser.ts} +125 -57
  50. package/extension/{doors/hunkHandoff.ts → pi/v1/codeReview/checkout.ts} +12 -8
  51. package/extension/{doors/reviewWaveTools.ts → pi/v1/codeReview/reviewWave.ts} +169 -116
  52. package/extension/pi/v1/codeReview/stack.ts +606 -0
  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 +163 -265
  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 +128 -60
  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/{doors → pi/v1}/lifecycleGates.ts +14 -59
  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/pi/v1/objectivePlanning.ts +776 -0
  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 +152 -34
  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 -19
  112. package/extension/substrate/git.ts +88 -6
  113. package/extension/substrate/modelVisible.ts +53 -0
  114. package/extension/substrate/paths.ts +2 -7
  115. package/extension/substrate/prompts.ts +22 -0
  116. package/extension/substrate/registry.ts +2 -0
  117. package/extension/substrate/resolverLease.ts +364 -0
  118. package/extension/substrate/sessionData.ts +85 -152
  119. package/extension/substrate/toolGating.ts +279 -84
  120. package/extension/substrate/unifiedDiff.ts +1 -1
  121. package/extension/substrate/workflowState.ts +191 -166
  122. package/extension/substrate/worktreeResolverLock.ts +261 -0
  123. package/extension/surfaces/surfaces.ts +79 -27
  124. package/extension/waves/adversarialReviewWave.ts +103 -48
  125. package/extension/waves/blockedReports.ts +59 -0
  126. package/extension/waves/draftReviewWave.ts +42 -42
  127. package/extension/waves/laneIdentity.ts +77 -0
  128. package/extension/waves/objectiveExplorerWave.ts +24 -24
  129. package/extension/waves/prReviewWave.ts +89 -77
  130. package/extension/waves/reportWave.ts +438 -578
  131. package/extension/waves/reviewClassifierWave.ts +22 -22
  132. package/extension/waves/rpcAdapter.ts +100 -15
  133. package/extension/waves/scoutWave.ts +192 -0
  134. package/extension/waves/transport.ts +480 -0
  135. package/extension/worker/sdkAdapter.ts +494 -0
  136. package/extension/worker/stageExecution.ts +679 -0
  137. package/extension/workerMain.ts +18 -19
  138. package/package.json +6 -4
  139. package/prompts/_fixtures/live.yaml +98 -10
  140. package/prompts/contexts/adapters/plannotator-gist.md +6 -0
  141. package/prompts/contexts/adapters/plannotator-objective.md +6 -0
  142. package/prompts/contexts/adapters/plannotator-plan.md +8 -1
  143. package/prompts/contexts/adapters/plannotator-refinement.md +22 -0
  144. package/prompts/contexts/adapters/tombell-plan.md +4 -0
  145. package/prompts/contexts/objective-refinement.md +17 -0
  146. package/prompts/contexts/plan-authoring.md +6 -5
  147. package/prompts/contexts/read-only.md +1 -1
  148. package/prompts/stages/conflict-resolution-continuation.md +9 -0
  149. package/prompts/stages/conflict-resolution.md +4 -4
  150. package/prompts/stages/objective-author/adopt.md +1 -1
  151. package/prompts/stages/objective-author/file.md +1 -1
  152. package/prompts/stages/objective-author/seed.md +1 -1
  153. package/prompts/stages/objective-plan/guidance.md +2 -2
  154. package/prompts/stages/objective-plan/seed.md +9 -1
  155. package/prompts/stages/objective-reconcile-ready.md +7 -0
  156. package/prompts/stages/objective-reconcile.md +1 -1
  157. package/prompts/stages/objective-refine/seed.md +18 -0
  158. package/prompts/stages/objective-review-browser.md +4 -4
  159. package/prompts/stages/objective-sync.md +1 -1
  160. package/prompts/stages/plan-review-browser.md +4 -4
  161. package/prompts/stages/pr-review-browser/active.md +3 -4
  162. package/prompts/stages/pr-review-browser/foreign.md +3 -4
  163. package/prompts/stages/pr-review-terminal/active.md +3 -3
  164. package/prompts/stages/pr-review-terminal/foreign.md +3 -3
  165. package/prompts/stages/pr-review.md +3 -3
  166. package/prompts/stages/stack-review/cold.md +1 -0
  167. package/prompts/stages/stack-review-browser/stack.md +22 -0
  168. package/shared/README.md +8 -3
  169. package/shared/bindings.yaml +6 -3
  170. package/shared/contracts.md +4499 -2147
  171. package/shared/fixtures/issues-table.json +130 -0
  172. package/shared/registry.yaml +29 -1
  173. package/shared/schemas/outputs/objective-node-engagement.schema.json +318 -0
  174. package/shared/schemas/outputs/objective-stack-status.schema.json +178 -2
  175. package/shared/schemas/outputs/pr-ready.schema.json +110 -2
  176. package/shared/schemas/outputs/pr-review-context.schema.json +54 -9
  177. package/shared/schemas/outputs/pr-review-stack-context.schema.json +196 -0
  178. package/extension/adapters/planAdapterPlannotator.ts +0 -362
  179. package/extension/doors/auditWaveTools.ts +0 -352
  180. package/extension/doors/ciExecutor.ts +0 -756
  181. package/extension/doors/commitCompact.ts +0 -251
  182. package/extension/doors/dreamWaveTools.ts +0 -475
  183. package/extension/doors/learn.ts +0 -655
  184. package/extension/doors/objectiveStack.ts +0 -1143
  185. package/extension/doors/prReviewDynamic.ts +0 -276
  186. package/extension/doors/ready.ts +0 -87
  187. package/extension/doors/submit.ts +0 -347
  188. package/extension/doors/submitPrReview.ts +0 -408
  189. package/extension/factories/gistAuthor.ts +0 -94
  190. package/extension/factories/gistDraft.ts +0 -265
  191. package/extension/factories/gistSave.ts +0 -251
  192. package/extension/factories/implementHere.ts +0 -116
  193. package/extension/factories/objectiveAuthor.ts +0 -98
  194. package/extension/factories/objectiveDraft.ts +0 -466
  195. package/extension/factories/objectivePlan.ts +0 -975
  196. package/extension/factories/objectiveSave.ts +0 -363
  197. package/extension/factories/planDraft.ts +0 -140
  198. package/extension/factories/planMode.ts +0 -205
  199. package/extension/factories/planReview.ts +0 -1237
  200. package/extension/factories/planSave.ts +0 -604
  201. package/extension/factories/planTitle.ts +0 -141
  202. package/extension/substrate/structuredOutput.ts +0 -202
  203. package/extension/waves/auditWave.ts +0 -312
  204. package/extension/waves/harvestWave.ts +0 -399
  205. package/extension/waves/learnWave.ts +0 -155
  206. package/extension/waves/memoryAdapter.ts +0 -139
  207. package/extension/waves/prReviewDynamicWave.ts +0 -777
  208. package/extension/worker/readOnlySession.ts +0 -294
  209. package/extension/worker/worker.ts +0 -899
  210. package/prompts/stages/pr-review-dynamic.md +0 -7
  211. package/shared/contracts-history.md +0 -605
@@ -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
+ }