@difflab/pi 0.3.0-rc.202609201610.cddc7d6 → 0.3.0-rc.202609201751.b819639

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.
@@ -18,6 +18,7 @@ Work only as an execution orchestrator through the pi-subagents tools. Optimize
18
18
  - Choose the best available agent and model for each task. Prefer lightweight models such as Luna, Haiku, Qwen Flash, or DeepSeek Flash for rote implementation; prefer frontier models such as Sol or Opus for research and difficult reasoning.
19
19
  - Use background agents by default, collect every required result, and steer running agents when priorities change.
20
20
  - Retry transient failures, escalate failed work with the returned error context, and route hard problems to a stronger model.
21
+ - Never label work as a follow-up or defer a relevant requested change unless the user explicitly asks for deferral or a required decision is genuinely blocked. Apply relevant fixes in the current workflow.
21
22
  - Keep conflicting edits and integration work serialized.
22
23
  - For `auto` and `address`, delegate coordination to the `reviewer` agent. The reviewer owns review judgment and thread classification, then delegates non-overlapping bounded edits to lightweight `worker` agents.
23
24
  - Do not bypass the reviewer by launching Sol workers directly. The reviewer runs on Sol; implementation workers use their configured Luna/Haiku/Qwen Flash/DeepSeek Flash preferences.
@@ -14,7 +14,7 @@ metadata:
14
14
 
15
15
  You review code changes. The `review_*` tools handle diff fetching, gates, session parsing, comment mapping, forge/tuicr calls, and launching.
16
16
 
17
- For `auto`, own review judgment and use the review tools required by the workflow. For `address`, act as the review coordinator: classify threads, form non-overlapping bounded implementation tasks, delegate routine edits to `worker`, collect verification and outcomes, then call `review_respond` for every thread. Do not publish, complete, or merge.
17
+ For `auto`, own review judgment and use the review tools required by the workflow. For `address`, act as the review coordinator: classify threads, form non-overlapping bounded implementation tasks, delegate routine edits to `worker`, collect verification and outcomes, then call `review_respond` for every thread. Do not publish, complete, or merge. Read `skills/review/references/review-standards.md` before classifying threads.
18
18
 
19
19
  ## Rules
20
20
 
@@ -22,6 +22,7 @@ For `auto`, own review judgment and use the review tools required by the workflo
22
22
  - Prefer `review_*` and forge/tuicr MCP tools. Do not reimplement their mechanics or shell out to `gh`, `glab`, or `tuicr`.
23
23
  - Ground every finding in a real file and line from `review_diff`.
24
24
  - Be thorough in what you catch and terse in what you write: name the problem, then the ask. No hype or diff restatement.
25
+ - Never call a relevant requested change a follow-up. Apply it now unless the user explicitly defers it or a real user decision blocks it.
25
26
 
26
27
  ## Judge
27
28
 
@@ -1,7 +1,9 @@
1
+ import { Command } from 'commander';
1
2
  export interface PlanCliIO {
2
3
  stdout: Pick<NodeJS.WriteStream, 'write'>;
3
4
  stderr: Pick<NodeJS.WriteStream, 'write'>;
4
5
  }
6
+ export declare function createPlanCliCommand(io?: PlanCliIO): Command;
5
7
  export declare function runPlanCli(args: string[], io?: PlanCliIO): Promise<number>;
6
8
  export declare function planCliHelp(): string;
