pi-orchestrator-config 4.2.1 → 4.3.2

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 (92) hide show
  1. package/README.md +52 -61
  2. package/agents/git-expert.md +5 -1
  3. package/agents/github-expert.md +4 -1
  4. package/extensions/acpx-provider/runtime-models.ts +18 -6
  5. package/extensions/cli-provider/agents/claude.ts +3 -2
  6. package/extensions/cli-provider/agents/cursor.ts +3 -5
  7. package/extensions/cli-provider/agents/gemini.ts +3 -2
  8. package/extensions/cli-provider/discover.ts +7 -7
  9. package/extensions/cli-provider/index.ts +5 -0
  10. package/extensions/cli-provider/runtime-models.ts +18 -6
  11. package/extensions/cli-provider/session-reaper.ts +5 -7
  12. package/extensions/cli-provider/sessions.ts +4 -0
  13. package/extensions/cli-provider/shared/discover-cache.ts +17 -176
  14. package/extensions/coms/coms-p2p.ts +1719 -423
  15. package/extensions/coms/coms-shared.ts +261 -39
  16. package/extensions/coms/coms-wrapper.ts +100 -62
  17. package/extensions/coms/index.ts +8 -4
  18. package/extensions/coms/mixed-turn.ts +26 -0
  19. package/extensions/coms/probe-socket.ts +42 -0
  20. package/extensions/coms/themeMap.ts +0 -1
  21. package/extensions/image-gen/image-gen.ts +19 -1
  22. package/extensions/orchestrator/async-agents.ts +509 -85
  23. package/extensions/orchestrator/cron.ts +14 -8
  24. package/extensions/orchestrator/dreaming.ts +31 -24
  25. package/extensions/orchestrator/enforcement-helpers.ts +459 -17
  26. package/extensions/orchestrator/enforcement-rules.ts +5 -4
  27. package/extensions/orchestrator/enforcement.ts +79 -25
  28. package/extensions/orchestrator/extended-autocomplete.ts +7 -0
  29. package/extensions/orchestrator/git-helpers.ts +2 -2
  30. package/extensions/orchestrator/index.ts +23 -10
  31. package/extensions/orchestrator/markdown-transformer.ts +313 -0
  32. package/extensions/orchestrator/memory-embeddings.ts +36 -34
  33. package/extensions/orchestrator/memory-provenance.ts +29 -25
  34. package/extensions/orchestrator/memory-scoring.ts +23 -18
  35. package/extensions/orchestrator/memory-tools.ts +10 -3
  36. package/extensions/orchestrator/overlay-dashboard.ts +17 -5
  37. package/extensions/orchestrator/pi-config-review-state.ts +44 -33
  38. package/extensions/orchestrator/project-settings.ts +220 -21
  39. package/extensions/orchestrator/review-porcelain.ts +4 -0
  40. package/extensions/orchestrator/review-ui.ts +11 -5
  41. package/extensions/orchestrator/rule-placeholders.ts +384 -1
  42. package/extensions/orchestrator/rules.ts +80 -132
  43. package/extensions/orchestrator/settings-tui-helpers.ts +380 -0
  44. package/extensions/orchestrator/settings-tui-submenus.ts +647 -0
  45. package/extensions/orchestrator/settings-tui.ts +636 -0
  46. package/extensions/orchestrator/state-jsonl.ts +431 -0
  47. package/extensions/orchestrator/subagent-tool.ts +105 -50
  48. package/extensions/orchestrator/sync-limit.ts +23 -0
  49. package/extensions/orchestrator/task-lifecycle.ts +77 -67
  50. package/extensions/orchestrator/utils.ts +8 -5
  51. package/extensions/pidash/pidash.ts +193 -156
  52. package/extensions/pidiff/pidiff.ts +64 -38
  53. package/extensions/pidiff/spawn-lock.ts +62 -0
  54. package/extensions/pitasks/index.ts +430 -0
  55. package/extensions/pitasks/reminders.ts +37 -0
  56. package/extensions/pitasks/task-store.ts +467 -0
  57. package/extensions/pitasks/task-tools.ts +375 -0
  58. package/extensions/pitasks/task-widget.ts +181 -0
  59. package/extensions/pitasks/types.ts +38 -0
  60. package/extensions/providers/acpx-driver.ts +12 -2
  61. package/extensions/providers/built-in-drivers.ts +6 -6
  62. package/extensions/providers/claude-driver.ts +1 -1
  63. package/extensions/providers/cursor-cli-driver.ts +1 -1
  64. package/extensions/providers/gemini-driver.ts +1 -1
  65. package/extensions/providers/index.ts +144 -26
  66. package/extensions/providers/initialized-guard.ts +27 -0
  67. package/extensions/providers/restore-default-model.ts +596 -0
  68. package/extensions/providers/session-shutdown.ts +39 -0
  69. package/extensions/shared/coms-active.ts +23 -0
  70. package/extensions/shared/create-runtime-provider.ts +2 -0
  71. package/extensions/shared/daemon-manager.ts +0 -8
  72. package/extensions/shared/file-logger.ts +132 -25
  73. package/extensions/shared/logger.ts +50 -0
  74. package/extensions/shared/models-dev.ts +421 -0
  75. package/extensions/shared/oneshot.ts +116 -0
  76. package/extensions/shared/resolve-binary.ts +191 -0
  77. package/extensions/shared/types.ts +3 -0
  78. package/package.json +7 -2
  79. package/prompts/coderabbit-rate-limit.md +2 -0
  80. package/rules/00-orchestrator-core.md +3 -0
  81. package/rules/10-agent-routing.md +1 -1
  82. package/rules/20-code-review-loop.md +38 -16
  83. package/rules/30-prompt-templates.md +4 -0
  84. package/rules/35-memory.md +3 -3
  85. package/rules/40-critical-rules.md +3 -0
  86. package/rules/55-coms-protocol.md +84 -18
  87. package/rules/60-task-tracking.md +2 -0
  88. package/settings-keys.json +481 -20
  89. package/templates/coms-feature-manager-prompt.md +4 -6
  90. package/extensions/coms/coms-net-server.ts +0 -1642
  91. package/extensions/coms/coms-net-wrapper.ts +0 -521
  92. package/extensions/coms/coms-net.ts +0 -1589
