@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
@@ -1,205 +0,0 @@
1
- // perk-owned plan mode. The first consumer of the tool-gating primitive
2
- // (extension/substrate/toolGating.ts). This is the *toggle surface* on top of that structural gate: a
3
- // `/plan` command, a `Ctrl+Alt+P` shortcut, and a `--plan` flag all flip `gating.enter`/`exit`.
4
- // perk owns NO parallel enforcement here — the gate is the single read-only authority.
5
- //
6
- // It also injects the cooperative *plan-authoring* prompt layer (the gather-then-plan contract)
7
- // under its own `perk:plan-context` customType (display:false, once-only: branch-scan dedup'd on
8
- // the marker),
9
- // keyed directly off the read-only gate (read-only ⟹ plan in the main session). The
10
- // content is stripped from `context` when the gate is off — the same hygiene the gate applies to its
11
- // `perk:mode-context`. An optional `[workflow] plan_authoring` config addendum (extension/substrate/config.ts)
12
- // is appended when present.
13
- //
14
- // Grounded in pi's official `examples/extensions/plan-mode/` recipe, but perk adopts ONLY the
15
- // read-only authoring half: there is no in-session "execution mode" flip — perk separates plan
16
- // (read-only session) from implement (cold-door fresh worktree session), and progress tracking
17
- // lives in the implement session.
18
- //
19
- // REGISTRATION-TIME DEFERRAL, now THREE-TIER. `registerPlanMode` resolves the plan
20
- // provider id once at factory time and branches:
21
- // - `perk-plan` (and the fail-safe error path) → register EVERYTHING (the default path is the
22
- // hard guarantee, zero behavior change).
23
- // - `plannotator-plan` (AUGMENT posture) → register everything EXCEPT the `--plan` flag, the
24
- // `Ctrl+Alt+P` shortcut, and the `--plan` session_start handler: `@plannotator/pi-extension`
25
- // also registers that flag + shortcut, and duplicate flag/shortcut registration is the known
26
- // potentially-fatal Pi behavior — plannotator owns `--plan`/`Ctrl+Alt+P` exclusively while
27
- // perk keeps `/plan`, the authoring injection, and the read-only gate (plannotator augments
28
- // perk's plan flow via the planAdapterPlannotator `plan_review` bridge; it does not replace it).
29
- // - any other foreign id (tombell, REPLACE posture) → register NOTHING; the foreign package owns
30
- // `/plan`/`Ctrl+Alt+P`/`--plan` unambiguously (Pi suffixes duplicate command names, so
31
- // handler-time deferral alone is insufficient once the foreign package is loaded).
32
-
33
- import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
34
- import { registerPerkCommand } from "../substrate/command.ts";
35
- import { loadPerkConfig } from "../substrate/config.ts";
36
- import { render } from "../substrate/prompts.ts";
37
- import {
38
- loadProviders,
39
- PERK_PLAN_PROVIDER_ID,
40
- PLANNOTATOR_PLAN_PROVIDER_ID,
41
- resolveProviders,
42
- } from "../substrate/providers.ts";
43
- import type { ToolGating } from "../substrate/toolGating.ts";
44
- import { branchCarries, branchOf, rebuildWorkflowState } from "../substrate/workflowState.ts";
45
- import { report } from "../surfaces/report.ts";
46
- // `Key` via the surfaces re-export (keybinding vocabulary, not rich UI) — keeps pi-tui imports
47
- // structurally confined to the surfaces module (the surfacesGuard pi-tui import rule).
48
- import { Key } from "../surfaces/surfaces.ts";
49
- import { GIST_AUTHOR_STAGE } from "./gistAuthor.ts";
50
- import { OBJECTIVE_AUTHOR_STAGE } from "./objectiveAuthor.ts";
51
-
52
- /** The plan-authoring context customType (distinct from the gate's `perk:mode-context`). */
53
- export const PLAN_CONTEXT_TYPE = "perk:plan-context";
54
- const PLAN_MARKER = "[PLAN AUTHORING]";
55
-
56
- /**
57
- * The cooperative gather-then-plan contract. This is prompting, NOT enforcement (the gate is the
58
- * enforcement). It never leaks internal policy text — it tells the model how to materialize a
59
- * decision-complete plan an executor with zero prior context can follow. Per contracts.md §8.57
60
- * this mode context is the plan stage's DESIGNATED FLOW CARRIER in every plan-stage session
61
- * shape (seeded doors carry launch-shape deltas only; the `perk-plan` skill is the detail tier).
62
- * Durable anchors only, no line numbers.
63
- */
64
- export const PLAN_AUTHORING_CONTEXT = render("contexts/plan-authoring.md", {
65
- marker: PLAN_MARKER,
66
- });
67
-
68
- /** Build the full plan-authoring injection, appending the project config addendum when present. */
69
- export function planContextContent(cwd: string): string {
70
- const addendum = loadPerkConfig(cwd).planAuthoring;
71
- return addendum ? `${PLAN_AUTHORING_CONTEXT}\n\n${addendum.trim()}` : PLAN_AUTHORING_CONTEXT;
72
- }
73
-
74
- /**
75
- * The resolved `[providers] plan` selection id for `cwd`, read fresh per-event (no static state —
76
- * the same per-event-read shape `planContextContent(ctx.cwd)` uses). Fail-safe to the perk-plan
77
- * reference: any load/resolution failure returns the reference id so perk's own plan mode keeps
78
- * working — the default path is the hard guarantee. With the resolver's per-seam fail-open
79
- * fallbacks this catch narrows to genuine file-read/parse failures — logged loudly (consoleCapture
80
- * routes it into the session log), never swallowed: a silent catch here once masked a
81
- * version-skew throw and silently swapped the review surface to first-party.
82
- */
83
- export function resolvedPlanProviderId(cwd: string): string {
84
- try {
85
- return resolveProviders(loadPerkConfig(cwd).providers, loadProviders()).plan.id;
86
- } catch (error) {
87
- console.error(
88
- `perk: plan provider resolution failed — falling back to ${PERK_PLAN_PROVIDER_ID}: ${error}`,
89
- );
90
- return PERK_PLAN_PROVIDER_ID;
91
- }
92
- }
93
-
94
- /**
95
- * Whether perk's own plan-mode reference is the selected plan provider for `cwd`. When a foreign
96
- * plan provider is selected via `[providers] plan`, perk's authoring surface steps aside (defers).
97
- */
98
- export function isPerkPlanReferenceSelected(cwd: string): boolean {
99
- return resolvedPlanProviderId(cwd) === PERK_PLAN_PROVIDER_ID;
100
- }
101
-
102
- /**
103
- * Register the perk-owned plan-mode toggle surface over the read-only gate. Idempotent enter/exit (the gate
104
- * tracks its own on/off transition), fail-safe-headless (notify when UI, else stderr).
105
- */
106
- export function registerPlanMode(pi: ExtensionAPI, gating: ToolGating): void {
107
- // Three-tier registration branch (see the header comment): full registration for the reference
108
- // (fail-safe default), a PARTIAL vacate (skip only `--plan` + `Ctrl+Alt+P`) under the augment-
109
- // posture plannotator selection, and a full vacate under any other foreign selection (tombell).
110
- const providerId = resolvedPlanProviderId(process.cwd());
111
- const plannotatorSelected = providerId === PLANNOTATOR_PLAN_PROVIDER_ID;
112
- if (providerId !== PERK_PLAN_PROVIDER_ID && !plannotatorSelected) return;
113
-
114
- if (!plannotatorSelected) {
115
- pi.registerFlag("plan", {
116
- description: "Start in perk plan mode (read-only exploration + plan authoring).",
117
- type: "boolean",
118
- default: false,
119
- });
120
- }
121
-
122
- function announce(ctx: ExtensionContext, on: boolean): void {
123
- const message = on
124
- ? "plan mode ON — read-only exploration; author the plan, then review with plan_review (approval auto-saves; /plan-save is the manual failsafe)."
125
- : "plan mode OFF — full tool access restored.";
126
- report(ctx, "plan-mode", "info", message);
127
- }
128
-
129
- function toggle(ctx: ExtensionContext): void {
130
- if (gating.isActive()) {
131
- gating.exit(ctx);
132
- announce(ctx, false);
133
- } else {
134
- gating.enter(ctx);
135
- announce(ctx, true);
136
- }
137
- }
138
-
139
- registerPerkCommand(pi, "plan", {
140
- description: "Toggle perk plan mode (read-only exploration + plan authoring).",
141
- handler: async (_args, ctx) => toggle(ctx),
142
- });
143
-
144
- if (!plannotatorSelected) {
145
- pi.registerShortcut(Key.ctrlAlt("p"), {
146
- description: "Toggle perk plan mode",
147
- handler: async (ctx) => toggle(ctx),
148
- });
149
-
150
- // `--plan` cold start: enter read-only on session_start when the flag is set and the gate is
151
- // off. (index.ts's session_start already syncs the gate from the rebuilt `mode`; this layers
152
- // the flag on top for ad-hoc `pi --plan` interactive starts — the cold plan door drives
153
- // read-only via the handoff `mode`, not this flag.) Skipped under the plannotator selection
154
- // along with the flag itself (the flag no longer exists on perk's side).
155
- pi.on("session_start", async (_event, ctx) => {
156
- if (pi.getFlag("plan") === true && !gating.isActive()) {
157
- gating.enter(ctx);
158
- }
159
- });
160
- }
161
-
162
- // Inject the plan-authoring context while the read-only gate is active (display:false). The
163
- // exceptions: objective-author and gist-author sessions are ALSO read-only, but
164
- // objectiveAuthor.ts / gistAuthor.ts inject their own authoring contexts there — so plan mode
165
- // defers when the launched stage is either (the coupling break: plan-authoring context is no
166
- // longer keyed off the bare read-only gate).
167
- pi.on("before_agent_start", async (_event, ctx) => {
168
- if (!gating.isActive()) return;
169
- const branch = branchOf(ctx);
170
- const launchedStage = rebuildWorkflowState(branch).stage;
171
- if (launchedStage === OBJECTIVE_AUTHOR_STAGE || launchedStage === GIST_AUTHOR_STAGE) return;
172
- // Once-only: injected customs persist to the branch, so a live copy suppresses re-injection;
173
- // compaction dropping it makes the scan come up clean and the next turn re-injects.
174
- if (branchCarries(branch, PLAN_MARKER)) return;
175
- return {
176
- message: {
177
- customType: PLAN_CONTEXT_TYPE,
178
- content: planContextContent(ctx.cwd),
179
- display: false,
180
- },
181
- };
182
- });
183
-
184
- // Strip the stale plan-authoring marker from context when the gate is off (so it never lingers).
185
- pi.on("context", async (event) => {
186
- if (gating.isActive()) return;
187
- return {
188
- messages: event.messages.filter((m) => {
189
- const msg = m as { customType?: string; role?: string; content?: unknown };
190
- if (msg.customType === PLAN_CONTEXT_TYPE) return false;
191
- if (msg.role !== "user") return true;
192
- const content = msg.content;
193
- if (typeof content === "string") return !content.includes(PLAN_MARKER);
194
- if (Array.isArray(content)) {
195
- return !content.some(
196
- (c) =>
197
- (c as { type?: string; text?: string }).type === "text" &&
198
- ((c as { text?: string }).text ?? "").includes(PLAN_MARKER),
199
- );
200
- }
201
- return true;
202
- }),
203
- };
204
- });
205
- }