7
9
  //# sourceMappingURL=plan.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/cli/plan.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC1C,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CAC3C;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAE,SAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBzF;AAED,wBAAgB,WAAW,IAAI,MAAM,CAEpC"}
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/cli/plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAkB,MAAM,WAAW,CAAC;AAKpD,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC1C,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CAC3C;AAED,wBAAgB,oBAAoB,CAAC,EAAE,GAAE,SAAmB,GAAG,OAAO,CAcrE;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAE,SAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CASzF;AAED,wBAAgB,WAAW,IAAI,MAAM,CAEpC"}
package/dist/cli.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  #!/usr/bin/env node
2
- export declare function main(argv?: string[]): Promise<number>;
2
+ import { type PlanCliIO } from './cli/plan';
3
+ export declare function main(argv?: string[], io?: PlanCliIO): Promise<number>;
3
4
  //# sourceMappingURL=cli.d.ts.map
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAIA,wBAAsB,IAAI,CAAC,IAAI,WAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,CAQxE"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAGA,OAAO,EAAwB,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAElE,wBAAsB,IAAI,CAAC,IAAI,WAAwB,EAAE,EAAE,GAAE,SAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBjG"}
package/dist/cli.js CHANGED
@@ -1,6 +1,37 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from "node:module";
3
+ var __create = Object.create;
4
+ var __getProtoOf = Object.getPrototypeOf;
3
5
  var __defProp = Object.defineProperty;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ function __accessProp(key) {
9
+ return this[key];
10
+ }
11
+ var __toESMCache_node;
12
+ var __toESMCache_esm;
13
+ var __toESM = (mod, isNodeMode, target) => {
14
+ var canCache = mod != null && typeof mod === "object";
15
+ if (canCache) {
16
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
17
+ var cached = cache.get(mod);
18
+ if (cached)
19
+ return cached;
20
+ }
21
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
22
+ const to = isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
23
+ if (mod && typeof mod === "object" || typeof mod === "function") {
24
+ for (let key of __getOwnPropNames(mod))
25
+ if (!__hasOwnProp.call(to, key))
26
+ __defProp(to, key, {
27
+ get: __accessProp.bind(mod, key),
28
+ enumerable: true
29
+ });
30
+ }
31
+ if (canCache)
32
+ cache.set(mod, to);
33
+ return to;
34
+ };
4
35
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
5
36
  var __exportCjs = (target, getters, setters) => {
6
37
  for (var name in getters)
@@ -2086,8 +2117,60 @@ Expecting one of '${allowedValues.join("', '")}'`);
2086
2117
  exports.useColor = useColor;
2087
2118
  });
2088
2119
 
2089
- // src/cli.ts
2090
- import { pathToFileURL } from "node:url";
2120
+ // ../../node_modules/mdast-builder/lib/src/index.js
2121
+ var require_src = __commonJS(function(exports) {
2122
+ Object.defineProperty(exports, "__esModule", { value: true });
2123
+ function normalizeChildren(children) {
2124
+ if (Array.isArray(children)) {
2125
+ return children;
2126
+ } else if (typeof children === "function") {
2127
+ const res = children();
2128
+ return normalizeChildren(res);
2129
+ } else if (typeof children === "undefined") {
2130
+ return [];
2131
+ } else {
2132
+ return [children];
2133
+ }
2134
+ }
2135
+ var valueNode = (type, value) => ({
2136
+ type,
2137
+ value
2138
+ });
2139
+ var nodeWithChildren = (type, kids) => ({
2140
+ type,
2141
+ children: normalizeChildren(kids)
2142
+ });
2143
+ exports.text = (value) => valueNode("text", value);
2144
+ exports.inlineCode = (value) => valueNode("inlineCode", value);
2145
+ exports.html = (value) => valueNode("html", value);
2146
+ exports.strong = (kids) => nodeWithChildren("strong", kids);
2147
+ exports.emphasis = (kids) => nodeWithChildren("emphasis", kids);
2148
+ exports.strike = (kids) => nodeWithChildren("delete", kids);
2149
+ exports.tableCell = (kids) => nodeWithChildren("tableCell", kids);
2150
+ exports.tableRow = (kids) => nodeWithChildren("tableRow", kids);
2151
+ exports.table = (align, kids) => Object.assign({}, nodeWithChildren("table", kids), { align });
2152
+ exports.brk = Object.freeze({ type: "break" });
2153
+ exports.separator = exports.text("---");
2154
+ exports.link = (url, title = "", kids) => Object.assign({}, nodeWithChildren("link", kids), {
2155
+ url,
2156
+ title
2157
+ });
2158
+ exports.root = (kids) => nodeWithChildren("root", kids);
2159
+ exports.rootWithTitle = (depth, title, kids) => {
2160
+ return exports.root([exports.heading(depth, title), ...normalizeChildren(kids)]);
2161
+ };
2162
+ exports.paragraph = (kids) => nodeWithChildren("paragraph", kids);
2163
+ exports.image = (url, title, alt, kids) => Object.assign({}, nodeWithChildren("image", kids), { url, title, alt });
2164
+ exports.blockquote = (kids) => nodeWithChildren("blockquote", kids);
2165
+ exports.code = (lang, value) => Object.assign({}, valueNode("code", value), { lang });
2166
+ exports.heading = (depth, kids) => {
2167
+ if (depth < 1)
2168
+ throw new Error(`Invalid depth: ${depth}`);
2169
+ return Object.assign({}, nodeWithChildren("heading", kids), { depth });
2170
+ };
2171
+ exports.list = (ordered, kids) => Object.assign({}, nodeWithChildren("list", kids), { ordered: ordered === "ordered" });
2172
+ exports.listItem = (kids) => nodeWithChildren("listItem", kids);
2173
+ });
2091
2174
 
2092
2175
  // ../../node_modules/commander/index.js
2093
2176
  var exports_commander = {};
@@ -2148,6 +2231,9 @@ var {
2148
2231
  Help: Help2
2149
2232
  } = exports_commander;
2150
2233
 
2234
+ // src/cli.ts
2235
+ import { pathToFileURL } from "node:url";
2236
+
2151
2237
  // src/cli/plan.ts
2152
2238
  import { resolve as resolve4 } from "node:path";
2153
2239
 
@@ -2368,18 +2454,6 @@ async function atomicJson(path, value) {
2368
2454
  function integer(value) {
2369
2455
  return typeof value === "number" && Number.isInteger(value) ? value : undefined;
2370
2456
  }
2371
- // src/plan/escalation.ts
2372
- import { z } from "zod";
2373
- var escalationSchema = z.object({
2374
- planId: z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),
2375
- executionId: z.string().min(1),
2376
- phaseId: z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),
2377
- taskId: z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).optional(),
2378
- blocker: z.string().min(1),
2379
- attempts: z.array(z.string()),
2380
- evidence: z.array(z.string()),
2381
- needsUserDecision: z.boolean()
2382
- }).strict();
2383
2457
  // src/plan/transitions.ts
2384
2458
  var STABLE_ID = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
2385
2459
  function isStableId(value) {
@@ -2399,7 +2473,124 @@ function assertUniqueIds(ids, label) {
2399
2473
  }
2400
2474
  }
2401
2475
 
2476
+ // src/plan/store.ts
2477
+ import { open, mkdir as mkdir3, readdir, readFile as readFile3, realpath as realpath3, rename as rename2, rm as rm2 } from "node:fs/promises";
2478
+ import { basename as basename3, dirname as dirname3, join as join5, resolve as resolve3, sep } from "node:path";
2479
+
2480
+ // src/store.ts
2481
+ import { createHash } from "node:crypto";
2482
+ import { lstat, mkdir as mkdir2, readlink, realpath as realpath2, symlink, unlink } from "node:fs/promises";
2483
+ import { homedir } from "node:os";
2484
+ import { dirname as dirname2, isAbsolute as isAbsolute2, join as join4, resolve as resolve2 } from "node:path";
2485
+
2486
+ // src/extensions/gitx.ts
2487
+ import { realpath } from "node:fs/promises";
2488
+ import { basename as basename2, isAbsolute, join as join3, resolve } from "node:path";
2489
+ async function gitToplevel(cwd) {
2490
+ const result = await run("git", ["-C", cwd, "rev-parse", "--show-toplevel"]);
2491
+ const top = result.stdout.trim();
2492
+ return result.code === 0 && top ? top : resolve(cwd);
2493
+ }
2494
+ async function inspectGitRepository(cwd) {
2495
+ const root = await gitToplevel(cwd);
2496
+ const remoteResult = await run("git", ["-C", root, "remote", "get-url", "origin"]);
2497
+ const remote = remoteResult.code === 0 ? remoteResult.stdout.trim() : "";
2498
+ const commonResult = await run("git", ["-C", root, "rev-parse", "--git-common-dir"]);
2499
+ const common = commonResult.stdout.trim();
2500
+ const commonPath = commonResult.code === 0 && common ? resolve(isAbsolute(common) ? common : join3(root, common)) : root;
2501
+ const commonDir = await canonicalPath(commonPath);
2502
+ return {
2503
+ root,
2504
+ commonDir,
2505
+ ...remote ? { remote } : {},
2506
+ name: remote ? repositoryName(remote) : basename2(resolve(commonDir, "..")) || basename2(root),
2507
+ identity: remote ? `remote:${normalizeRemote(remote)}` : `git-common-dir:${commonDir}`
2508
+ };
2509
+ }
2510
+ function normalizeRemote(remote) {
2511
+ return remote.trim().replace(/\.git\/?$/i, "").replace(/\/+$/, "").toLowerCase();
2512
+ }
2513
+ function repositoryName(remote) {
2514
+ const normalized = remote.trim().replace(/\.git\/?$/i, "").replace(/\/+$/, "");
2515
+ return normalized.split(/[/\\:]/).filter(Boolean).at(-1) ?? "";
2516
+ }
2517
+ async function canonicalPath(path) {
2518
+ try {
2519
+ return await realpath(path);
2520
+ } catch {
2521
+ return resolve(path);
2522
+ }
2523
+ }
2524
+
2525
+ // src/store.ts
2526
+ var STORE_LINK = ".diffpi";
2527
+ var LEGACY_STORE_LINK = join4(".pi", "diffpi");
2528
+ function storeGlobalRoot(homeDir = homedir()) {
2529
+ return join4(homeDir, ".difflab", "diffpi", "projects");
2530
+ }
2531
+ async function ensureStore(cwd, homeDir = homedir()) {
2532
+ const repository = await inspectGitRepository(cwd);
2533
+ const root = repository.root;
2534
+ const slug = projectSlug(repository);
2535
+ const dest = join4(storeGlobalRoot(homeDir), slug);
2536
+ const link = join4(root, STORE_LINK);
2537
+ await mkdir2(dest, { recursive: true });
2538
+ try {
2539
+ await assertStoreLink(link, dest);
2540
+ } catch (error) {
2541
+ if (error.code !== "ENOENT")
2542
+ throw error;
2543
+ await symlink(dest, link);
2544
+ }
2545
+ await removeLegacyStoreLink(join4(root, LEGACY_STORE_LINK), dest);
2546
+ return { slug, root, dest, link, linked: true };
2547
+ }
2548
+ async function plansDir(cwd, homeDir = homedir()) {
2549
+ const store = await ensureStore(cwd, homeDir);
2550
+ const dir = join4(store.link, "plan");
2551
+ await mkdir2(dir, { recursive: true });
2552
+ return dir;
2553
+ }
2554
+ async function assertStoreLink(path, dest) {
2555
+ const entry = await lstat(path);
2556
+ if (!entry.isSymbolicLink())
2557
+ throw new Error(`${path} exists and is not a symlink.`);
2558
+ const target = await symlinkTarget(path);
2559
+ if (target !== await canonicalPath2(dest))
2560
+ throw new Error(`${path} points to ${target}, not ${dest}.`);
2561
+ }
2562
+ async function removeLegacyStoreLink(path, dest) {
2563
+ try {
2564
+ const entry = await lstat(path);
2565
+ if (!entry.isSymbolicLink())
2566
+ return;
2567
+ const target = await symlinkTarget(path);
2568
+ if (target === await canonicalPath2(dest))
2569
+ await unlink(path);
2570
+ } catch (error) {
2571
+ if (error.code !== "ENOENT")
2572
+ throw error;
2573
+ }
2574
+ }
2575
+ async function symlinkTarget(path) {
2576
+ const target = await readlink(path);
2577
+ return canonicalPath2(isAbsolute2(target) ? target : resolve2(dirname2(path), target));
2578
+ }
2579
+ async function canonicalPath2(path) {
2580
+ try {
2581
+ return await realpath2(path);
2582
+ } catch {
2583
+ return resolve2(path);
2584
+ }
2585
+ }
2586
+ function projectSlug(repository) {
2587
+ const readable = repository.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "unnamed";
2588
+ const digest = createHash("sha256").update(repository.identity).digest("hex").slice(0, 12);
2589
+ return `${readable}-${digest}`;
2590
+ }
2591
+
2402
2592
  // src/plan/markdown.ts
2593
+ var import_mdast_builder = __toESM(require_src(), 1);
2403
2594
  var PLAN_MARKER = /<!-- diffpi-plan: (\{[^\n]+\}) -->/;
2404
2595
  var PHASE_MARKER = /<!-- diffpi-phase: (\{[^\n]+\}) -->/g;
2405
2596
  var TASK_MARKER = /<!-- diffpi-task: (\{[^\n]+\}) -->/g;
@@ -2618,121 +2809,6 @@ function parseMarker(value, label) {
2618
2809
  function escapeRegExp(value) {
2619
2810
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2620
2811
  }
2621
- // src/plan/store.ts
2622
- import { open, mkdir as mkdir3, readdir, readFile as readFile3, realpath as realpath3, rename as rename2, rm as rm2 } from "node:fs/promises";
2623
- import { basename as basename3, dirname as dirname3, join as join5, resolve as resolve3, sep } from "node:path";
2624
-
2625
- // src/store.ts
2626
- import { createHash } from "node:crypto";
2627
- import { lstat, mkdir as mkdir2, readlink, realpath as realpath2, symlink, unlink } from "node:fs/promises";
2628
- import { homedir } from "node:os";
2629
- import { dirname as dirname2, isAbsolute as isAbsolute2, join as join4, resolve as resolve2 } from "node:path";
2630
-
2631
- // src/extensions/gitx.ts
2632
- import { realpath } from "node:fs/promises";
2633
- import { basename as basename2, isAbsolute, join as join3, resolve } from "node:path";
2634
- async function gitToplevel(cwd) {
2635
- const result = await run("git", ["-C", cwd, "rev-parse", "--show-toplevel"]);
2636
- const top = result.stdout.trim();
2637
- return result.code === 0 && top ? top : resolve(cwd);
2638
- }
2639
- async function inspectGitRepository(cwd) {
2640
- const root = await gitToplevel(cwd);
2641
- const remoteResult = await run("git", ["-C", root, "remote", "get-url", "origin"]);
2642
- const remote = remoteResult.code === 0 ? remoteResult.stdout.trim() : "";
2643
- const commonResult = await run("git", ["-C", root, "rev-parse", "--git-common-dir"]);
2644
- const common = commonResult.stdout.trim();
2645
- const commonPath = commonResult.code === 0 && common ? resolve(isAbsolute(common) ? common : join3(root, common)) : root;
2646
- const commonDir = await canonicalPath(commonPath);
2647
- return {
2648
- root,
2649
- commonDir,
2650
- ...remote ? { remote } : {},
2651
- name: remote ? repositoryName(remote) : basename2(resolve(commonDir, "..")) || basename2(root),
2652
- identity: remote ? `remote:${normalizeRemote(remote)}` : `git-common-dir:${commonDir}`
2653
- };
2654
- }
2655
- function normalizeRemote(remote) {
2656
- return remote.trim().replace(/\.git\/?$/i, "").replace(/\/+$/, "").toLowerCase();
2657
- }
2658
- function repositoryName(remote) {
2659
- const normalized = remote.trim().replace(/\.git\/?$/i, "").replace(/\/+$/, "");
2660
- return normalized.split(/[/\\:]/).filter(Boolean).at(-1) ?? "";
2661
- }
2662
- async function canonicalPath(path) {
2663
- try {
2664
- return await realpath(path);
2665
- } catch {
2666
- return resolve(path);
2667
- }
2668
- }
2669
-
2670
- // src/store.ts
2671
- var STORE_LINK = ".diffpi";
2672
- var LEGACY_STORE_LINK = join4(".pi", "diffpi");
2673
- function storeGlobalRoot(homeDir = homedir()) {
2674
- return join4(homeDir, ".difflab", "diffpi", "projects");
2675
- }
2676
- async function ensureStore(cwd, homeDir = homedir()) {
2677
- const repository = await inspectGitRepository(cwd);
2678
- const root = repository.root;
2679
- const slug = projectSlug(repository);
2680
- const dest = join4(storeGlobalRoot(homeDir), slug);
2681
- const link = join4(root, STORE_LINK);
2682
- await mkdir2(dest, { recursive: true });
2683
- try {
2684
- await assertStoreLink(link, dest);
2685
- } catch (error) {
2686
- if (error.code !== "ENOENT")
2687
- throw error;
2688
- await symlink(dest, link);
2689
- }
2690
- await removeLegacyStoreLink(join4(root, LEGACY_STORE_LINK), dest);
2691
- return { slug, root, dest, link, linked: true };
2692
- }
2693
- async function plansDir(cwd, homeDir = homedir()) {
2694
- const store = await ensureStore(cwd, homeDir);
2695
- const dir = join4(store.link, "plan");
2696
- await mkdir2(dir, { recursive: true });
2697
- return dir;
2698
- }
2699
- async function assertStoreLink(path, dest) {
2700
- const entry = await lstat(path);
2701
- if (!entry.isSymbolicLink())
2702
- throw new Error(`${path} exists and is not a symlink.`);
2703
- const target = await symlinkTarget(path);
2704
- if (target !== await canonicalPath2(dest))
2705
- throw new Error(`${path} points to ${target}, not ${dest}.`);
2706
- }
2707
- async function removeLegacyStoreLink(path, dest) {
2708
- try {
2709
- const entry = await lstat(path);
2710
- if (!entry.isSymbolicLink())
2711
- return;
2712
- const target = await symlinkTarget(path);
2713
- if (target === await canonicalPath2(dest))
2714
- await unlink(path);
2715
- } catch (error) {
2716
- if (error.code !== "ENOENT")
2717
- throw error;
2718
- }
2719
- }
2720
- async function symlinkTarget(path) {
2721
- const target = await readlink(path);
2722
- return canonicalPath2(isAbsolute2(target) ? target : resolve2(dirname2(path), target));
2723
- }
2724
- async function canonicalPath2(path) {
2725
- try {
2726
- return await realpath2(path);
2727
- } catch {
2728
- return resolve2(path);
2729
- }
2730
- }
2731
- function projectSlug(repository) {
2732
- const readable = repository.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "unnamed";
2733
- const digest = createHash("sha256").update(repository.identity).digest("hex").slice(0, 12);
2734
- return `${readable}-${digest}`;
2735
- }
2736
2812
 
2737
2813
  // src/plan/store.ts
2738
2814
  async function resolvePlan(cwd, query, filters = {}, options = {}) {
@@ -2767,7 +2843,15 @@ async function readRecord(dir) {
2767
2843
  const logPath = join5(dir, "logs.txt");
2768
2844
  const source = await readFile3(planPath, "utf8");
2769
2845
  const document = parsePlanDocument(source, planPath);
2770
- return { id: basename3(dir), dir, planPath, logPath, document, source };
2846
+ return {
2847
+ id: basename3(dir),
2848
+ dir,
2849
+ planPath,
2850
+ logPath,
2851
+ implementationDir: join5(dir, "implementation"),
2852
+ document,
2853
+ source
2854
+ };
2771
2855
  }
2772
2856
  async function assertContained(root, candidate) {
2773
2857
  const canonicalRoot = await realpath3(root);
@@ -2790,22 +2874,27 @@ function normalizeQuery(value) {
2790
2874
  function stripDate(value) {
2791
2875
  return value.replace(/^\d{6}-/, "");
2792
2876
  }
2877
+ // src/plan/escalation.ts
2878
+ import { z } from "zod";
2879
+ var escalationSchema = z.object({
2880
+ planId: z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),
2881
+ executionId: z.string().min(1),
2882
+ phaseId: z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),
2883
+ taskId: z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).optional(),
2884
+ blocker: z.string().min(1),
2885
+ attempts: z.array(z.string()),
2886
+ evidence: z.array(z.string()),
2887
+ needsUserDecision: z.boolean()
2888
+ }).strict();
2793
2889
  // src/cli/plan.ts
2794
- async function runPlanCli(args, io = process) {
2795
- const program = new Command2().name("diffpi plan").description("Plan annotation commands").showHelpAfterError().exitOverride().configureOutput({
2890
+ function createPlanCliCommand(io = process) {
2891
+ const program = new Command2().name("plan").description("Plan annotation commands").showHelpAfterError().exitOverride().configureOutput({
2796
2892
  writeOut: (message) => io.stdout.write(message),
2797
2893
  writeErr: (message) => io.stderr.write(message)
2798
2894
  });
2799
2895
  addAnnotationCommand(program, "annotate", io);
2800
2896
  addAnnotationCommand(program, "annotations", io);
2801
- try {
2802
- await program.parseAsync(["node", "diffpi plan", ...args]);
2803
- return 0;
2804
- } catch (error) {
2805
- if (error instanceof CommanderError2)
2806
- return error.exitCode;
2807
- throw error;
2808
- }
2897
+ return program;
2809
2898
  }
2810
2899
  function addAnnotationCommand(program, verb, io) {
2811
2900
  program.command(`${verb} [plan]`).description(verb === "annotate" ? "Open a plan in tuicr for annotation" : "Print plan annotations as JSON").option("--cwd <path>", "Repository working directory", process.cwd()).action(async (query, options) => {
@@ -2830,16 +2919,20 @@ async function resolveCliPlan(cwd, query) {
2830
2919
  }
2831
2920
 
2832
2921
  // src/cli.ts
2833
- async function main(argv = process.argv.slice(2)) {
2834
- const [command, ...args] = argv;
2835
- if (command === "--help" || command === "-h" || !command) {
2836
- process.stdout.write(`Usage: diffpi plan <annotate|annotations> [options]
2837
- `);
2922
+ async function main(argv = process.argv.slice(2), io = process) {
2923
+ const program = new Command2().name("diffpi").description("Diffpi command-line tools").showHelpAfterError().exitOverride().configureOutput({
2924
+ writeOut: (message) => io.stdout.write(message),
2925
+ writeErr: (message) => io.stderr.write(message)
2926
+ });
2927
+ program.addCommand(createPlanCliCommand(io));
2928
+ try {
2929
+ await program.parseAsync(["node", "diffpi", ...argv]);
2838
2930
  return 0;
2931
+ } catch (error) {
2932
+ if (error instanceof CommanderError2)
2933
+ return error.exitCode;
2934
+ throw error;
2839
2935
  }
2840
- if (command !== "plan")
2841
- throw new Error(`Unknown command: ${command}.`);
2842
- return runPlanCli(args);
2843
2936
  }
2844
2937
  if (import.meta.url === pathToFileURL(process.argv[1] ?? "").href) {
2845
2938
  main().then((code) => {
@@ -24,6 +24,7 @@ export interface LaunchBackgroundPiOptions {
24
24
  prompt: string;
25
25
  packetPath?: string;
26
26
  }
27
+ /** Delegate scheduling to pi-background-tasks through its `/bg --agent` command. */
27
28
  export declare function launchBackgroundPi(pi: Pick<ExtensionAPI, 'sendUserMessage'>, options: LaunchBackgroundPiOptions): Promise<{
28
29
  name: string;
29
30
  command: string;
@@ -1 +1 @@
1
- {"version":3,"file":"background.d.ts","sourceRoot":"","sources":["../../src/commands/background.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAKpE,MAAM,WAAW,sBAAsB;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,iBAAiB,CAAC,EACzC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,IAAI,CAAA;CAAE,CAAC,CA0B1D;AAED,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,IAAI,CAAC,uBAAuB,EAAE,SAAS,GAAG,WAAW,CAAC,EAC/D,MAAM,GAAE,sBAA2B,GAClC,OAAO,CAAC,MAAM,CAAC,CAajB;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,SAAS,OAAO,EAAE,EAC3B,WAAW,SAAK,EAChB,QAAQ,SAAY,GACnB,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAmBrD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAE5D"}
1
+ {"version":3,"file":"background.d.ts","sourceRoot":"","sources":["../../src/commands/background.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAKpE,MAAM,WAAW,sBAAsB;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,oFAAoF;AACpF,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,iBAAiB,CAAC,EACzC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,IAAI,CAAA;CAAE,CAAC,CA0B1D;AAED,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,IAAI,CAAC,uBAAuB,EAAE,SAAS,GAAG,WAAW,CAAC,EAC/D,MAAM,GAAE,sBAA2B,GAClC,OAAO,CAAC,MAAM,CAAC,CAajB;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,SAAS,OAAO,EAAE,EAC3B,WAAW,SAAK,EAChB,QAAQ,SAAY,GACnB,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAmBrD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAE5D"}