pi-harness-runtime 1.1.275 → 1.1.277

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 (108) hide show
  1. package/index.ts +204 -90
  2. package/package.json +1 -1
  3. package/packages/a2a-adapter/package.json +1 -1
  4. package/packages/agent-policy/package.json +1 -1
  5. package/packages/architecture-generator/package.json +1 -1
  6. package/packages/auth/package.json +1 -1
  7. package/packages/autonomous-refactor/package.json +1 -1
  8. package/packages/autonomous-runtime/package.json +1 -1
  9. package/packages/cache-strategy/package.json +1 -1
  10. package/packages/capability-registry/package.json +1 -1
  11. package/packages/checkpoint/package.json +1 -1
  12. package/packages/cli-plugin-sdk/package.json +1 -1
  13. package/packages/clipboard/package.json +1 -1
  14. package/packages/clipboard-plugin/package.json +1 -1
  15. package/packages/code-generation/package.json +1 -1
  16. package/packages/code-review/package.json +1 -1
  17. package/packages/codex-adapter/package.json +1 -1
  18. package/packages/codex-watcher/dist/src/session.d.ts.map +1 -1
  19. package/packages/codex-watcher/dist/src/session.js +57 -8
  20. package/packages/codex-watcher/dist/src/session.js.map +1 -1
  21. package/packages/codex-watcher/dist/src/types.d.ts +2 -0
  22. package/packages/codex-watcher/dist/src/types.d.ts.map +1 -1
  23. package/packages/codex-watcher/package.json +1 -1
  24. package/packages/codex-watcher/src/session.ts +57 -8
  25. package/packages/codex-watcher/src/types.ts +2 -0
  26. package/packages/config-capture/package.json +1 -1
  27. package/packages/context-compiler/package.json +1 -1
  28. package/packages/context-discovery/package.json +1 -1
  29. package/packages/context-manager/package.json +1 -1
  30. package/packages/cookie-sanitizer/package.json +1 -1
  31. package/packages/cost-optimizer/package.json +1 -1
  32. package/packages/dependency-analyzer/package.json +1 -1
  33. package/packages/django-plugin/package.json +1 -1
  34. package/packages/doc-generator/package.json +1 -1
  35. package/packages/e2e-tester/package.json +1 -1
  36. package/packages/evaluation-engine/package.json +1 -1
  37. package/packages/evaluation-runner/package.json +1 -1
  38. package/packages/event-bus/package.json +1 -1
  39. package/packages/event-store/package.json +1 -1
  40. package/packages/experience-replay/package.json +1 -1
  41. package/packages/feedback-collector/package.json +1 -1
  42. package/packages/file-copy-helper/package.json +1 -1
  43. package/packages/framework-detector/package.json +1 -1
  44. package/packages/framework-plugin-sdk/package.json +1 -1
  45. package/packages/frappe-plugin/package.json +1 -1
  46. package/packages/generic-web-plugin/package.json +1 -1
  47. package/packages/health-monitor/package.json +1 -1
  48. package/packages/intent-analyzer/package.json +1 -1
  49. package/packages/jev-judge/package.json +1 -1
  50. package/packages/knowledge-graph/package.json +1 -1
  51. package/packages/knowledge-retrieval/package.json +1 -1
  52. package/packages/laravel-plugin/package.json +1 -1
  53. package/packages/learning-engine/package.json +1 -1
  54. package/packages/mcp-adapter/package.json +1 -1
  55. package/packages/memory-engine/package.json +1 -1
  56. package/packages/milestone-manager/package.json +1 -1
  57. package/packages/model-registry/package.json +1 -1
  58. package/packages/nextjs-plugin/package.json +1 -1
  59. package/packages/notification/package.json +1 -1
  60. package/packages/observability/package.json +1 -1
  61. package/packages/okf-indexer/package.json +1 -1
  62. package/packages/paperclip-integration/package.json +1 -1
  63. package/packages/performance-optimizer/package.json +1 -1
  64. package/packages/privilege-broker/package.json +1 -1
  65. package/packages/project-analyzer/package.json +1 -1
  66. package/packages/project-bootstrap/package.json +1 -1
  67. package/packages/projection-engine/package.json +1 -1
  68. package/packages/prompt-compiler/package.json +1 -1
  69. package/packages/prompt-versioning/package.json +1 -1
  70. package/packages/provider-adapter-sdk/package.json +1 -1
  71. package/packages/provider-router/package.json +1 -1
  72. package/packages/provider-selector/package.json +1 -1
  73. package/packages/providers/package.json +1 -1
  74. package/packages/qdrant-skills/package.json +1 -1
  75. package/packages/quota-manager/package.json +1 -1
  76. package/packages/rate-limiter/package.json +1 -1
  77. package/packages/react-vite-plugin/package.json +1 -1
  78. package/packages/release-manager/package.json +1 -1
  79. package/packages/requirement-compiler/package.json +1 -1
  80. package/packages/runtime/package.json +1 -1
  81. package/packages/scheduler/package.json +1 -1
  82. package/packages/scheduler-adapter/package.json +1 -1
  83. package/packages/session/package.json +1 -1
  84. package/packages/session-api/package.json +1 -1
  85. package/packages/session-export/package.json +1 -1
  86. package/packages/shared-context/package.json +1 -1
  87. package/packages/skill-mcp-client/package.json +1 -1
  88. package/packages/skill-registry/package.json +1 -1
  89. package/packages/skills/package.json +1 -1
  90. package/packages/sprint-planner/package.json +1 -1
  91. package/packages/subscription-engine/package.json +1 -1
  92. package/packages/task-compiler/package.json +1 -1
  93. package/packages/telegram/package.json +1 -1
  94. package/packages/tencentdb-memory/package.json +1 -1
  95. package/packages/tencentdb-sync/package.json +1 -1
  96. package/packages/test-data-generator/package.json +1 -1
  97. package/packages/test-generator/package.json +1 -1
  98. package/packages/todo-bd-sync/package.json +1 -1
  99. package/packages/token-estimation/package.json +1 -1
  100. package/packages/token-optimizer/package.json +1 -1
  101. package/packages/trajectory/package.json +1 -1
  102. package/packages/tui/package.json +1 -1
  103. package/packages/types/package.json +1 -1
  104. package/packages/webmcp-tester/package.json +1 -1
  105. package/packages/workflow-events/package.json +1 -1
  106. package/packages/workspace-scanner/package.json +1 -1
  107. package/packages/worktree/package.json +1 -1
  108. package/packages/write-review/package.json +1 -1