@@ -11,6 +11,9 @@
11
11
  * Prompt tasks run as async agents with triggerTurn: true.
12
12
  */
13
13
 
14
+ import { createLogger } from "../shared/logger.js";
15
+
16
+ const log = createLogger("cron");
14
17
  import * as fs from "node:fs";
15
18
  import * as os from "node:os";
16
19
  import * as path from "node:path";
@@ -84,7 +87,7 @@ function saveCrons(tasks: CronTask[]): void {
84
87
  try {
85
88
  CRON_IGNORE_WATCH_UNTIL = Date.now() + 400;
86
89
  fs.writeFileSync(CRON_FILE, JSON.stringify(tasks), { mode: 0o600 });
87
- } catch (e: any) { console.debug("[cron] save crons failed:", e?.message || e); }
90
+ } catch (e: any) { log.debug("save crons failed:", e?.message || e); }
88
91
  }
89
92
 
90
93
  function loadCrons(): CronTask[] {
@@ -137,7 +140,7 @@ function cleanupOrphanedCronFiles(): void {
137
140
  // If kill(pid, 0) succeeds but /proc is unreadable — skip (can't verify)
138
141
  }
139
142
  }
140
- } catch (e: any) { console.debug("[cron] cleanup orphaned cron files failed:", e?.message || e); }
143
+ } catch (e: any) { log.debug("cleanup orphaned cron files failed:", e?.message || e); }
141
144
  }
142
145
 
143
146
  // ── Helpers ──────────────────────────────────────────────────────────
