@difflab/pi 0.7.1 → 0.7.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 (56) hide show
  1. package/README.md +22 -40
  2. package/agents/diffpi-copilot.md +2 -2
  3. package/agents/diffpi-orchestrator.md +9 -14
  4. package/agents/diffpi-plan-reviewer.md +4 -12
  5. package/agents/diffpi-planner.md +6 -12
  6. package/agents/diffpi-reviewer.md +6 -10
  7. package/agents/diffpi-tutor.md +2 -2
  8. package/agents/diffpi-worker.md +3 -6
  9. package/dist/commands/dispatch.d.ts +4 -0
  10. package/dist/commands/dispatch.d.ts.map +1 -0
  11. package/dist/commands/index.d.ts +1 -3
  12. package/dist/commands/index.d.ts.map +1 -1
  13. package/dist/commands/plan.d.ts +1 -1
  14. package/dist/commands/plan.d.ts.map +1 -1
  15. package/dist/commands/review.d.ts +1 -1
  16. package/dist/commands/review.d.ts.map +1 -1
  17. package/dist/extensions/index.js +365 -881
  18. package/dist/index.d.ts +0 -2
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +40 -403
  21. package/dist/tools/index.d.ts +1 -3
  22. package/dist/tools/index.d.ts.map +1 -1
  23. package/dist/tools/index.js +95 -212
  24. package/package.json +2 -2
  25. package/skills/diffpi-setup/SKILL.md +1 -1
  26. package/skills/plan/SKILL.md +12 -22
  27. package/skills/plan/references/design-quality.md +3 -3
  28. package/skills/plan/references/workflows/annotate.md +9 -3
  29. package/skills/plan/references/workflows/finalize.md +10 -6
  30. package/skills/plan/references/workflows/go.md +25 -7
  31. package/skills/plan/references/workflows/help.md +20 -3
  32. package/skills/plan/references/workflows/init.md +23 -6
  33. package/skills/plan/references/workflows/inline-fallback.md +9 -0
  34. package/skills/plan/references/workflows/new.md +22 -7
  35. package/skills/plan/references/workflows/update.md +22 -6
  36. package/skills/plan/references/workflows/validate.md +31 -0
  37. package/skills/review/SKILL.md +14 -6
  38. package/skills/review/references/workflows/address.md +19 -6
  39. package/skills/review/references/workflows/auto.md +21 -5
  40. package/skills/review/references/workflows/complete.md +17 -4
  41. package/skills/review/references/workflows/edit.md +8 -2
  42. package/skills/review/references/workflows/foreground-fallback.md +7 -0
  43. package/skills/review/references/workflows/help.md +22 -13
  44. package/skills/review/references/workflows/merge.md +17 -2
  45. package/skills/review/references/workflows/new.md +17 -5
  46. package/skills/review/references/workflows/open.md +8 -2
  47. package/skills/review/references/workflows/publish.md +17 -4
  48. package/skills/review/references/workflows/status.md +7 -2
  49. package/templates/plan/PLAN.md +1 -1
  50. package/dist/commands/mode.d.ts +0 -5
  51. package/dist/commands/mode.d.ts.map +0 -1
  52. package/dist/modes.d.ts +0 -75
  53. package/dist/modes.d.ts.map +0 -1
  54. package/dist/tools/modes.d.ts +0 -4
  55. package/dist/tools/modes.d.ts.map +0 -1
  56. package/skills/mode/SKILL.md +0 -38
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAY/C,OAAO,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAIjD,wBAAgB,aAAa,CAC3B,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,GAAG,iBAAiB,CAAC,EACpD,KAAK,EAAE,cAAc,GACpB,SAAS,cAAc,EAAE,CAY3B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAWpF,OAAO,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAIjD,wBAAgB,aAAa,CAAC,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,GAAG,iBAAiB,CAAC,GAAG,SAAS,cAAc,EAAE,CAW7G"}
@@ -1083,127 +1083,12 @@ function createDiffpiReloadTool(pi) {
1083
1083
  });
1084
1084
  }
1085
1085
 
