@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.
- package/README.md +22 -40
- package/agents/diffpi-copilot.md +2 -2
- package/agents/diffpi-orchestrator.md +9 -14
- package/agents/diffpi-plan-reviewer.md +4 -12
- package/agents/diffpi-planner.md +6 -12
- package/agents/diffpi-reviewer.md +6 -10
- package/agents/diffpi-tutor.md +2 -2
- package/agents/diffpi-worker.md +3 -6
- package/dist/commands/dispatch.d.ts +4 -0
- package/dist/commands/dispatch.d.ts.map +1 -0
- package/dist/commands/index.d.ts +1 -3
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/plan.d.ts +1 -1
- package/dist/commands/plan.d.ts.map +1 -1
- package/dist/commands/review.d.ts +1 -1
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/extensions/index.js +365 -881
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -403
- package/dist/tools/index.d.ts +1 -3
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +95 -212
- package/package.json +2 -2
- package/skills/diffpi-setup/SKILL.md +1 -1
- package/skills/plan/SKILL.md +12 -22
- package/skills/plan/references/design-quality.md +3 -3
- package/skills/plan/references/workflows/annotate.md +9 -3
- package/skills/plan/references/workflows/finalize.md +10 -6
- package/skills/plan/references/workflows/go.md +25 -7
- package/skills/plan/references/workflows/help.md +20 -3
- package/skills/plan/references/workflows/init.md +23 -6
- package/skills/plan/references/workflows/inline-fallback.md +9 -0
- package/skills/plan/references/workflows/new.md +22 -7
- package/skills/plan/references/workflows/update.md +22 -6
- package/skills/plan/references/workflows/validate.md +31 -0
- package/skills/review/SKILL.md +14 -6
- package/skills/review/references/workflows/address.md +19 -6
- package/skills/review/references/workflows/auto.md +21 -5
- package/skills/review/references/workflows/complete.md +17 -4
- package/skills/review/references/workflows/edit.md +8 -2
- package/skills/review/references/workflows/foreground-fallback.md +7 -0
- package/skills/review/references/workflows/help.md +22 -13
- package/skills/review/references/workflows/merge.md +17 -2
- package/skills/review/references/workflows/new.md +17 -5
- package/skills/review/references/workflows/open.md +8 -2
- package/skills/review/references/workflows/publish.md +17 -4
- package/skills/review/references/workflows/status.md +7 -2
- package/templates/plan/PLAN.md +1 -1
- package/dist/commands/mode.d.ts +0 -5
- package/dist/commands/mode.d.ts.map +0 -1
- package/dist/modes.d.ts +0 -75
- package/dist/modes.d.ts.map +0 -1
- package/dist/tools/modes.d.ts +0 -4
- package/dist/tools/modes.d.ts.map +0 -1
- 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;
|
|
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"}
|
package/dist/tools/index.js
CHANGED
|
@@ -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
|
|
1206
|
-
import { z as
|
|
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
|
|
1440
|
-
var severitySchema =
|
|
1441
|
-
var findingSchema =
|
|
1442
|
-
file:
|
|
1443
|
-
line:
|
|
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:
|
|
1446
|
-
reference:
|
|
1330
|
+
body: z6.string().min(1),
|
|
1331
|
+
reference: z6.string().optional().default("")
|
|
1447
1332
|
});
|
|
1448
|
-
var findingsSchema =
|
|
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
|
|
1522
|
-
var reviewThreadRecordSchema =
|
|
1523
|
-
id:
|
|
1524
|
-
file:
|
|
1525
|
-
line:
|
|
1526
|
-
body:
|
|
1527
|
-
author:
|
|
1528
|
-
resolved:
|
|
1529
|
-
addressed:
|
|
1530
|
-
question:
|
|
1531
|
-
replies:
|
|
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 =
|
|
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
|
|
2290
|
-
var reviewPublicationStateSchema =
|
|
2291
|
-
target:
|
|
2292
|
-
bodies:
|
|
2293
|
-
comments:
|
|
2294
|
-
stagedComments:
|
|
2295
|
-
replies:
|
|
2296
|
-
overlayPath:
|
|
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
|
|
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 =
|
|
2373
|
-
cwd:
|
|
2374
|
-
target:
|
|
2375
|
-
workingTree:
|
|
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:
|
|
2262
|
+
var localSchema = contextSchema.extend({ local: z9.boolean().optional() });
|
|
2378
2263
|
var openSchema = localSchema.extend({
|
|
2379
|
-
title:
|
|
2380
|
-
intent:
|
|
2381
|
-
issueUrl:
|
|
2382
|
-
base:
|
|
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:
|
|
2387
|
-
notVerified:
|
|
2388
|
-
title:
|
|
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:
|
|
2392
|
-
file:
|
|
2393
|
-
line:
|
|
2394
|
-
side:
|
|
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:
|
|
2398
|
-
body:
|
|
2399
|
-
question:
|
|
2400
|
-
resolve:
|
|
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:
|
|
2288
|
+
status: z9.enum(["COMMENT", "APPROVE", "REQUEST_CHANGES", "CLOSE"]).optional()
|
|
2404
2289
|
});
|
|
2405
2290
|
var completeSchema = localSchema.extend({
|
|
2406
|
-
action:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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
|
|
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
|
|
3352
|
-
import { z as
|
|
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
|
|
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 =
|
|
3384
|
-
models:
|
|
3268
|
+
var agentConfigSchema = z10.object({
|
|
3269
|
+
models: z10.array(modelReferenceSchema).optional()
|
|
3385
3270
|
}).strict();
|
|
3386
|
-
var diffpiConfigSchema =
|
|
3387
|
-
agents:
|
|
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 =
|
|
3927
|
-
issueTracker:
|
|
3928
|
-
forges:
|
|
3929
|
-
forge:
|
|
3930
|
-
bindZedKey:
|
|
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 =
|
|
3933
|
-
var diffpiSetupTool =
|
|
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 =
|
|
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
|
|
4005
|
-
import { z as
|
|
4006
|
-
var templateSchema =
|
|
4007
|
-
name:
|
|
4008
|
-
variables:
|
|
4009
|
-
homeDir:
|
|
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 =
|
|
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:
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
package/skills/plan/SKILL.md
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|