@@ -217,6 +220,7 @@ function registerCronTool(pi: ExtensionAPI, state: CronInternals): void {
217
220
  state.tasks.set(task.id, task);
218
221
  state.startTask(task);
219
222
  saveCrons([...state.tasks.values()]);
223
+ log.info("cron_add", task.description);
220
224
 
221
225
  state.updateCronStatus();
222
226
  return {
@@ -266,7 +270,7 @@ function registerCronTool(pi: ExtensionAPI, state: CronInternals): void {
266
270
  });
267
271
  sections.push(`**${label}:**\n${lines.join("\n")}`);
268
272
  }
269
- } catch (e: any) { console.debug("[cron] list-all scan failed:", e?.message || e); }
273
+ } catch (e: any) { log.debug("list-all scan failed:", e?.message || e); }
270
274
  if (sections.length === 0) {
271
275
  return { content: [{ type: "text", text: "No scheduled tasks in any session." }] };
272
276
  }
@@ -284,6 +288,7 @@ function registerCronTool(pi: ExtensionAPI, state: CronInternals): void {
284
288
  state.stopTask(id);
285
289
  state.tasks.delete(id);
286
290
  saveCrons([...state.tasks.values()]);
291
+ log.info("cron_remove", id);
287
292
  state.updateCronStatus();
288
293
  return {
289
294
  content: [{ type: "text", text: `Cron #${id} removed: ${task.description}` }],
@@ -353,7 +358,7 @@ function listAllCronViews(state: CronInternals) {
353
358
  }
354
359
  }
355
360
  } catch (e: any) {
356
- console.debug("[cron] list-all scan failed:", e?.message || e);
361
+ log.debug("list-all scan failed:", e?.message || e);
357
362
  }
358
363
  return views;
359
364
  }
@@ -383,7 +388,7 @@ function removeCronByOverlayId(state: CronInternals, overlayId: string): boolean
383
388
  fs.writeFileSync(view.cronFile, JSON.stringify(next), { mode: 0o600 });
384
389
  return true;
385
390
  } catch (e: any) {
386
- console.debug("[cron] remote remove failed:", e?.message || e);
391
+ log.debug("remote remove failed:", e?.message || e);
387
392
  return false;
388
393
  }
389
394
  }
@@ -523,6 +528,7 @@ export function registerCron(
523
528
  }
524
529
 
525
530
  function executeCronTask(task: CronTask) {
531
+ log.info("cron_execute", task.id);
526
532
  task.lastRun = Date.now();
527
533
  saveCrons([...tasks.values()]);
528
534
 
@@ -541,7 +547,7 @@ export function registerCron(
541
547
  mustAsync: true,
542
548
  });
543
549
  if (dispatch.action === "skip") {
544
- console.debug(`[cron] ${dispatch.note} (task #${task.id})`);
550
+ log.error("cron_error", task.id, dispatch.note);
545
551
  try {
546
552
  state.lastCtx?.ui?.notify?.(
547
553
  `Cron #${task.id} skipped: set internal_operations_provider/internal_operations_model for acpx`,
@@ -677,13 +683,13 @@ export function registerCron(
677
683
  try {
678
684
  syncTasksFromDisk();
679
685
  } catch (e: any) {
680
- console.debug("[cron] sync from disk failed:", e?.message || e);
686
+ log.debug("sync from disk failed:", e?.message || e);
681
687
  }
682
688
  }, 150);
683
689
  });
684
690
  cronFileWatcher.unref?.();
685
691
  } catch (e: any) {
686
- console.debug("[cron] watch setup failed:", e?.message || e);
692
+ log.debug("watch setup failed:", e?.message || e);
687
693
  }
688
694
  });
689
695
 
@@ -10,6 +10,9 @@
10
10
  * Users toggle with /dream-auto on|off.
11
11
  */
12
12
 
13
+ import { createLogger } from "../shared/logger.js";
14
+
15
+ const log = createLogger("dreaming");
13
16
  import { spawn } from "node:child_process";