1086
- // src/tools/modes.ts
1087
- import { defineTool as defineTool5 } from "@earendil-works/pi-coding-agent";
1088
- import { z as z6 } from "zod";
1089
- var emptyParametersSchema = z6.object({});
1090
- var emptyParameters = z6.toJSONSchema(emptyParametersSchema, { io: "input" });
1091
- var listParametersSchema = z6.object({
1092
- includeSkills: z6.boolean().optional().describe("Include skill-owned agents using skill:agent ids.")
1093
- });
1094
- var listParameters = z6.toJSONSchema(listParametersSchema, { io: "input" });
1095
- var setParametersSchema = z6.object({
1096
- agent: zx.text.describe("Inline agent id from diffpi_modes_list.")
1097
- });
1098
- var setParameters = z6.toJSONSchema(setParametersSchema, { io: "input" });
1099
- function createModeTools(controller) {
1100
- return [
1101
- defineTool5({
1102
- name: "diffpi_modes_status",
1103
- label: "diffpi modes status",
1104
- description: "Report the actual runtime model, thinking level, and active tools for capability inspection.",
1105
- promptSnippet: "Inspect actual post-compaction inline mode capabilities before claiming them.",
1106
- parameters: emptyParameters,
1107
- executionMode: "parallel",
1108
- async execute(_toolCallId, input, _signal, _onUpdate, ctx) {
1109
- emptyParametersSchema.parse(input);
1110
- const status = controller.getStatus(ctx);
1111
- return {
1112
- content: [{ type: "text", text: JSON.stringify(status) }],
1113
- details: status
1114
- };
1115
- }
1116
- }),
1117
- defineTool5({
1118
- name: "diffpi_modes_list",
1119
- label: "diffpi modes list",
1120
- description: "List inline agents shared with the subagent plugin, optionally including skill-owned agents.",
1121
- promptSnippet: "List inline agents before selecting one when the requested agent is unclear",
1122
- promptGuidelines: [
1123
- "Call diffpi_modes_list when the user asks which inline agents are available.",
1124
- "Set includeSkills to true only when the user asks for skill agents or runs /skill:mode --include-skills.",
1125
- "Inline mode applies the profile prompt, first available preferred model, thinking level, and available tools."
1126
- ],
1127
- parameters: listParameters,
1128
- executionMode: "parallel",
1129
- async execute(_toolCallId, input, _signal, _onUpdate, ctx) {
1130
- const params = listParametersSchema.parse(input);
1131
- const catalog = await controller.list(ctx, { includeSkills: params.includeSkills });
1132
- return {
1133
- content: [{ type: "text", text: formatCatalog(catalog, controller.getActive()?.id) }],
1134
- details: { active: controller.getActive()?.id, catalog }
1135
- };
1136
- }
1137
- }),
1138
- defineTool5({
1139
- name: "diffpi_modes_set",
1140
- label: "diffpi modes set",
1141
- description: "Set a validated available agent as the inline behavioral agent for subsequent chat turns.",
1142
- promptSnippet: "Set the inline behavioral agent only after the user chooses one",
1143
- promptGuidelines: [
1144
- "Call diffpi_modes_set only after the user explicitly selects an agent.",
1145
- "Use the exact skill:agent id for a skill-owned agent.",
1146
- "The selected prompt takes effect on the next model turn."
1147
- ],
1148
- parameters: setParameters,
1149
- executionMode: "sequential",
1150
- async execute(_toolCallId, input, _signal, _onUpdate, ctx) {
1151
- const params = setParametersSchema.parse(input);
1152
- const result = await controller.set(params.agent, ctx);
1153
- if (!result.ok)
1154
- throw new Error(result.message);
1155
- return {
1156
- content: [{ type: "text", text: `${result.message} The prompt takes effect on the next turn.` }],
1157
- details: { active: result.active }
1158
- };
1159
- }
1160
- }),
1161
- defineTool5({
1162
- name: "diffpi_modes_unset",
1163
- label: "diffpi modes unset",
1164
- description: "Clear the inline behavioral agent and restore default Pi prompting for subsequent turns.",
1165
- promptSnippet: "Clear the inline agent when the user asks for default behavior",
1166
- promptGuidelines: [
1167
- "Call diffpi_modes_unset only when the user explicitly asks to clear the active inline agent."
1168
- ],
1169
- parameters: emptyParameters,
1170
- executionMode: "sequential",
1171
- async execute(_toolCallId, input, _signal, _onUpdate, ctx) {
1172
- emptyParametersSchema.parse(input);
1173
- const result = await controller.unset(ctx);
1174
- return {
1175
- content: [{ type: "text", text: result.message }],
1176
- details: { active: controller.getActive()?.id }
1177
- };
1178
- }
1179
- })
1180
- ];
1181
- }
1182
- function formatCatalog(catalog, active) {
1183
- const lines = [`Active inline agent: ${active ?? "default"}.`, "", "Available inline agents:"];
1184
- for (const mode of catalog.modes) {
1185
- const runtime = [mode.modelPreferences[0], mode.thinkingLevel].filter(Boolean).join(", ");
1186
- lines.push(`- ${mode.id} [${mode.promptStrategy}${runtime ? `; ${runtime}` : ""}] — ${sanitize(mode.description)} (${mode.source})`);
1187
- }
1188
- if (catalog.diagnostics.length > 0) {
1189
- lines.push("", "Skipped agent files:");
1190
- for (const diagnostic of catalog.diagnostics)
1191
- lines.push(`- ${sanitize(diagnostic)}`);
1192
- }
1193
- lines.push("", "Inline mode applies the profile prompt, preferred available model, thinking level, and tool set.");
1194
- return lines.join(`
1195
- `);
1196
- }
1197
- function sanitize(value) {
1198
- return value.replace(/[\r\n\t]+/g, " ").replace(/\s+/g, " ").trim();
1199
- }
1200
-
1201
1086
  // src/tools/review.ts
1202
1087
  import { existsSync as existsSync2 } from "node:fs";
1203
1088
  import { mkdir as mkdir4, readdir as readdir2, readFile as readFile10, rename as rename2, stat as stat2, unlink as unlink2, writeFile as writeFile5 } from "node:fs/promises";
1204
1089
  import { join as join12 } from "node:path";
1205
- import { defineTool as defineTool6 } from "@earendil-works/pi-coding-agent";
1206
- import { z as z10 } from "zod";
1090
+ import { defineTool as defineTool5 } from "@earendil-works/pi-coding-agent";
1091
+ import { z as z9 } from "zod";
1207
1092
 
