pi-plans 0.6.0 → 0.8.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 (116) hide show
  1. package/AGENTS.md +58 -0
  2. package/CONTRIBUTING.md +8 -15
  3. package/README.md +39 -37
  4. package/agents/execution-reviewer.md +40 -0
  5. package/agents/reviewer.md +12 -3
  6. package/index.ts +55 -58
  7. package/package.json +2 -1
  8. package/references/pi-planning-workflow.md +50 -60
  9. package/references/plan-artifact-template.md +81 -60
  10. package/references/state-and-config.md +60 -44
  11. package/scripts/bench/pi-adapter/pi_plans_bench.py +33 -22
  12. package/scripts/bench/pi-adapter/rpc_driver.mjs +4 -4
  13. package/scripts/run-tests.ts +12 -1
  14. package/scripts/validate.ts +39 -11
  15. package/skills/debug-and-plan/SKILL.md +3 -3
  16. package/skills/plan-big/SKILL.md +3 -3
  17. package/skills/plan-normal/SKILL.md +3 -3
  18. package/skills/plan-small/SKILL.md +4 -4
  19. package/skills/plan-with-refs/SKILL.md +6 -6
  20. package/skills/planning/SKILL.md +1 -1
  21. package/src/ask-form.ts +4 -4
  22. package/src/auditor.ts +227 -0
  23. package/src/auto-approve.ts +1 -1
  24. package/src/autocomplete.ts +19 -17
  25. package/src/code-graph/commands.ts +8 -3
  26. package/src/code-graph/community.ts +1 -1
  27. package/src/code-graph/paths.ts +1 -1
  28. package/src/code-graph/watch.ts +2 -2
  29. package/src/compaction.ts +3 -3
  30. package/src/config-command.ts +146 -73
  31. package/src/dashboard.ts +303 -0
  32. package/src/exec.ts +1185 -924
  33. package/src/global-state.ts +304 -0
  34. package/src/guard.ts +18 -19
  35. package/src/messaging.ts +44 -0
  36. package/src/plan.ts +421 -112
  37. package/src/query-hook.ts +4 -4
  38. package/src/refine-prompts.ts +12 -70
  39. package/src/refine-ui-helpers.ts +24 -5
  40. package/src/refine-ui-state.ts +1 -1
  41. package/src/refine-ui.ts +19 -3
  42. package/src/resume-command.ts +45 -129
  43. package/src/resume.ts +5 -1
  44. package/src/role-panels.ts +542 -0
  45. package/src/run-context.ts +3 -10
  46. package/src/staleness.ts +53 -0
  47. package/src/state.ts +273 -72
  48. package/src/subagent.ts +19 -29
  49. package/src/task-tool.ts +100 -0
  50. package/src/tasks.ts +223 -0
  51. package/src/thinking-levels.ts +67 -0
  52. package/src/ui-language.ts +7 -54
  53. package/src/workflow-state.ts +76 -58
  54. package/tests/analyze-refs.test.ts +35 -18
  55. package/tests/ask-choice-schema.test.ts +0 -12
  56. package/tests/ask-choice.test.ts +2 -49
  57. package/tests/ask-form-tool.test.ts +4 -5
  58. package/tests/ask-form.test.ts +2 -2
  59. package/tests/auditor.test.ts +210 -0
  60. package/tests/auto-approve.test.ts +7 -10
  61. package/tests/autocomplete.test.ts +8 -11
  62. package/tests/code-graph-apply-action.test.ts +2 -2
  63. package/tests/code-graph-commands.test.ts +2 -2
  64. package/tests/code-graph-index.test.ts +2 -2
  65. package/tests/code-graph-loop.e2e.test.ts +1 -1
  66. package/tests/code-graph-mutations.test.ts +1 -1
  67. package/tests/code-graph-rollback.test.ts +1 -1
  68. package/tests/code-graph-v05.test.ts +2 -2
  69. package/tests/compaction.test.ts +1 -1
  70. package/tests/config-command.test.ts +103 -100
  71. package/tests/dashboard.test.ts +402 -0
  72. package/tests/exec-lifecycle.test.ts +181 -115
  73. package/tests/exec-panel-lifecycle.test.ts +106 -251
  74. package/tests/exec-review-loop.test.ts +331 -0
  75. package/tests/exec.test.ts +771 -1706
  76. package/tests/execute-plan.test.ts +44 -19
  77. package/tests/extension-load.test.ts +48 -0
  78. package/tests/global-state.test.ts +371 -0
  79. package/tests/graph-aware-file-tools.test.ts +5 -5
  80. package/tests/guard.test.ts +1 -1
  81. package/tests/multi-run.test.ts +3 -103
  82. package/tests/plan.test.ts +139 -62
  83. package/tests/plans.test.ts +7 -79
  84. package/tests/refine-prompts.test.ts +20 -71
  85. package/tests/refine-resume.test.ts +27 -22
  86. package/tests/refine-ui.test.ts +6 -15
  87. package/tests/resume-lifecycle.test.ts +41 -22
  88. package/tests/resume.test.ts +39 -81
  89. package/tests/role-panels.test.ts +391 -0
  90. package/tests/run-context.test.ts +1 -1
  91. package/tests/run-ownership.test.ts +1 -1
  92. package/tests/stale-ctx.test.ts +218 -0
  93. package/tests/staleness.test.ts +76 -0
  94. package/tests/state.test.ts +155 -32
  95. package/tests/subagent-thinking.test.ts +65 -0
  96. package/tests/subagent-usage.test.ts +1 -1
  97. package/tests/task-tool.test.ts +61 -0
  98. package/tests/tasks.test.ts +142 -0
  99. package/tests/thinking-levels.test.ts +77 -0
  100. package/tests/ui-language.test.ts +2 -17
  101. package/tests/workflow-state.test.ts +73 -90
  102. package/tools/analyze-refs.ts +67 -32
  103. package/tools/ask-choice.ts +7 -53
  104. package/tools/code-graph.ts +2 -2
  105. package/tools/execute-plan.ts +55 -99
  106. package/tools/graph-aware-file-tools.ts +4 -10
  107. package/tools/plans.ts +41 -67
  108. package/tools/refine.ts +101 -164
  109. package/agents/criticizer.md +0 -18
  110. package/agents/executor.md +0 -26
  111. package/scripts/bench/pi-adapter/__pycache__/pi_plans_bench.cpython-312.pyc +0 -0
  112. package/src/panel.ts +0 -473
  113. package/src/termination-prompt.ts +0 -73
  114. package/tests/goal-wait.test.ts +0 -269
  115. package/tests/panel-i-zero.test.ts +0 -420
  116. package/tests/panel.test.ts +0 -355