14
17
  import * as fs from "node:fs";
15
18
  import * as os from "node:os";
@@ -23,13 +26,8 @@ import { setSlot } from "./status-bar.js";
23
26
  import { rebuildAndOrganize } from "./situation-report.js";
24
27
  import { runPromotionPass } from "./memory-promotion.js";
25
28
  import { mergeProvenancePending } from "./memory-provenance.js";
26
- import { getProjectTmpDir } from "./utils.js";
27
- import { dreamingLog } from "../shared/file-logger.js";
28
-
29
- // Default: 3 hours. Override with PI_DREAM_INTERVAL_HOURS env var (0.5–24).
30
- const _rawHours = parseFloat(process.env.PI_DREAM_INTERVAL_HOURS || "3");
31
- const DREAM_INTERVAL_HOURS = Number.isFinite(_rawHours) && _rawHours >= 0.5 && _rawHours <= 24 ? _rawHours : 3;
32
- const DREAM_INTERVAL_MS = DREAM_INTERVAL_HOURS * 60 * 60 * 1000;
29
+ import { getProjectTmpDir, shouldSkipOneshotShutdownDream } from "./utils.js";
30
+ import { fileLog } from "../shared/file-logger.js";
33
31
 
34
32
  // Scoring rebuild runs every 30 minutes (cheap, no LLM — just rescores and reorganizes)
35
33
  const REBUILD_INTERVAL_MS = 30 * 60 * 1000;
@@ -84,7 +82,7 @@ export function registerDreaming(
84
82
  mustAsync: true,
85
83
  });