1208
1093
  // src/extensions/misex.ts
1209
1094
  import { mkdir as mkdir3, readFile as readFile5, writeFile as writeFile2 } from "node:fs/promises";
@@ -1436,16 +1321,16 @@ async function discoverMiseTasks(cwd) {
1436
1321
  }
1437
1322
 
1438
1323
  // src/review/types.ts
1439
- import { z as z7 } from "zod";
1440
- var severitySchema = z7.enum(["BLOCKING", "CONSIDER", "NOTE"]);
1441
- var findingSchema = z7.object({
1442
- file: z7.string().min(1),
1443
- line: z7.number().int().nonnegative(),
1324
+ import { z as z6 } from "zod";
1325
+ var severitySchema = z6.enum(["BLOCKING", "CONSIDER", "NOTE"]);
1326
+ var findingSchema = z6.object({
1327
+ file: z6.string().min(1),
1328
+ line: z6.number().int().nonnegative(),
1444
1329
  severity: severitySchema,
1445
- body: z7.string().min(1),
1446
- reference: z7.string().optional().default("")
1330
+ body: z6.string().min(1),
1331
+ reference: z6.string().optional().default("")
1447
1332
  });
1448
- var findingsSchema = z7.array(findingSchema);
1333
+ var findingsSchema = z6.array(findingSchema);
1449
1334
  function reviewSlug(input) {
1450
1335
  return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 50);
1451
1336
  }
@@ -1518,17 +1403,17 @@ function renderCommentBody(finding) {
1518
1403
  return `${prefix}${finding.body}${reference}`;
1519
1404
  }
1520
1405
  // src/review/review-markdown.ts
1521
- import { z as z8 } from "zod";
1522
- var reviewThreadRecordSchema = z8.object({
1523
- id: z8.string().min(1),
1524
- file: z8.string().nullable().optional().transform((value) => value ?? undefined),
1525
- line: z8.number().int().positive().nullable().optional().transform((value) => value ?? undefined),
1526
- body: z8.string(),
1527
- author: z8.string().optional(),
1528
- resolved: z8.boolean(),
1529
- addressed: z8.boolean().optional(),
1530
- question: z8.boolean(),
1531
- replies: z8.array(z8.string()).optional()
1406
+ import { z as z7 } from "zod";
1407
+ var reviewThreadRecordSchema = z7.object({
1408
+ id: z7.string().min(1),
1409
+ file: z7.string().nullable().optional().transform((value) => value ?? undefined),
1410
+ line: z7.number().int().positive().nullable().optional().transform((value) => value ?? undefined),
1411
+ body: z7.string(),
1412
+ author: z7.string().optional(),
1413
+ resolved: z7.boolean(),
1414
+ addressed: z7.boolean().optional(),
1415
+ question: z7.boolean(),
1416
+ replies: z7.array(z7.string()).optional()
1532
1417
  });
1533
1418
  function renderReviewDoc(input) {
1534
1419
  const anchored = dedupeFindings(input.findings).filter((finding) => finding.line > 0);
@@ -1615,7 +1500,7 @@ function parseThreadArtifact(content) {
1615
1500
  let threads;
1616
1501
  try {
1617
1502
  const decoded = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
1618
- threads = z8.array(reviewThreadRecordSchema).parse(decoded);
1503
+ threads = z7.array(reviewThreadRecordSchema).parse(decoded);
1619
1504
  } catch {
1620
1505
  throw new Error("Cannot parse the Diffpi thread artifact payload.");
1621
1506
  }
@@ -2286,14 +2171,14 @@ function createLocalReviewBackend(options) {
2286
2171
  import { createHash as createHash2 } from "node:crypto";
2287
2172
  import { readFile as readFile8, rename, writeFile as writeFile4 } from "node:fs/promises";
2288
2173
  import { join as join10 } from "node:path";
2289
- import { z as z9 } from "zod";
2290
- var reviewPublicationStateSchema = z9.object({
2291
- target: z9.string().optional(),
2292
- bodies: z9.array(z9.string()).default([]),
2293
- comments: z9.array(z9.string()).default([]),
2294
- stagedComments: z9.array(z9.string()).default([]),
2295
- replies: z9.array(z9.string()).default([]),
2296
- overlayPath: z9.string().optional()
2174
+ import { z as z8 } from "zod";
2175
+ var reviewPublicationStateSchema = z8.object({
2176
+ target: z8.string().optional(),
2177
+ bodies: z8.array(z8.string()).default([]),
2178
+ comments: z8.array(z8.string()).default([]),
2179
+ stagedComments: z8.array(z8.string()).default([]),
2180
+ replies: z8.array(z8.string()).default([]),
2181
+ overlayPath: z8.string().optional()
2297
2182
  });
2298
2183
  function reviewBodyFingerprint(body) {
2299
2184
  return digest(body);
@@ -2317,7 +2202,7 @@ async function loadReviewPublicationState(cwd, vcs, number, homeDir) {
2317
2202
  if (error.code === "ENOENT") {
2318
2203
  return { path, state: { target, bodies: [], comments: [], stagedComments: [], replies: [] } };
2319
2204
  }
2320
- if (error instanceof SyntaxError || error instanceof z9.ZodError) {
2205
+ if (error instanceof SyntaxError || error instanceof z8.ZodError) {
2321
2206
  throw new Error(`Cannot parse review publication state: ${path}`);
2322
2207
  }
2323
2208
  throw error;
@@ -2369,41 +2254,41 @@ async function readOptionalFile(path) {
2369
2254
  }
2370
2255
 
2371
2256
  // src/tools/review.ts
2372
- var contextSchema = z10.object({
2373
- cwd: z10.string().optional(),
2374
- target: z10.string().optional(),
2375
- workingTree: z10.boolean().optional()
2257
+ var contextSchema = z9.object({
2258
+ cwd: z9.string().optional(),
2259
+ target: z9.string().optional(),
2260
+ workingTree: z9.boolean().optional()
2376
2261
  });
2377
- var localSchema = contextSchema.extend({ local: z10.boolean().optional() });
2262
+ var localSchema = contextSchema.extend({ local: z9.boolean().optional() });
2378
2263
  var openSchema = localSchema.extend({
2379
- title: z10.string().optional(),
2380
- intent: z10.string().optional(),
2381
- issueUrl: z10.string().url().optional(),
2382
- base: z10.string().optional()
2264
+ title: z9.string().optional(),
2265
+ intent: z9.string().optional(),
2266
+ issueUrl: z9.string().url().optional(),
2267
+ base: z9.string().optional()
2383
2268
  });
2384
2269
  var submitSchema = localSchema.extend({
2385
2270
  findings: findingsSchema,
2386
- overallIssues: z10.array(z10.string()).optional(),
2387
- notVerified: z10.array(z10.string()).optional(),
2388
- title: z10.string().optional()
2271
+ overallIssues: z9.array(z9.string()).optional(),
2272
+ notVerified: z9.array(z9.string()).optional(),
2273
+ title: z9.string().optional()
2389
2274
  });
2390
2275
  var addCommentSchema = localSchema.extend({
2391
- body: z10.string().min(1),
2392
- file: z10.string().min(1),
2393
- line: z10.number().int().positive(),
2394
- side: z10.enum(["LEFT", "RIGHT"]).optional()
2276
+ body: z9.string().min(1),
2277
+ file: z9.string().min(1),
2278
+ line: z9.number().int().positive(),
2279
+ side: z9.enum(["LEFT", "RIGHT"]).optional()
2395
2280
  });
2396
2281
  var respondSchema = localSchema.extend({
2397
- threadId: z10.string().min(1),
2398
- body: z10.string().min(1),
2399
- question: z10.boolean().optional(),
2400
- resolve: z10.boolean().optional()
2282
+ threadId: z9.string().min(1),
2283
+ body: z9.string().min(1),
2284
+ question: z9.boolean().optional(),
2285
+ resolve: z9.boolean().optional()
2401
2286
  });
2402
2287
  var publishSchema = localSchema.extend({
2403
- status: z10.enum(["COMMENT", "APPROVE", "REQUEST_CHANGES", "CLOSE"]).optional()
2288
+ status: z9.enum(["COMMENT", "APPROVE", "REQUEST_CHANGES", "CLOSE"]).optional()
2404
2289
  });
2405
2290
  var completeSchema = localSchema.extend({
2406
- action: z10.enum(["approve", "reject", "abandon"]).optional()
2291
+ action: z9.enum(["approve", "reject", "abandon"]).optional()
2407
2292
  });
2408
2293
  function hasReviewDraft(comments, body) {
2409
2294
  return comments.length > 0 || body.trim().length > 0;
@@ -2477,7 +2362,7 @@ async function workingTreeDiff(cwd) {
2477
2362
  }
2478
2363
  function createReviewTools() {
2479
2364
  return [
2480
- defineTool6({
2365
+ defineTool5({
2481
2366
  name: "review_context",
2482
2367
  label: "review context",
2483
2368
  description: "Orient to the target, backend, forge, environment, shared store, PR/MR, and tuicr session.",
@@ -2516,7 +2401,7 @@ function createReviewTools() {
2516
2401
  });
2517
2402
  }
2518
2403
  }),
2519
- defineTool6({
2404
+ defineTool5({
2520
2405
  name: "review_status",
2521
2406
  label: "review status",
2522
2407
  description: "Report local and remote review lifecycle status without requiring a forge or tuicr.",
@@ -2531,7 +2416,7 @@ function createReviewTools() {
2531
2416
  return result2(status.text, status.details);
2532
2417
  }
2533
2418
  }),
2534
- defineTool6({
2419
+ defineTool5({
2535
2420
  name: "review_new",
2536
2421
  label: "review new",
2537
2422
  description: "Create a new local tuicr review or a remote draft PR/MR and open it in tuicr.",
@@ -2574,7 +2459,7 @@ ${openMessage}`, {
2574
2459
  });
2575
2460
  }
2576
2461
  }),
2577
- defineTool6({
2462
+ defineTool5({
2578
2463
  name: "review_open",
2579
2464
  label: "review open",
2580
2465
  description: "Open an existing remote PR/MR in the system browser; never creates one.",
@@ -2599,7 +2484,7 @@ ${openMessage}`, {
2599
2484
  });
2600
2485
  }
2601
2486
  }),
2602
- defineTool6({
2487
+ defineTool5({
2603
2488
  name: "review_edit",
2604
2489
  label: "review edit",
2605
2490
  description: "Open an existing local tuicr session or remote PR/MR in tuicr without generating findings.",
@@ -2623,7 +2508,7 @@ ${openMessage}`, {
2623
2508
  return launchLocalReview(review, false);
2624
2509
  }
2625
2510
  }),
2626
- defineTool6({
2511
+ defineTool5({
2627
2512
  name: "review_diff",
2628
2513
  label: "review diff",
2629
2514
  description: "Fetch the target PR/MR diff or auto-detected local working-tree diff.",
@@ -2646,7 +2531,7 @@ ${openMessage}`, {
2646
2531
  return result2(diff || "Empty diff.", { diff, pr: review.pr });
2647
2532
  }
2648
2533
  }),
2649
- defineTool6({
2534
+ defineTool5({
2650
2535
  name: "review_gates",
2651
2536
  label: "review gates",
2652
2537
  description: "Run format, lint, test, conventional-subject, and available CI checks.",
@@ -2676,7 +2561,7 @@ ${openMessage}`, {
2676
2561
  });
2677
2562
  }
2678
2563
  }),
2679
- defineTool6({
2564
+ defineTool5({
2680
2565
  name: "review_submit",
2681
2566
  label: "review submit",
2682
2567
  description: "Write the review artifact and stage comments in the selected local or remote backend.",
@@ -2739,7 +2624,7 @@ ${openMessage}`, {
2739
2624
  });
2740
2625
  }
2741
2626
  }),
2742
- defineTool6({
2627
+ defineTool5({
2743
2628
  name: "review_add_comment",
2744
2629
  label: "review add comment",
2745
2630
  description: "Add one provenance-marked comment through tuicr or the remote pending-review backend.",
@@ -2778,7 +2663,7 @@ ${openMessage}`, {
2778
2663
  return result2(`Draft comment added to #${review.pr.number}.`, { pr: review.pr, comment });
2779
2664
  }
2780
2665
  }),
2781
- defineTool6({
2666
+ defineTool5({
2782
2667
  name: "review_comments",
2783
2668
  label: "review comments",
2784
2669
  description: "Pull review threads or local tuicr comments and write a target-named artifact.",
@@ -2809,7 +2694,7 @@ ${openMessage}`, {
2809
2694
  `) || "No comments.", { artifact, threads });
2810
2695
  }
2811
2696
  }),
2812
- defineTool6({
2697
+ defineTool5({
2813
2698
  name: "review_respond",
2814
2699
  label: "review respond",
2815
2700
  description: "Post local question replies to tuicr and record their publish overlay, or reply to remote threads.",
@@ -2870,7 +2755,7 @@ ${params.body}`, {
2870
2755
  });
2871
2756
  }
2872
2757
  }),
2873
- defineTool6({
2758
+ defineTool5({
2874
2759
  name: "review_publish",
2875
2760
  label: "review publish",
2876
2761
  description: "Publish pending remote draft PR/MR review comments and status, or promote a local tuicr draft before publishing.",
@@ -2886,7 +2771,7 @@ ${params.body}`, {
2886
2771
  return publishResolvedReview(review, params, modelRoute(ctx));
2887
2772
  }
2888
2773
  }),
2889
- defineTool6({
2774
+ defineTool5({
2890
2775
  name: "review_complete",
2891
2776
  label: "review complete",
2892
2777
  description: "Approve, reject, or abandon a remote review, or archive a local review artifact.",
@@ -2920,7 +2805,7 @@ ${params.body}`, {
2920
2805
  return publishResolvedReview(review, { ...params, status }, modelRoute(ctx));
2921
2806
  }
2922
2807
  }),
2923
- defineTool6({
2808
+ defineTool5({
2924
2809
  name: "review_merge",
2925
2810
  label: "review merge",
2926
2811
  description: "Squash-merge an open, ready GitHub PR through gh after checking its conventional subject.",
@@ -2929,10 +2814,10 @@ ${params.body}`, {
2929
2814
  "Do not query GitHub through MCP or duplicate readiness checks before calling review_merge.",
2930
2815
  "This is intentionally GitHub-only until GitLab merge support is added."
2931
2816
  ],
2932
- parameters: parameters(contextSchema.extend({ subject: z10.string().optional() })),
2817
+ parameters: parameters(contextSchema.extend({ subject: z9.string().optional() })),
2933
2818
  executionMode: "sequential",
2934
2819
  async execute(_id, input) {
2935
- const params = contextSchema.extend({ subject: z10.string().optional() }).parse(input);
2820
+ const params = contextSchema.extend({ subject: z9.string().optional() }).parse(input);
2936
2821
  const review = await resolveReviewContext(resolveWorkingDirectory(params), params.target);
2937
2822
  if (review.vcs.provider !== "github" || !review.forge)
2938
2823
  return result2("review_merge currently supports GitHub only.");
@@ -2946,7 +2831,7 @@ ${params.body}`, {
2946
2831
  return result2(`Merged #${review.pr.number} with subject: ${subject}.`, { pr: review.pr, guard });
2947
2832
  }
2948
2833
  }),
2949
- defineTool6({
2834
+ defineTool5({
2950
2835
  name: "review_launch_ui",
2951
2836
  label: "review launch UI",
2952
2837
  description: "Open a tuicr UI in a mux tab, configure Zed, or return the command to run.",
@@ -2990,7 +2875,7 @@ async function syncLocalThreadArtifact(path, title, sessionSlug, threads) {
2990
2875
  return merged;
2991
2876
  }
2992
2877
  function parameters(schema) {
2993
- return z10.toJSONSchema(schema, { io: "input" });
2878
+ return z9.toJSONSchema(schema, { io: "input" });
2994
2879
  }
2995
2880
  function resolveWorkingDirectory(params) {
2996
2881
  return params.cwd ?? process.cwd();
@@ -3348,8 +3233,8 @@ function artifactNameMatches(name, suffix) {
3348
3233
  }
3349
3234
 
3350
3235
  // src/tools/setup.ts
3351
- import { defineTool as defineTool7 } from "@earendil-works/pi-coding-agent";
3352
- import { z as z12 } from "zod";
3236
+ import { defineTool as defineTool6 } from "@earendil-works/pi-coding-agent";
3237
+ import { z as z11 } from "zod";
3353
3238
 
3354
3239
  // src/setup.ts
3355
3240
  import { parseFrontmatter as parseFrontmatter2 } from "@earendil-works/pi-coding-agent";
@@ -3359,7 +3244,7 @@ import { basename as basename5, join as join16 } from "node:path";
3359
3244
 
3360
3245
  // src/config.ts
3361
3246
  import { parseFrontmatter } from "@earendil-works/pi-coding-agent";
3362
- import { z as z11 } from "zod";
3247
+ import { z as z10 } from "zod";
3363
3248
  import { homedir as homedir5 } from "node:os";
3364
3249
  import { join as join13 } from "node:path";
3365
3250
 
@@ -3380,11 +3265,11 @@ function isMissingPath(error) {
3380
3265
 
3381
3266
  // src/config.ts
3382
3267
  var modelReferenceSchema = zx.text;
3383
- var agentConfigSchema = z11.object({
3384
- models: z11.array(modelReferenceSchema).optional()
3268
+ var agentConfigSchema = z10.object({
3269
+ models: z10.array(modelReferenceSchema).optional()
3385
3270
  }).strict();
3386
- var diffpiConfigSchema = z11.object({
3387
- agents: z11.record(z11.string(), agentConfigSchema).optional()
3271
+ var diffpiConfigSchema = z10.object({
3272
+ agents: z10.record(z10.string(), agentConfigSchema).optional()
3388
3273
  }).strict();
3389
3274
  function diffpiConfigPaths(homeDir = homedir5()) {
3390
3275
  const directory = join13(homeDir, ".difflab", "diffpi");
@@ -3923,14 +3808,14 @@ function getRecord(value) {
3923
3808
  }
3924
3809
 
3925
3810
  // src/tools/setup.ts
3926
- var setupParametersSchema = z12.object({
3927
- issueTracker: z12.enum(["none", "linear", "jira"]).default("none").describe("Issue tracker MCP server to configure. Use none unless the user explicitly selects Linear or Jira."),
3928
- forges: z12.array(z12.enum(["github", "gitlab"])).default([]).describe("Hosted VCS MCP servers to configure. Installs matching CLIs and registers each MCP server."),
3929
- forge: z12.enum(["none", "github", "gitlab"]).optional().describe("Deprecated single-host alias. Prefer forges for one or more VCS MCP servers."),
3930
- bindZedKey: z12.boolean().default(false).describe("Opt in to a Zed keybinding for the tuicr review task.")
3811
+ var setupParametersSchema = z11.object({
3812
+ issueTracker: z11.enum(["none", "linear", "jira"]).default("none").describe("Issue tracker MCP server to configure. Use none unless the user explicitly selects Linear or Jira."),
3813
+ forges: z11.array(z11.enum(["github", "gitlab"])).default([]).describe("Hosted VCS MCP servers to configure. Installs matching CLIs and registers each MCP server."),
3814
+ forge: z11.enum(["none", "github", "gitlab"]).optional().describe("Deprecated single-host alias. Prefer forges for one or more VCS MCP servers."),
3815
+ bindZedKey: z11.boolean().default(false).describe("Opt in to a Zed keybinding for the tuicr review task.")
3931
3816
  });
3932
- var setupParameters = z12.toJSONSchema(setupParametersSchema, { io: "input" });
3933
- var diffpiSetupTool = defineTool7({
3817
+ var setupParameters = z11.toJSONSchema(setupParametersSchema, { io: "input" });
3818
+ var diffpiSetupTool = defineTool6({
3934
3819
  name: "diffpi_setup",
3935
3820
  label: "diffpi setup",
3936
3821
  description: "Install or repair the @difflab/pi environment. This mutates user-level tool installations and configuration files.",
@@ -3959,7 +3844,7 @@ var diffpiSetupTool = defineTool7({
3959
3844
  return formatResult(result, "Setup complete.");
3960
3845
  }
3961
3846
  });
3962
- var diffpiValidateTool = defineTool7({
3847
+ var diffpiValidateTool = defineTool6({
3963
3848
  name: "diffpi_validate",
3964
3849
  label: "diffpi validate",
3965
3850
  description: "Inspect the @difflab/pi environment without installing software or changing configuration files.",
@@ -4001,20 +3886,20 @@ ${lines.join(`
4001
3886
  }
4002
3887
 
4003
3888
  // src/tools/templates.ts
4004
- import { defineTool as defineTool8 } from "@earendil-works/pi-coding-agent";
4005
- import { z as z13 } from "zod";
4006
- var templateSchema = z13.object({
4007
- name: z13.string().min(1),
4008
- variables: z13.record(z13.string(), z13.string()).optional(),
4009
- homeDir: z13.string().optional()
3889
+ import { defineTool as defineTool7 } from "@earendil-works/pi-coding-agent";
3890
+ import { z as z12 } from "zod";
3891
+ var templateSchema = z12.object({
3892
+ name: z12.string().min(1),
3893
+ variables: z12.record(z12.string(), z12.string()).optional(),
3894
+ homeDir: z12.string().optional()
4010
3895
  });
4011
- var diffpiTemplateTool = defineTool8({
3896
+ var diffpiTemplateTool = defineTool7({
4012
3897
  name: "diffpi_template",
4013
3898
  label: "diffpi template",
4014
3899
  description: "Load a bundled Diffpi template or a user override and render named variables.",
4015
3900
  promptSnippet: "Use diffpi_template for package workflow templates",
4016
3901
  promptGuidelines: ["User overrides live under ~/.difflab/diffpi/templates."],
4017
- parameters: z13.toJSONSchema(templateSchema, { io: "input" }),
3902
+ parameters: z12.toJSONSchema(templateSchema, { io: "input" }),
4018
3903
  executionMode: "parallel",
4019
3904
  async execute(_id, input) {
4020
3905
  const params = templateSchema.parse(input);
@@ -4028,7 +3913,7 @@ var diffpiTemplateTool = defineTool8({
4028
3913
  });
4029
3914
 
4030
3915
  // src/tools/index.ts
4031
- function createPiTools(pi, modes) {
3916
+ function createPiTools(pi) {
4032
3917
  return [
4033
3918
  diffpiSetupTool,
4034
3919
  diffpiValidateTool,
@@ -4037,13 +3922,11 @@ function createPiTools(pi, modes) {
4037
3922
  diffpiTemplateTool,
4038
3923
  planVerifyTool,
4039
3924
  watchCiTool,
4040
- ...createModeTools(modes),
4041
3925
  ...createReviewTools()
4042
3926
  ];
4043
3927
  }
4044
3928
  export {
4045
3929
  createDiffpiReloadTool,
4046
- createModeTools,
4047
3930
  createPiTools,
4048
3931
  createReviewTools,
4049
3932
  diffpiLogTool,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@difflab/pi",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "description": "Tools and skills for the pi coding agent",
5
5
  "repository": {
6
6
  "type": "git",
@@ -59,7 +59,7 @@
59
59
  "@juicesharp/rpiv-ask-user-question": "^2.10.1",
60
60
  "commander": "^14.0.0",
61
61
  "mdast-builder": "1.1.1",
62
- "pi-mcp-adapter": "^2.33.0",
62
+ "pi-mcp-adapter": "^2.38.0",
63
63
  "remark-stringify": "11.0.0",
64
64
  "unified": "11.0.5",
65
65
  "zod": "^4.6.5"
@@ -47,4 +47,4 @@ Map `None`, `Linear`, and `Jira` to `none`, `linear`, and `jira`. Infer the revi
47
47
 
48
48
  When the user is using Zed, ask separately whether to bind `cmd-alt-r` to the `diffpi: tuicr review` task. Only pass `bindZedKey: true` when the user opts in; otherwise pass `false`.
49
49
 
50
- Setup installs Diffpi's bundled agent Markdown into Pi's standard global agent directory. Explain that each default can run through the subagent plugin or as the current inline prompt. `/skill:mode` opens the structured picker. It also accepts `--include-skills`, one agent id, a qualified `skill:agent` id, or `clear`.
50
+ Setup installs Diffpi's bundled agent Markdown into Pi's standard global agent directory. The agents run through the subagent plugin; no inline profile selection is required for plan or review workflows.
@@ -1,31 +1,21 @@
1
1
  ---
2
2
  name: plan
3
3
  description: Create, revise, review, finalize, and execute live Diffpi plans with direct files and one verified plan reviewer.
4
- allowed-tools: read grep find write edit ask_user_question Agent get_subagent_result steer_subagent diffpi_modes_set diffpi_modes_status plan_verify bash ctx_execute ctx_execute_file watch_ci
5
4
  ---
6
5
 
7
6
  # Plan
8
7
 
9
- `/plan` forwards raw arguments to this skill. Parse the first explicit verb (`init`, `new`, `update`, `annotate`, `finalize`, `go`, `help`); for unknown or empty input, infer a verb from a clear natural-language request. Use `help` only when neither verb nor intent is identifiable; when plan/intent is ambiguous, ask one structured material-decision question. Preserve the exact incoming user request for the Planner. Read the matching reference first. Keep the alias handler thin. Git and project tasks run through `bash` (or the upstream git skill); do not invent tool names for tasks, format, lint, test, CI, or push.
8
+ Route the verb and remaining request to its workflow. Fuzzy-match recognizable natural language; treat argument shapes as hints, not rigid gates.
10
9
 
11
- ## Roles and preflight
10
+ | Input | Workflow |
11
+ | -------------------------------------------- | -------------------------------------------- |
12
+ | `init <slug> [--branch <branch>]` | [init](references/workflows/init.md) |
13
+ | `new <slug> <request>` | [new](references/workflows/new.md) |
14
+ | `update <slug> <request>` | [update](references/workflows/update.md) |
15
+ | `annotate <plan-path>` | [annotate](references/workflows/annotate.md) |
16
+ | `validate <slug>` | [validate](references/workflows/validate.md) |
17
+ | `finalize <slug>` | [finalize](references/workflows/finalize.md) |
18
+ | `go <slug> [--mode no-commit\|commit\|push]` | [go](references/workflows/go.md) |
19
+ | `help`, missing or unrecognizable request | [help](references/workflows/help.md) |
12
20
 
13
- - **Planner** authors and repairs live `PLAN.md` and numbered briefs with frontier/high thinking.
14
- - **diffpi-plan-reviewer** is exactly one independent frontier/high, read/search-only child. It first calls `diffpi_modes_status` and returns actual model, thinking, and tools evidence, then reviews structure, parity, action labels, quality, risk, and Worker executability. Reject missing or unverifiable evidence; do not use a fallback reviewer.
15
- - **Orchestrator** owns go coordination, live-file checkboxes/status, project gates, Git, push, and CI. **Worker** edits only its declared source/test scope and never changes plan files or commits.
16
-
17
- For foreground authoring, call `diffpi_modes_set({agent: "planner"})` using the shared inline id (never `plan:planner`); on the next model turn call `diffpi_modes_status` and stop if the switch or evidence is unavailable. For foreground `go`, call `diffpi_modes_set({agent: "orchestrator"})` and verify its status on the next turn. `--bg` launches exactly one named same-session child with `Agent` (Planner for `init/new/update/finalize`, Orchestrator for `go`), passing the exact verb, target, cwd, mode, and `background: true`; remove `--bg`. The child never redispatches, asks questions, or falls back inline.
18
-
19
- ## Live-file contract
20
-
21
- Plans live under the initiating nested Git root in one flat `.diffpi/plan/<YYMMDD[-ticket]-short-slug>/` directory. The date and slug are parts of ONE directory name, never nested `date/slug` directories. Resolve collisions before writing. Use ordinary `read`/`write`/`edit` calls, read every file back, and preserve intent, IDs, completed evidence, order, dependencies, scopes, and constraints. Document phase constraints in each phase's `PLAN.md` entry (use `None` if empty). Each brief puts its sole action-labeled, fenced `text` file tree under `## Files Affected` immediately after `## Objective` (never a bullet list); `## Implementation Constraints` is free-form with optional subheadings. Edit only live plan files; never managed records, plugin source, tests, or profiles. `INCOMPLETE` is a visible marker inside an open `DRAFT`, not a status enum.
22
-
23
- `new` and `update` run the stateless read-only `plan_verify` on the current files, then review the complete current draft with one reviewer profile. Repair actionable findings, rerun mechanical verification after each repair, and invoke the same named reviewer again in a fresh `Agent` call (never resume a finished child) within bounded attempts. They remain `DRAFT` after a successful review. Require the child to complete with an attested explicit PASS; partial, steered, stopped, missing, and BLOCKING reports never count. `finalize` and draft `go` write `READY` only after both a passing `plan_verify` on current files and that completed reviewer PASS; do not dispatch Workers or write ready after repairing a failed review without a new completed review. An already-ready plan is reread and mechanically verified too. `plan_verify` does not judge quality, change status, freeze files, or replace the reviewer. No retired managed-plan tools.
24
-
25
- ## Execution
26
-
27
- `go --mode no-commit|commit|push` defaults to `no-commit`. The Orchestrator is the only writer of plan status/checkboxes and coordinates Workers. A draft gets one mechanical `plan_verify` check and one reviewer per pass; both must pass on current files before ready. Schedule a phase only after all prerequisites complete; derive each bounded Worker's task scope from its steps and the phase's sole Files Affected tree. Serialize tasks with overlapping or uncertain derived scopes; independent tasks may run concurrently only when scopes are unambiguously disjoint and prerequisites are satisfied. Run project format, lint, test, and CI checks via `bash`/`ctx_execute` as appropriate. On any failure, preserve the exact command/output, attempts, and affected role and block.
28
-
29
- With `commit`, after gates pass make one phase commit. With `push`, push it and call `watch_ci` for that exact SHA; do not push the next phase until settled. `--bg` has one child only and that child does not redispatch. No stateful plan tools.
30
-
31
- Read: [init](references/workflows/init.md), [new](references/workflows/new.md), [update](references/workflows/update.md), [annotate](references/workflows/annotate.md), [finalize](references/workflows/finalize.md), [go](references/workflows/go.md), [help](references/workflows/help.md).
21
+ Follow the selected workflow. For `init`, `new`, `update`, DRAFT `validate`, `finalize`, or `go` when no native subagents are available, follow [the explicit inline exception](references/workflows/inline-fallback.md) only after the caller obtains confirmation; never silently fall back.