@getpipher/armory-fleet 0.10.3 → 0.11.1

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.
@@ -22,6 +22,11 @@ export const subagentParams = Type.Object({
22
22
  lifecycle: Type.Optional(Type.String({ description: "Run a multi-phase superpowers lifecycle by name (e.g. 'default') instead of a single delegate. Tool-driven lifecycles run end-to-end (auto) — checkpoints are a /fleet panel feature." })),
23
23
  auto: Type.Optional(Type.Boolean({ description: "Only relevant with `lifecycle`. Tool-driven is always auto; this flag is forward-compat. Panel-driven uses --auto on /fleet-implement." })),
24
24
  background: Type.Optional(Type.Boolean({ description: "Fire without awaiting. The run goes to the async/bg pool on an isolated git worktree; this returns { runId, status: 'background' } immediately. Foreground (default) awaits the result." })),
25
+ isolation: Type.Optional(Type.Union([
26
+ Type.Literal("worktree"),
27
+ Type.Literal("none"),
28
+ Type.Literal("auto"),
29
+ ], { description: "Edit isolation for background runs. 'worktree' = git worktree (requires a git repo; fails sync if not). 'none' = in-place in cwd (no isolation; parallel edits may conflict). 'auto' (default) = worktree when cwd is a git repo, in-place otherwise." })),
25
30
  schedule: Type.Optional(Type.String({ description: 'Schedule the run instead of firing now: a cron string ("0 9 * * 1-5"), an interval ("30m"/"2h"), or a one-shot ISO datetime ("2026-07-25T14:00"). Returns { scheduleId, nextFire }. Session-scoped (fires only while pi is open); no catch-up.' })),
26
31
  maxTurns: Type.Optional(Type.Number({ description: 'Per-run turn budget (default 20). Raise for complex multi-step tasks (e.g. 40) so the subagent doesn\'t hit the budget mid-task; lower for trivial lookups.' })),
27
32
  });
@@ -80,13 +85,14 @@ export function createSubagentTool(deps: SubagentToolDeps) {
80
85
  }
81
86
  if (params.schedule) {
82
87
  if (!deps.scheduler) return { isError: true, content: [{ type: "text" as const, text: "scheduling not configured (scheduler missing)" }] };
83
- const id = deps.scheduler.register({ task: params.task, expression: params.schedule, lifecycle: params.lifecycle ?? "default", auto: params.auto ?? true });
88
+ const id = deps.scheduler.register({ task: params.task, expression: params.schedule, lifecycle: params.lifecycle ?? "default", auto: params.auto ?? true, isolation: params.isolation });
84
89
  const entry = deps.scheduler.list().find((s) => s.id === id);
85
90
  return { content: [{ type: "text" as const, text: `scheduled: ${id} · next fire: ${entry?.nextFire?.toISOString() ?? "(paused)"}` }], details: { scheduleId: id, nextFire: entry?.nextFire ?? null } };
86
91
  }
87
92
  if (params.background) {
88
93
  if (!deps.asyncRunner) return { isError: true, content: [{ type: "text" as const, text: "background runs not configured (asyncRunner missing)" }] };
89
- const handle = runBackground(params.task, { deps: deps.asyncRunner, lifecycle: params.lifecycle ?? "default", mode: "auto" });
94
+ const handle = runBackground(params.task, { deps: deps.asyncRunner, lifecycle: params.lifecycle ?? "default", mode: "auto", isolation: params.isolation });
95
+ if (handle.status === "failed") return { isError: true, content: [{ type: "text" as const, text: handle.error }] };
90
96
  return { content: [{ type: "text" as const, text: `background run: ${handle.runId}` }], details: handle };
91
97
  }
92
98
  if (params.lifecycle) {
@@ -40,6 +40,16 @@ export class WorktreeService {
40
40
  return existsSync(this.pathFor(runId));
41
41
  }
42
42
 
43
+ /** v0.11.1: is `rootDir` (or `dir`) inside a git repo? Cheap sync pre-flight for isolation routing. */
44
+ isGitRepo(dir: string = this.rootDir): boolean {
45
+ try {
46
+ sh("git rev-parse --show-toplevel", dir);
47
+ return true;
48
+ } catch {
49
+ return false;
50
+ }
51
+ }
52
+
43
53
  create(runId: string, baseRef = "HEAD"): WorktreeRef {
44
54
  if (this.exists(runId)) {
45
55
  throw new Error(`worktree for run ${runId} already exists at ${this.pathFor(runId)}`);