86
84
  if (dreamDispatch.action === "skip") {
87
- dreamingLog("warn", dreamDispatch.note || "dream skipped (no async LLM path)");
85
+ fileLog("dreaming", "warn", "dreaming", dreamDispatch.note || "dream skipped (no async LLM path)");
88
86
  try {
89
87
  lastCtx?.ui?.notify?.(
90
88
  "Dream skipped: set internal_operations_provider and internal_operations_model for acpx sessions",
@@ -99,6 +97,7 @@ export function registerDreaming(
99
97
  }
100
98
 
101
99
  dreamInFlight = true;
100
+ log.info("dream start", cwd);
102
101
  updateDreamStatus();
103
102
  currentDreamId = ""; // Reset until we get the ID from spawnAsyncAgent
104
103
  const { agents } = discoverAgents(cwd, "user");
@@ -168,9 +167,9 @@ export function registerDreaming(
168
167
  ` - discard: stale or superseded noise\n` +
169
168
  ` - Do not reopen entries already marked applied or rejected in promotions.md\n` +
170
169
  `11. Provenance sidecar (optional): for newly extracted entries, write\n` +
171
- ` ${topicsDir}/../provenance-pending.json as JSON:\n` +
170
+ ` ${topicsDir}/../provenance-pending.jsonl as a single line of JSON (preferred):\n` +
172
171
  ` {"entries":[{"category":"lesson","text":"<exact topic text>","sourceSession":"<session basename>","derivedFrom":"<optional>","informs":["optional"]}]}\n` +
173
- ` Do NOT edit memory-scores.json yourself — onComplete merges the sidecar.`,
172
+ ` Do NOT edit memory-scores.jsonl yourself — onComplete merges the sidecar.`,
174
173
  cwd,
175
174
  agents,
176
175
  {
@@ -180,23 +179,24 @@ export function registerDreaming(
180
179
  parentProvider: dreamProvider,
181
180
  onComplete: () => {
182
181
  dreamInFlight = false;
182
+ log.info("dream complete", cwd);
183
183
  updateDreamStatus();
184
184
  // File log only — console.* leaks into the chat text box.
185
185
  try {
186
186
  rebuildAndOrganize(cwd);
187
187
  } catch (err) {
188
- dreamingLog("error", "rebuildAndOrganize failed", err);
188
+ fileLog("dreaming", "error", "dreaming", "rebuildAndOrganize failed", err);
189
189
  }
190
190
  try {
191
191
  const n = mergeProvenancePending(cwd);
192
- if (n > 0) dreamingLog("info", `merged provenance for ${n} entries`);
192
+ if (n > 0) fileLog("dreaming", "info", "dreaming", `merged provenance for ${n} entries`);
193
193
  } catch (err) {
194
- dreamingLog("error", "provenance merge failed", err);
194
+ fileLog("dreaming", "error", "dreaming", "provenance merge failed", err);
195
195
  }
196
196
  try {
197
197
  runPromotionPass(cwd);
198
198
  } catch (err) {
199
- dreamingLog("error", "promotion pass failed", err);
199
+ fileLog("dreaming", "error", "dreaming", "promotion pass failed", err);
200
200
  }
201
201
  },
202
202
  },
@@ -216,8 +216,10 @@ export function registerDreaming(
216
216
  if (dreamInFlight && currentDreamId === dreamId) {
217
217
  dreamInFlight = false;
218
218
  updateDreamStatus();
219
- dreamingLog(
219
+ fileLog(
220
+ "dreaming",
220
221
  "warn",
222
+ "dreaming",
221
223
  "fallback: reset dreamInFlight after 30 min (onComplete never fired)",
222
224
  );
223
225
  }
@@ -256,7 +258,7 @@ export function registerDreaming(
256
258
  try {
257
259
  rebuildAndOrganize(lastCwd);
258
260
  } catch (err) {
259
- dreamingLog("error", "rebuildAndOrganize failed", err);
261
+ fileLog("dreaming", "error", "dreaming", "rebuildAndOrganize failed", err);
260
262
  }
261
263
  }
262
264
  }, REBUILD_INTERVAL_MS);
@@ -327,29 +329,34 @@ export function registerDreaming(
327
329
  lastCwd = ctx.cwd;
328
330
  lastCtx = ctx;
329
331
  dreamInFlight = false; // Reset — previous session's dream state doesn't carry over
330
- // Skip dreaming in one-shot modes (print/json)
331
- if (ctx.mode === "print" || ctx.mode === "json") return;
332
+ // Skip auto-dream timer in print/json; shutdown dream is skipped in
333
+ // session_shutdown via shouldSkipOneshotShutdownDream.
334
+ if (ctx.mode === "print" || ctx.mode === "json") {
335
+ log.debug("skip dream timer: print/json mode");
336
+ return;
337
+ }
332
338
  updateDreamStatus();
333
339
  if (enabled) startTimer(ctx.cwd);
334
340
  });
335
341
 
336
- // Fire-and-forget dream on session shutdown.
337
- // Uses detached spawn (not async agent) because the session is ending —
338
- // async agents need the pi process alive to deliver results.
342
+ // Shutdown dream: runDreamAsync → spawnAsyncAgent (not detached/unref'd).
343
+ // Skip oneshot print/json or the child keeps the parent event loop alive.
339
344
  pi.on("session_shutdown", (event) => {
340
345
  stopTimer();
346
+ if (shouldSkipOneshotShutdownDream(lastCtx?.mode)) {
347
+ log.info("skip shutdown dream: oneshot print/json");
348
+ return;
349
+ }
341
350
  if (!enabled || !lastCwd || dreamInFlight) return;
342
351
 
343
352
  // Only dream on quit — skip for fork/new/resume/reload since the
344
353
  // session continues or transitions, not ending meaningfully.
345
354
  if ((event as any).reason && (event as any).reason !== "quit") return;
346
355
 
347
- // On shutdown, run a lightweight dream via detached async runner
348
- // (can't use spawnAsyncAgent since the session is ending)
349
356
  try {
350
357
  runDreamAsync(lastCwd);
351
358
  } catch (err) {
352
- dreamingLog("error", "shutdown dream failed", err);
359
+ fileLog("dreaming", "error", "dreaming", "shutdown dream failed", err);
353
360
  }
354
361
  });
355
362
  }