package/index.ts CHANGED
@@ -377,47 +377,80 @@ async function initAutoContinue(pi: ExtensionAPI): Promise<void> {
377
377
  let pendingUserPromptCount = 0;
378
378
  let lastPromptTime = 0;
379
379
  let intakeTimer: ReturnType<typeof setTimeout> | null = null;
380
- let _pendingUserMessage = ""; // Store message for delayed evaluation (unused but reserved)
380
+ let pendingPromptContents: string[] = []; // Accumulate batch prompt contents
381
381
  const PROMPT_WINDOW_MS = 2000; // 2 second debounce window
382
382
 
383
+ // --- Codex plan auto-trigger: Track our Pi session's cwd ---
384
+ let _piSessionCwd = "";
385
+ const _SETTLE_DELAY_MS = 5000; // Wait 5 seconds after plan ready
386
+
387
+ // Capture our Pi session's cwd on session_start
388
+ pi.on("session_start", () => {
389
+ try {
390
+ _piSessionCwd = realpathSync(process.cwd());
391
+ logToFile("[codex-trigger]", "Pi session cwd captured:", _piSessionCwd);
392
+ } catch {
393
+ _piSessionCwd = process.cwd();
394
+ }
395
+ });
396
+
383
397
  // Detect user responses - track prompts for debounced task capture
384
398
  pi.on("message_start", async (event) => {
385
399
  const msg = event.message as { role?: string } | undefined;
386
400
  if (msg?.role === "user") {
401
+ // Normalize content to string (handle array of text blocks)
402
+ let content = "";
403
+ const rawContent = (msg as { content?: string | Array<{ text?: string }> } | undefined)?.content;
404
+ if (Array.isArray(rawContent)) {
405
+ content = rawContent.map((c) => c.text ?? "").join("\n");
406
+ } else if (typeof rawContent === "string") {
407
+ content = rawContent;
408
+ }
409
+
387
410
  // Skip harness-generated follow-ups (not real user prompts)
388
- const content = (msg as { content?: string } | undefined)?.content ?? "";
389
- if (!content.includes("Please add all tasks to task list todo")) {
390
- const now = Date.now();
391
- // Reset count if window expired
392
- if (now - lastPromptTime > PROMPT_WINDOW_MS) {
393
- pendingUserPromptCount = 0;
394
- }
395
- pendingUserPromptCount++;
396
- lastPromptTime = now;
397
- logToFile("[auto-continue]", "User prompt arrived, pending count:", String(pendingUserPromptCount));
398
-
399
- // Clear any pending timer
400
- if (intakeTimer) {
401
- clearTimeout(intakeTimer);
402
- intakeTimer = null;
403
- }
411
+ if (!content.includes("Please add all tasks to task list todo")) {
412
+ const now = Date.now();
413
+ // Reset batch if window expired
414
+ if (now - lastPromptTime > PROMPT_WINDOW_MS) {
415
+ pendingUserPromptCount = 0;
416
+ pendingPromptContents = [];
417
+ }
418
+ pendingUserPromptCount++;
419
+ pendingPromptContents.push(content);
420
+ lastPromptTime = now;
421
+ logToFile("[auto-continue]", "User prompt arrived, pending count:", String(pendingUserPromptCount));
422
+
423
+ // Clear any pending timer
424
+ if (intakeTimer) {
425
+ clearTimeout(intakeTimer);
426
+ intakeTimer = null;
427
+ }
404
428
 
405
- // Set debounce timer - evaluate after window expires
406
- if (taskIntakeController && todoContinuationController) {
407
- const intake = taskIntakeController;
408
- const controller = todoContinuationController;
409
- const capturedCount = pendingUserPromptCount;
410
-
411
- intakeTimer = setTimeout(async () => {
412
- // Only trigger if multiple prompts arrived
413
- if (capturedCount > 1) {
414
- pendingUserPromptCount = 0;
415
- logToFile("[auto-continue]", "Multiple prompts in queue, evaluating for task capture");
416
- try {
417
- const result = await intake.evaluateWithTodos(content, controller);
418
- if (result.actionable && result.action !== "skip") {
419
- await intake.requestCapture(content, "harness:task-capture");
420
- }
429
+ // Set debounce timer - evaluate after window expires
430
+ if (taskIntakeController && todoContinuationController) {
431
+ const intake = taskIntakeController;
432
+ const controller = todoContinuationController;
433
+ const capturedCount = pendingUserPromptCount;
434
+ const capturedContents = [...pendingPromptContents];
435
+
436
+ intakeTimer = setTimeout(async () => {
437
+ // Only trigger if multiple prompts arrived
438
+ if (capturedCount > 1) {
439
+ pendingUserPromptCount = 0;
440
+ pendingPromptContents = [];
441
+ logToFile("[auto-continue]", "Multiple prompts in queue, evaluating for task capture");
442
+ try {
443
+ // Check if stopped before dispatching
444
+ if (intake.isStopped()) {
445
+ logToFile("[auto-continue]", "Task intake skipped - stopped after evaluation");
446
+ return;
447
+ }
448
+ // Evaluate all prompts in batch
449
+ const combinedContent = capturedContents.join("\n---\n");
450
+ const result = await intake.evaluateWithTodos(combinedContent, controller);
451
+ if (result.actionable && result.action !== "skip") {
452
+ await intake.requestCapture(combinedContent, "harness:task-capture");
453
+ }
421
454
  } catch (err) {
422
455
  logToFile("[auto-continue]", "Task intake error:", String(err));
423
456
  }
@@ -1608,7 +1641,7 @@ function processCompletionFile(filePath: string, pi: ExtensionAPI): void {
1608
1641
  // --- Debug logging (file only, no console override) ---------------
1609
1642
  // Logs written to file only. Real console output preserved for pi's TUI.
1610
1643
  import { homedir } from "node:os";
1611
- import { existsSync, mkdirSync, readFileSync, symlinkSync, appendFileSync } from "node:fs";
1644
+ import { existsSync, mkdirSync, readFileSync, symlinkSync, appendFileSync, realpathSync } from "node:fs";
1612
1645
  import { truncateToWidth } from "@earendil-works/pi-tui";
1613
1646
  import { join, dirname } from "node:path";
1614
1647
 
@@ -2030,39 +2063,122 @@ export default function (pi: ExtensionAPI) {
2030
2063
  // Collect promise so we can wait for initialization before showing startup notification
2031
2064
  asyncInitPromises.push(initTelegram(pi));
2032
2065
 
2033
- // --- codex-watcher: Inject Codex plans into pi.dev + Telegram --------------
2034
- // Lightweight: polls ~/.codex/sessions/ every 5s, no LangChain daemon.
2035
- // On plan detected: sends Telegram alert + steer message to pi.dev.
2066
+ // --- codex-watcher: Auto-trigger Pi when Codex finishes a plan ---
2067
+ // Flow: detect plan -> settle timer -> file stability check -> cwd match -> trigger
2036
2068
  try {
2037
- // Pending delivery queue: messages waiting to be delivered to Pi
2038
- // Keyed by sessionId, value is array of {ordinal, text, delivered}
2039
- const pendingDelivery = new Map<string, Array<{ordinal: number; text: string; delivered: boolean}>>();
2040
- let currentSessionId: string | null = null;
2069
+ // Event tracking for deduplication
2070
+ interface PlanEvent {
2071
+ codexSessionId: string;
2072
+ planPath: string;
2073
+ planHash: string;
2074
+ status: "observed" | "settling" | "ready" | "triggered" | "failed";
2075
+ ordinal: number;
2076
+ lastActivity: number;
2077
+ settleTimer: ReturnType<typeof setTimeout> | null;
2078
+ fileStableSince: number;
2079
+ }
2080
+ const deliveredEvents = new Map<string, PlanEvent>();
2081
+ let currentCodexSessionId: string | null = null;
2082
+ let currentProjectRoot = "";
2083
+ let currentPlanCandidate: { ordinal: number; text: string; timestamp: number } | null = null;
2084
+ let lastActivityTime = 0;
2085
+
2086
+ // Check if plan file exists and is stable (mtime unchanged)
2087
+ function checkPlanFileStable(planPath: string, sinceMs: number): boolean {
2088
+ try {
2089
+ const stat = statSync(planPath);
2090
+ const ageMs = Date.now() - stat.mtimeMs;
2091
+ return ageMs >= sinceMs;
2092
+ } catch {
2093
+ return false;
2094
+ }
2095
+ }
2041
2096
 
2042
- // Process pending delivery queue - try to deliver queued messages
2043
- function processDeliveryQueue(sessionId: string) {
2044
- const queue = pendingDelivery.get(sessionId);
2045
- if (!queue || queue.length === 0) return;
2097
+ // Try to find wiki/plan.md in project root
2098
+ function findPlanFile(projectRoot: string): string | null {
2099
+ const candidates = [
2100
+ join(projectRoot, "wiki", "plan.md"),
2101
+ join(projectRoot, "wiki", "PLAN.md"),
2102
+ join(projectRoot, "docs", "plan.md"),
2103
+ ];
2104
+ for (const path of candidates) {
2105
+ if (existsSync(path)) return path;
2106
+ }
2107
+ return null;
2108
+ }
2046
2109
 
2047
- // Try to deliver pending messages
2048
- for (const item of queue) {
2049
- if (item.delivered) continue;
2110
+ // Trigger Pi to read the plan
2111
+ async function triggerPiForPlan(event: PlanEvent): Promise<void> {
2112
+ // Check cwd match
2113
+ if (_piSessionCwd && currentProjectRoot && _piSessionCwd !== currentProjectRoot) {
2114
+ logToFile("[codex-trigger]", "Cwd mismatch, skipping:", _piSessionCwd, "!=", currentProjectRoot);
2115
+ return;
2116
+ }
2050
2117
 
2051
- try {
2052
- const planContent = `[Codex plan detected — ordinal ${item.ordinal}]\n\n${item.text}`;
2053
- pi.sendUserMessage(planContent, { deliverAs: "steer" });
2054
- item.delivered = true;
2055
- logToFile("[codex]", `Delivered queued ordinal ${item.ordinal} to Pi`);
2056
- } catch {
2057
- // Still failing, will retry on next poll
2058
- logToFile("[codex]", `Retry failed for ordinal ${item.ordinal}`);
2059
- }
2118
+ const triggerMsg = `Codex finished a plan for this workspace. Read and follow the plan at:\n${event.planPath}\n\nTreat that file as the task requirements. Start by summarizing the plan and then carry it out. Do not edit the plan unless the user asks.`;
2119
+
2120
+ try {
2121
+ await pi.sendUserMessage(triggerMsg, { deliverAs: "steer" });
2122
+ event.status = "triggered";
2123
+ logToFile("[codex-trigger]", "Triggered Pi for plan:", event.planPath);
2124
+ nc("CodexPlanDetected", {
2125
+ requirement: `Plan ready: ${event.planPath}`,
2126
+ taskTitle: `Ordinal ${event.ordinal}`,
2127
+ });
2128
+ } catch (err) {
2129
+ event.status = "failed";
2130
+ logToFile("[codex-trigger]", "Trigger failed:", String(err));
2060
2131
  }
2132
+ }
2061
2133
 
2062
- // Clean up delivered messages from the front of the queue
2063
- while (queue.length > 0 && queue[0].delivered) {
2064
- queue.shift();
2134
+ // Start settle timer for plan
2135
+ function startSettleTimer(planPath: string, ordinal: number) {
2136
+ const eventKey = `${currentCodexSessionId}:${planPath}`;
2137
+ const existing = deliveredEvents.get(eventKey);
2138
+ if (existing && (existing.status === "triggered" || existing.status === "ready")) {
2139
+ logToFile("[codex-trigger]", "Plan already handled:", eventKey);
2140
+ return;
2065
2141
  }
2142
+
2143
+ const event: PlanEvent = {
2144
+ codexSessionId: currentCodexSessionId ?? "",
2145
+ planPath,
2146
+ planHash: "",
2147
+ status: "settling",
2148
+ ordinal,
2149
+ lastActivity: Date.now(),
2150
+ settleTimer: null,
2151
+ fileStableSince: 0,
2152
+ };
2153
+ deliveredEvents.set(eventKey, event);
2154
+
2155
+ logToFile("[codex-trigger]", "Plan observed, starting settle timer:", planPath);
2156
+
2157
+ // Cancel existing timer if any
2158
+ if (event.settleTimer) {
2159
+ clearTimeout(event.settleTimer);
2160
+ }
2161
+
2162
+ event.settleTimer = setTimeout(async () => {
2163
+ // Check file stability (5 seconds without changes)
2164
+ if (!checkPlanFileStable(planPath, _SETTLE_DELAY_MS)) {
2165
+ logToFile("[codex-trigger]", "Plan file still changing, restarting timer:", planPath);
2166
+ // Restart timer
2167
+ event.lastActivity = Date.now();
2168
+ startSettleTimer(planPath, ordinal);
2169
+ return;
2170
+ }
2171
+
2172
+ // Check no new activity during settle
2173
+ if (Date.now() - lastActivityTime > _SETTLE_DELAY_MS) {
2174
+ event.status = "ready";
2175
+ logToFile("[codex-trigger]", "Plan settled, triggering Pi:", planPath);
2176
+ await triggerPiForPlan(event);
2177
+ } else {
2178
+ logToFile("[codex-trigger]", "New activity during settle, restarting:", planPath);
2179
+ startSettleTimer(planPath, ordinal);
2180
+ }
2181
+ }, _SETTLE_DELAY_MS);
2066
2182
  }
2067
2183
 
2068
2184
  const codexHandle = startWatcher({
@@ -2070,61 +2186,59 @@ export default function (pi: ExtensionAPI) {
2070
2186
  maxIdlePolls: Infinity,
2071
2187
  onSessionChange: (session) => {
2072
2188
  if (session) {
2073
- logToFile("[codex]", `Session started: ${session.threadName}`);
2074
- currentSessionId = session.id;
2075
- // Initialize queue for new session
2076
- if (!pendingDelivery.has(session.id)) {
2077
- pendingDelivery.set(session.id, []);
2078
- }
2189
+ logToFile("[codex]", `Session started: ${session.threadName}, root: ${session.projectRoot}`);
2190
+ currentCodexSessionId = session.id;
2191
+ currentProjectRoot = session.projectRoot;
2079
2192
  nc("CodexSessionStarted", {
2080
2193
  requirement: session.threadName || "Codex session",
2081
2194
  taskTitle: session.id,
2082
2195
  });
2083
2196
  } else {
2084
- currentSessionId = null;
2197
+ currentCodexSessionId = null;
2198
+ currentProjectRoot = "";
2199
+ currentPlanCandidate = null;
2085
2200
  }
2086
2201
  },
2087
2202
  onMessages: (msgs) => {
2088
- const sessionId = currentSessionId;
2089
- if (!sessionId) return;
2090
-
2091
- // First, try to deliver any pending messages
2092
- processDeliveryQueue(sessionId);
2203
+ if (!currentCodexSessionId) return;
2093
2204
 
2094
2205
  for (const msg of msgs) {
2095
- // Skip user messages — only track assistant plans
2206
+ lastActivityTime = Date.now();
2207
+
2096
2208
  if (msg.role !== "assistant") continue;
2097
2209
 
2098
2210
  const classification = classifyMessage(msg.text);
2099
2211
  if (classification !== "plan" && classification !== "mixed") continue;
2100
2212
 
2101
- // Emit Telegram alert with preview (include more of the plan)
2102
- const planPreview = msg.text.slice(0, 800) + (msg.text.length > 800 ? "\n... (full plan forwarded to Pi)" : "");
2213
+ // Track plan candidate
2214
+ currentPlanCandidate = { ordinal: msg.ordinal, text: msg.text, timestamp: Date.now() };
2215
+
2216
+ // Try to find plan file in project root
2217
+ if (currentProjectRoot) {
2218
+ const planPath = findPlanFile(currentProjectRoot);
2219
+ if (planPath) {
2220
+ logToFile("[codex-trigger]", "Plan message + wiki file detected:", planPath);
2221
+ startSettleTimer(planPath, msg.ordinal);
2222
+ } else {
2223
+ // No wiki/plan.md found yet - wait for file to appear
2224
+ logToFile("[codex-trigger]", "Plan message but no wiki/plan.md yet, waiting...");
2225
+ }
2226
+ }
2227
+
2228
+ // Emit Telegram alert
2229
+ const planPreview = msg.text.slice(0, 500) + (msg.text.length > 500 ? "\n..." : "");
2103
2230
  nc("CodexPlanDetected", {
2104
2231
  requirement: planPreview,
2105
2232
  taskTitle: `Ordinal ${msg.ordinal}`,
2106
2233
  });
2107
-
2108
- // Inject full plan into pi.dev as a steer message
2109
- const planContent = `[Codex plan detected — ordinal ${msg.ordinal}]\n\n${msg.text}`;
2110
- try {
2111
- pi.sendUserMessage(planContent, { deliverAs: "steer" });
2112
- logToFile("[codex]", `Delivered ordinal ${msg.ordinal} to Pi`);
2113
- } catch {
2114
- // Add to pending queue for retry
2115
- const queue = pendingDelivery.get(sessionId) ?? [];
2116
- queue.push({ ordinal: msg.ordinal, text: msg.text, delivered: false });
2117
- pendingDelivery.set(sessionId, queue);
2118
- logToFile("[codex]", `Delivery failed for ordinal ${msg.ordinal}, queued for retry`);
2119
- }
2120
2234
  }
2121
2235
  },
2122
2236
  });
2123
2237
 
2124
2238
  // Clean up when pi session ends
2125
- pi.on("session_shutdown", () => codexHandle.stop());
2239
+ pi.on("session_shutdown", () => codexHandle.stop());
2126
2240
  } catch {
2127
- // Codex watcher unavailable (e.g. no codex package installed)
2241
+ // Codex watcher unavailable
2128
2242
  }
2129
2243
 
2130
2244
  // --- honcho-memory: Honcho MCP for peer/user memory (honcho_profile, etc.) ----
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-harness-runtime",
3
- "version": "1.1.275",
3
+ "version": "1.1.277",
4
4
  "description": "[BETA] Codex-style /usage status + autonomous coding harness for pi. Not production ready — expect breaking changes.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/a2a-adapter",
3
- "version": "1.1.275",
3
+ "version": "1.1.277",
4
4
  "type": "module",
5
5
  "description": "Google Agent-to-Agent (A2A) protocol adapter for pi-harness",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/agent-policy",
3
- "version": "1.1.275",
3
+ "version": "1.1.277",
4
4
  "description": "Agent policy runtime for pi-harness - enforces mandatory rule delivery and mutation gating",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/architecture-generator",
3
- "version": "1.1.275",
3
+ "version": "1.1.277",
4
4
  "description": "Generate ADR and Mermaid diagrams from project analysis",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/auth",
3
- "version": "1.1.275",
3
+ "version": "1.1.277",
4
4
  "description": "pi-harness-runtime — auth",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/autonomous-refactor",
3
- "version": "1.1.275",
3
+ "version": "1.1.277",
4
4
  "type": "module",
5
5
  "description": "Autonomous refactoring engine",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/autonomous-runtime",
3
- "version": "1.1.275",
3
+ "version": "1.1.277",
4
4
  "description": "Autonomous Operations Runtime — task inbox, lease management, and worker lifecycle (RFC-0101)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/cache-strategy",
3
- "version": "1.1.275",
3
+ "version": "1.1.277",
4
4
  "type": "module",
5
5
  "description": "Smart caching with TTL and invalidation strategies (RFC-0022)",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/capability-registry",
3
- "version": "1.1.275",
3
+ "version": "1.1.277",
4
4
  "description": "Capability Registry for pi-harness-runtime — tracks model capabilities and enables capability-based routing",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/checkpoint",
3
- "version": "1.1.275",
3
+ "version": "1.1.277",
4
4
  "description": "Enhanced checkpoint system with incremental snapshots, diff-based storage, and recovery strategies",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/cli-plugin-sdk",
3
- "version": "1.1.275",
3
+ "version": "1.1.277",
4
4
  "type": "module",
5
5
  "description": "CLI Plugin SDK for pi-harness — install, list, remove, update, invoke plugins",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/clipboard",
3
- "version": "1.1.275",
3
+ "version": "1.1.277",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/clipboard-plugin",
3
- "version": "1.1.275",
3
+ "version": "1.1.277",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/code-generation",
3
- "version": "1.1.275",
3
+ "version": "1.1.277",
4
4
  "description": "Code generation pipeline for pi-harness-runtime",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/code-review",
3
- "version": "1.1.275",
3
+ "version": "1.1.277",
4
4
  "description": "Automated code review engine for pi-harness-runtime",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/codex-adapter",
3
- "version": "1.1.275",
3
+ "version": "1.1.277",
4
4
  "type": "module",
5
5
  "description": "OpenAI Codex provider adapter for pi-harness",
6
6
  "main": "dist/index.js",
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,mDAAmD;AACnD,wBAAgB,gBAAgB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAsBvE;AAED,oDAAoD;AACpD,wBAAgB,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,EAAE,CAkBhE"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,mDAAmD;AACnD,wBAAgB,gBAAgB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CA0BvE;AAED,oDAAoD;AACpD,wBAAgB,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,EAAE,CAuBhE"}
@@ -3,7 +3,8 @@
3
3
  */
4
4
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
5
5
  import { homedir } from "node:os";
6
- import { join } from "node:path";
6
+ import { join, resolve } from "node:path";
7
+ import { realpathSync } from "node:fs";
7
8
  /** Find the most recently active Codex session. */
8
9
  export function getLatestSession(codexDir) {
9
10
  const indexPath = getSessionIndexPath(codexDir);
@@ -20,11 +21,14 @@ export function getLatestSession(codexDir) {
20
21
  }
21
22
  if (!latest)
22
23
  return null;
24
+ const rolloutPath = findRolloutPath(latest.id, codexDir);
25
+ const projectRoot = getProjectRootFromRollout(rolloutPath);
23
26
  return {
24
27
  id: latest.id,
25
28
  threadName: latest.thread_name,
26
29
  updatedAt: latest.updated_at,
27
- rolloutPath: findRolloutPath(latest.id, codexDir),
30
+ rolloutPath,
31
+ projectRoot,
28
32
  };
29
33
  }
30
34
  /** Get all sessions sorted by most recent first. */
@@ -40,12 +44,17 @@ export function getAllSessions(codexDir) {
40
44
  }
41
45
  return sessions
42
46
  .sort((a, b) => b.updated_at.localeCompare(a.updated_at))
43
- .map((e) => ({
44
- id: e.id,
45
- threadName: e.thread_name,
46
- updatedAt: e.updated_at,
47
- rolloutPath: findRolloutPath(e.id, codexDir),
48
- }));
47
+ .map((e) => {
48
+ const rolloutPath = findRolloutPath(e.id, codexDir);
49
+ const projectRoot = getProjectRootFromRollout(rolloutPath);
50
+ return {
51
+ id: e.id,
52
+ threadName: e.thread_name,
53
+ updatedAt: e.updated_at,
54
+ rolloutPath,
55
+ projectRoot,
56
+ };
57
+ });
49
58
  }
50
59
  // ---------------------------------------------------------------------------
51
60
  // Internal helpers
@@ -122,4 +131,44 @@ function readLines(filePath) {
122
131
  return [];
123
132
  }
124
133
  }
134
+ /**
135
+ * Parse rollout file for project working directory.
136
+ * Looks for session_meta JSONL records containing the working directory.
137
+ * Returns canonical absolute path or empty string if not found.
138
+ */
139
+ function getProjectRootFromRollout(rolloutPath) {
140
+ try {
141
+ if (!existsSync(rolloutPath))
142
+ return "";
143
+ const lines = readLines(rolloutPath);
144
+ // Look for session_meta records with working directory
145
+ for (const line of lines) {
146
+ try {
147
+ const obj = JSON.parse(line);
148
+ if (obj.type === "session_meta" || obj.type === "session_start") {
149
+ const data = obj.data;
150
+ if (data && typeof data.working_directory === "string") {
151
+ const cwd = data.working_directory;
152
+ if (cwd && cwd.startsWith("/")) {
153
+ // Canonicalize the path
154
+ try {
155
+ return realpathSync(cwd);
156
+ }
157
+ catch {
158
+ return resolve(cwd);
159
+ }
160
+ }
161
+ }
162
+ }
163
+ }
164
+ catch {
165
+ // Skip malformed JSON lines
166
+ }
167
+ }
168
+ }
169
+ catch {
170
+ // File read error
171
+ }
172
+ return "";
173
+ }
125
174
  //# sourceMappingURL=session.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,mDAAmD;AACnD,MAAM,UAAU,gBAAgB,CAAC,QAAiB;IACjD,MAAM,SAAS,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAChD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAExC,IAAI,MAAM,GAA6B,IAAI,CAAC;IAE5C,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;YACrD,MAAM,GAAG,KAAK,CAAC;QAChB,CAAC;IACF,CAAC;IAED,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,OAAO;QACN,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,UAAU,EAAE,MAAM,CAAC,WAAW;QAC9B,SAAS,EAAE,MAAM,CAAC,UAAU;QAC5B,WAAW,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC;KACjD,CAAC;AACH,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,cAAc,CAAC,QAAiB;IAC/C,MAAM,SAAS,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAChD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IAEtC,MAAM,QAAQ,GAAwB,EAAE,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,KAAK;YAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,QAAQ;SACb,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;SACxD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACZ,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,UAAU,EAAE,CAAC,CAAC,WAAW;QACzB,SAAS,EAAE,CAAC,CAAC,UAAU;QACvB,WAAW,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,EAAE,QAAQ,CAAC;KAC5C,CAAC,CAAC,CAAC;AACN,CAAC;AAED,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,SAAS,mBAAmB,CAAC,QAAiB;IAC7C,MAAM,IAAI,GAAG,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;IACnD,OAAO,IAAI,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,eAAe,CAAC,SAAiB,EAAE,QAAiB;IAC5D,MAAM,IAAI,GAAG,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;IACnD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAE3C,8FAA8F;IAC9F,kEAAkE;IAClE,mEAAmE;IACnE,MAAM,KAAK,GAAG,cAAc,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACrD,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,OAAO,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,GAAG,SAAS,QAAQ,CAAC,CAAC;AAC3D,CAAC;AAED,yEAAyE;AACzE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAW;IAC7B,IAAI,CAAC;QACJ,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAC9B,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,MAAM,IAAI,CAAC;gBACX,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACvB,CAAC;QACF,CAAC;IACF,CAAC;IAAC,MAAM,CAAC;QACR,yCAAyC;IAC1C,CAAC;AACF,CAAC;AAED,2EAA2E;AAC3E,SAAS,cAAc,CAAC,WAAmB,EAAE,SAAiB;IAC7D,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7C,IAAI,CAAC;YACJ,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;gBACzC,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,SAAS,QAAQ,CAAC,EAAE,CAAC;oBACxE,OAAO,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gBAC5B,CAAC;YACF,CAAC;QACF,CAAC;QAAC,MAAM,CAAC;YACR,8BAA8B;QAC/B,CAAC;IACF,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAQD,SAAS,qBAAqB,CAAC,IAAY;IAC1C,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC;QACxD,IAAI,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;YACvE,OAAO,IAAI,CAAC;QACb,CAAC;QACD,OAAO;YACN,EAAE,EAAE,GAAG,CAAC,EAAY;YACpB,WAAW,EAAE,GAAG,CAAC,WAAqB;YACtC,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC;SACxC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,SAAS,SAAS,CAAC,QAAgB;IAClC,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC/C,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,EAAE,CAAC;IACX,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"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"}
@@ -22,6 +22,8 @@ export interface CodexSession {
22
22
  updatedAt: string;
23
23
  /** Absolute path to the rollout transcript file */
24
24
  rolloutPath: string;
25
+ /** Canonical absolute path to the project working directory */
26
+ projectRoot: string;
25
27
  }
26
28
  export interface CodexMessage {
27
29
  /** Unique ordinal within the session (monotonically increasing) */