package/tools/plans.ts CHANGED
@@ -8,9 +8,6 @@ import { lintPlanIntoNotices } from "../src/state.ts";
8
8
  import { getExecution, markPrePlanCompactPending, refreshUiLanguage } from "../src/exec.ts";
9
9
  import { loadVccSettings, scaffoldVccSettings } from "../src/compaction.ts";
10
10
  import {
11
- applyCompleted,
12
- applyImplementationReviewConfigured,
13
- applyImplementationRoundFinished,
14
11
  applyPlanWritten,
15
12
  applyReviewConsolidated,
16
13
  createCheckpoint,
@@ -43,11 +40,12 @@ import {
43
40
  setRefsRoot,
44
41
  setRunStatus,
45
42
  setRole,
46
- showConfig,
43
+ showStateView,
47
44
  startRun,
48
45
  StateError,
49
46
  VALID_RUN_STATUSES,
50
47
  } from "../src/state.ts";
48
+ import { messaging } from "../src/messaging.ts";
51
49
 
52
50
  const PlansParams = Type.Object({
53
51
  action: StringEnum(
@@ -77,25 +75,31 @@ const PlansParams = Type.Object({
77
75
  requestText: Type.Optional(Type.String({ description: "start-run: original user request text" })),
78
76
  tag: Type.Optional(Type.String({ description: "set-language: BCP47 tag, e.g. zh-Hans, en" })),
79
77
  languageSource: Type.Optional(StringEnum(["user", "auto"] as const)),
80
- artifactRoot: Type.Optional(Type.String({ description: "set-artifact-root: planning docs root, e.g. ./docs/pi-plans" })),
78
+ artifactRoot: Type.Optional(Type.String({ description: "set-artifact-root: planning docs root, e.g. ./.git/pi-plans/plans" })),
81
79
  artifactRootSource: Type.Optional(StringEnum(["user", "auto"] as const)),
82
80
  refsRoot: Type.Optional(Type.String({ description: "set-refs-root: reference downloads root, e.g. .git/pi-plans/refs" })),
83
81
  refsRootSource: Type.Optional(StringEnum(["user", "auto"] as const)),
84
82
  enabled: Type.Optional(Type.Boolean({ description: "set-graph-enabled: enable/disable the code graph" })),
85
83
  message: Type.Optional(Type.String({ description: "final-commit: commit message body" })),
86
- role: Type.Optional(StringEnum(["reviewer", "criticizer"] as const)),
84
+ role: Type.Optional(StringEnum(["reviewer"] as const)),
87
85
  mode: Type.Optional(StringEnum(["delegated-subagent", "current-session"] as const)),
88
86
  modelSelector: Type.Optional(
89
- Type.String({ description: "set-role: exact provider/model selector, or 'inherit' to reset to inherited" }),
87
+ Type.String({ description: "set-role: exact provider/model selector; 'inherit' resets BOTH the selector and the confirmation" }),
88
+ ),
89
+ thinkingLevel: Type.Optional(
90
+ StringEnum(["default", "off", "minimal", "low", "medium", "high", "xhigh", "max"] as const, {
91
+ description:
92
+ "set-role: reviewer subagent thinking level in the GLOBAL config; 'default' (null) omits --thinking so the child pi resolves its own default chain; changing modelSelector without this resets the level",
93
+ }),
90
94
  ),
91
95
  confirmed: Type.Optional(
92
- Type.Boolean({ description: "set-role: stamp confirmed_at=now (used by the first-use confirmation flow)" }),
96
+ Type.Boolean({ description: "set-role: stamp confirmed_at=now; requires an exact selector for delegated-subagent" }),
93
97
  ),
94
98
  resetConfirmation: Type.Optional(Type.Boolean({ description: "set-role: clear confirmed_at to re-ask" })),
95
99
  runId: Type.Optional(Type.String()),
96
100
  status: Type.Optional(
97
101
  StringEnum(
98
- ["planning", "accepted", "executing", "stopped", "abandoned", "done"] as const,
102
+ ["planning", "accepted", "executing", "verifying", "stopped", "abandoned", "done"] as const,
99
103
  { description: "set-status: run lifecycle status" },
100
104
  ),
101
105
  ),
@@ -121,7 +125,7 @@ const PlansParams = Type.Object({
121
125
  ),
122
126
  subagent: Type.Optional(
123
127
  Type.Object({
124
- role: StringEnum(["reviewer", "criticizer", "ref-analyst"] as const),
128
+ role: StringEnum(["reviewer", "ref-analyst"] as const),
125
129
  name: Type.String(),
126
130
  model: Type.Optional(Type.String()),
127
131
  sessionDir: Type.Optional(Type.String()),
@@ -130,41 +134,16 @@ const PlansParams = Type.Object({
130
134
  checkpoint: Type.Optional(
131
135
  Type.Object({
132
136
  /** Whitelisted semantic transition (I-003). State-machine validated; approval cannot be forged here. */
133
- transition: StringEnum(
134
- [
135
- "plan-written",
136
- "review-consolidated",
137
- "implementation-review-configured",
138
- "implementation-round-finished",
139
- "completed",
140
- ] as const,
141
- ),
137
+ transition: StringEnum(["plan-written", "review-consolidated"] as const),
142
138
  /** plan-written: absolute or workdir-relative PLAN_vN.md path. */
143
139
  planPath: Type.Optional(Type.String()),
144
140
  /** review-consolidated: round id + optional disposition artifact (run-dir relative). */
145
141
  roundId: Type.Optional(Type.String()),
146
142
  dispositionArtifact: Type.Optional(Type.String()),
147
- /** implementation-review-configured: the serialized termination condition chosen by the user. */
148
- terminationCondition: Type.Optional(Type.String()),
149
- /** implementation-review-configured: concurrent reviewers per round (1-3);
150
- * omit to keep the skill-level default (plan-big / plan-with-refs → 3, others → 1). */
151
- reviewerCount: Type.Optional(Type.Integer({ minimum: 1, maximum: 3 })),
152
- /** completed: non-empty evidence that the termination condition is satisfied. */
153
- evidence: Type.Optional(Type.String()),
154
143
  }),
155
144
  ),
156
145
  });
157
146
 
158
- // Module-level reference so the start-run action can append a session entry
159
- // (pi-plans-run-start) at the moment the planning run begins. The ExtensionAPI
160
- // itself is not in scope for `startRun`, mirroring `setCurrentApi` in
161
- // tools/execute-plan.ts.
162
- let runStartAppender: ((runId: string, artifactDir: string) => void) | null = null;
163
-
164
- export function setRunStartAppender(appender: ((runId: string, artifactDir: string) => void) | null): void {
165
- runStartAppender = appender;
166
- }
167
-
168
147
  /** plans action final-commit: gate on code-graph drift (zero pending +
169
148
  * invariants (a)/(b) clean), then `git add -A` and commit the plan delivery.
170
149
  * A clean tree is a safe no-op. Returns a machine-readable result. */
@@ -238,13 +217,10 @@ export function recordCheckpointTransition(
238
217
  workdir: string,
239
218
  runIdArg: string | undefined,
240
219
  checkpoint: {
241
- transition: "plan-written" | "review-consolidated" | "implementation-review-configured" | "implementation-round-finished" | "completed";
220
+ transition: "plan-written" | "review-consolidated";
242
221
  planPath?: string;
243
222
  roundId?: string;
244
223
  dispositionArtifact?: string;
245
- terminationCondition?: string;
246
- reviewerCount?: number;
247
- evidence?: string;
248
224
  },
249
225
  ): WorkflowCheckpoint {
250
226
  const runId =
@@ -270,33 +246,15 @@ export function recordCheckpointTransition(
270
246
  applyReviewConsolidated(cp, checkpoint.roundId!, checkpoint.dispositionArtifact),
271
247
  );
272
248
  }
273
- case "implementation-review-configured": {
274
- if (!checkpoint.terminationCondition) {
275
- throw new StateError("implementation-review-configured requires terminationCondition");
276
- }
277
- return mutateCheckpoint(workdir, runId, (cp) =>
278
- applyImplementationReviewConfigured(cp, checkpoint.terminationCondition!, checkpoint.reviewerCount),
279
- );
280
- }
281
- case "implementation-round-finished": {
282
- return mutateCheckpoint(workdir, runId, (cp) => applyImplementationRoundFinished(cp));
283
- }
284
- case "completed": {
285
- if (!checkpoint.evidence) throw new StateError("completed requires evidence");
286
- return mutateCheckpoint(workdir, runId, (cp) => applyCompleted(cp, checkpoint.evidence!));
287
- }
288
249
  }
289
250
  }
290
251
 
291
- export function registerPlansTool(pi: ExtensionAPI): void {
292
- setRunStartAppender((runId, artifactDir) => {
293
- pi.appendEntry("pi-plans-run-start", { runId, artifactDir });
294
- });
295
- pi.registerTool({
252
+ export function registerPlansTool(ext: ExtensionAPI): void {
253
+ ext.registerTool({
296
254
  name: "plans",
297
255
  label: "Plans",
298
256
  description:
299
- "Manage pi-plans planning state in the target workspace: init/show config, set language and planning docs root plus reviewer/criticizer roles and the code-graph enabled flag, start planning runs, record decisions/refs/subagents, and update run status. Multiple concurrent runs per workdir are supported (registry-derived from runs/; sessions bind to their run). State lives in .git/pi_plans/ inside the resolved git common dir. Actions: init, show, set-language, set-artifact-root, set-refs-root, set-graph-enabled, set-role, start-run, set-status, final-commit, record-decision, record-ref, record-subagent.",
257
+ "Manage pi-plans planning state in the target workspace: init/show config, set language and planning docs root plus the reviewer role and the code-graph enabled flag, start planning runs, record decisions/refs/subagents, and update run status. Multiple concurrent runs per workdir are supported (registry-derived from runs/; sessions bind to their run). State lives in .git/pi-plans/ inside the resolved git common dir. Actions: init, show, set-language, set-artifact-root, set-refs-root, set-graph-enabled, set-role, start-run, set-status, final-commit, record-decision, record-ref, record-subagent.",
300
258
  promptSnippet: "Manage pi-plans planning state, runs, and ledgers",
301
259
  parameters: PlansParams,
302
260
 
@@ -317,10 +275,15 @@ export function registerPlansTool(pi: ExtensionAPI): void {
317
275
  break;
318
276
  }
319
277
  case "show": {
320
- const config = showConfig(workdir);
321
- const stateRoot = resolveStateRootOrNull(workdir);
322
- result = { config, stateRoot };
323
- if (config.graph_enabled === null) {
278
+ const view = showStateView(workdir);
279
+ result = {
280
+ config: view.config,
281
+ stateRoot: view.stateRoot,
282
+ reviewer: view.reviewer,
283
+ globalConfigPath: view.globalConfigPath,
284
+ notices: view.notices,
285
+ };
286
+ if (view.config.graph_enabled === null) {
324
287
  result = {
325
288
  ...(result as Record<string, unknown>),
326
289
  hint: "graph_enabled is null (never asked). Ask the user once via ask_choice, then persist with plans (action: set-graph-enabled, enabled: true|false).",
@@ -369,10 +332,17 @@ export function registerPlansTool(pi: ExtensionAPI): void {
369
332
  role: params.role,
370
333
  mode: params.mode,
371
334
  modelSelector: params.modelSelector,
335
+ thinkingLevel: params.thinkingLevel,
372
336
  confirmed: params.confirmed,
373
337
  resetConfirmation: params.resetConfirmation,
374
338
  });
375
- result = { config: updated.config, stateRoot: updated.stateRoot, notices: updated.notices };
339
+ result = {
340
+ global: updated.global,
341
+ globalRoot: updated.globalRoot,
342
+ notices: updated.notices,
343
+ config: updated.config,
344
+ stateRoot: updated.stateRoot,
345
+ };
376
346
  break;
377
347
  }
378
348
  case "start-run": {
@@ -383,8 +353,11 @@ export function registerPlansTool(pi: ExtensionAPI): void {
383
353
  topic: params.topic,
384
354
  skill: params.skill,
385
355
  requestText: params.requestText,
356
+ // Append the run-start session entry with this call's ctx —
357
+ // never a registration-time capture (stale after session
358
+ // replacement).
386
359
  onStart: (run) => {
387
- runStartAppender?.(run.run_id, run.artifact_dir);
360
+ messaging().appendEntry("pi-plans-run-start", { runId: run.run_id, artifactDir: run.artifact_dir });
388
361
  },
389
362
  });
390
363
  // I-002: attribute this session's work to the run it started.
@@ -454,3 +427,4 @@ export function registerPlansTool(pi: ExtensionAPI): void {
454
427
  },
455
428
  });
456
429
  }
430
+