pi-crew 0.10.4 → 0.10.5

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-crew",
3
- "version": "0.10.4",
3
+ "version": "0.10.5",
4
4
  "description": "Pi extension for coordinated AI teams, workflows, worktrees, and async task orchestration",
5
5
  "author": "baphuongna",
6
6
  "license": "MIT",
@@ -10,7 +10,6 @@ import { createRunPaths, loadRunManifestById, saveRunManifestAsync, updateRunSta
10
10
  import type { TeamRunManifest, TeamTaskState } from "../state/types.ts";
11
11
  import { allTeams, discoverTeams } from "../teams/discover-teams.ts";
12
12
  import { errorMessage } from "../utils/guards.ts";
13
- import { projectCrewRoot } from "../utils/paths.ts";
14
13
  import { assertSafePathId } from "../utils/safe-paths.ts";
15
14
  import { allWorkflows, discoverWorkflows } from "../workflows/discover-workflows.ts";
16
15
  // Heavy runtime — lazy-loaded to avoid pulling team-runner into background-runner
@@ -160,6 +159,27 @@ export function signalEventType(sig: string): "async.signal" | "async.failed" {
160
159
  return BENIGN_SIGNALS.has(sig) ? "async.signal" : "async.failed";
161
160
  }
162
161
 
162
+ /**
163
+ * Scope-aware diagnostic paths for the background runner (issue #55, follows
164
+ * the #54 fix in run-tracker.ts). Runs created in a markerless (non-git) cwd
165
+ * live under userCrewRoot() — resolved via the same createRunPaths/
166
+ * scopeBaseRoot chain used at run CREATION — while project cwds keep .crew/ or
167
+ * the .pi/teams/ fallback (issue #29). Pure path math: createRunPaths asserts
168
+ * the runId (R11-2 boundary hardening preserved) and never touches the fs.
169
+ *
170
+ * These must stay (cwd, runId)-derived: both sites run BEFORE the manifest is
171
+ * loaded (the console redirect is the FIRST thing main() does; exitCodePath is
172
+ * computed at module load), so manifest.stateRoot is not available yet.
173
+ */
174
+ export function backgroundLogPath(cwd: string, runId: string): string {
175
+ return path.join(createRunPaths(cwd, runId).stateRoot, "background.log");
176
+ }
177
+
178
+ /** exit-code.txt sibling of background.log — same scope resolution (#55). */
179
+ export function backgroundExitCodePath(cwd: string, runId: string): string {
180
+ return path.join(createRunPaths(cwd, runId).stateRoot, "exit-code.txt");
181
+ }
182
+
163
183
  /**
164
184
  * Fire-and-forget event log for signal handlers. Extracted to module level
165
185
  * (from inside main()) so the exported SIGINT handler installer (test seam)
@@ -421,10 +441,12 @@ async function main(): Promise<void> {
421
441
  // best-effort try/catch so the hardening is never silently swallowed).
422
442
  assertSafePathId("runId", _runId);
423
443
  try {
424
- // Use projectCrewRoot() so the background log lives next to the
425
- // manifest in either .crew/state/runs/ or .pi/teams/state/runs/
426
- // depending on the project's chosen layout (issue #29).
427
- const logPath = path.join(projectCrewRoot(_cwd), "state", "runs", _runId, "background.log");
444
+ // Scope-aware (issue #55): resolve via createRunPaths so the log lands
445
+ // next to the manifest for BOTH project cwds (.crew/ or the .pi/teams/
446
+ // fallback, issue #29) and markerless cwds (user scope, issue #54). The
447
+ // previous projectCrewRoot join silently dropped the console redirect
448
+ // for user-scope runs — exactly the log needed to diagnose them.
449
+ const logPath = backgroundLogPath(_cwd, _runId);
428
450
  logFd = fs.openSync(logPath, "a");
429
451
  const origWrite =
430
452
  (_prefix: string) =>
@@ -478,8 +500,11 @@ async function main(): Promise<void> {
478
500
  // IIFE runs at MODULE LOAD, so an unsafe runId throws before the runner
479
501
  // starts (intended fail-fast, matching run-import.ts:105 pattern).
480
502
  assertSafePathId("runId", runId);
481
- // Use projectCrewRoot() to honour the .pi/teams/ fallback (issue #29).
482
- return path.join(projectCrewRoot(cwd), "state", "runs", runId, "exit-code.txt");
503
+ // Scope-aware (issue #55): same resolution as backgroundLogPath — project
504
+ // scope (.crew/ or .pi/teams/, issue #29) or user scope (#54). The
505
+ // previous projectCrewRoot join never landed exit-code.txt for user-scope
506
+ // runs, hiding non-zero exit diagnostics.
507
+ return backgroundExitCodePath(cwd, runId);
483
508
  })();
484
509
  if (exitCodePath) {
485
510
  process.on("exit", (code) => {
@@ -1,8 +1,6 @@
1
1
  import * as fs from "node:fs";
2
- import * as path from "node:path";
3
- import { loadRunManifestById } from "../state/stores/state-store.ts";
2
+ import { createRunPaths, loadRunManifestById } from "../state/stores/state-store.ts";
4
3
  import type { TeamRunManifest, TeamTaskState } from "../state/types.ts";
5
- import { projectCrewRoot } from "../utils/paths.ts";
6
4
  import { isFinishedRunStatus } from "./process-status.ts";
7
5
 
8
6
  export interface RunWaitResult {
@@ -149,11 +147,14 @@ export async function waitForRun(
149
147
  }
150
148
  if (attempt === 0) {
151
149
  // Early exit: if the run directory doesn't exist, don't waste time polling.
152
- // Use projectCrewRoot() to honour the .pi/teams/ fallback for .pi-based
153
- // projects (see issue #29). Without this, the hardcoded `.crew/state/runs/`
154
- // path never resolves in projects that use the `.pi/` layout, the throw
155
- // escapes via subagent-manager.ts:281, and pi crashes with uncaughtException.
156
- const runDir = path.join(projectCrewRoot(cwd), "state", "runs", runId);
150
+ // Resolve through createRunPaths (scopeBaseRoot) so the probe matches where
151
+ // runs are CREATED: project scope — incl. the .pi/teams/ fallback for
152
+ // .pi-based projects (issue #29) — for cwds under a repo root, and USER
153
+ // scope for markerless cwds (issue #54). The previous projectCrewRoot(cwd)
154
+ // join always looked at <cwd>/.crew/state/runs for a markerless cwd, so
155
+ // RUN/WAIT instantly threw "Run not found" while the user-scope crew kept
156
+ // running. createRunPaths is pure path math (no mkdir), so it is safe here.
157
+ const runDir = createRunPaths(cwd, runId).stateRoot;
157
158
  if (!fs.existsSync(runDir)) {
158
159
  throw new Error(`Run ${runId} not found. No run directory at ${runDir}`);
159
160
  }