@appsforgood/next-supabase-kit 0.1.5 → 0.1.7
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/CHANGELOG.md +12 -0
- package/DOGFOOD.md +40 -0
- package/README.md +246 -43
- package/REPOSITORY_SETTINGS.md +7 -3
- package/SUPPLY_CHAIN.md +5 -5
- package/UPGRADE.md +2 -1
- package/antigravity/commands/accessibility-pass.toml +16 -0
- package/antigravity/commands/browser-qa.toml +18 -0
- package/antigravity/commands/distinctiveness-pass.toml +16 -0
- package/antigravity/commands/frontend.toml +5 -4
- package/antigravity/commands/layout-cleanup.toml +16 -0
- package/antigravity/commands/responsive-cleanup.toml +16 -0
- package/antigravity/commands/review.toml +16 -0
- package/antigravity/commands/screenshot-critique.toml +16 -0
- package/antigravity/commands/spec.toml +17 -0
- package/antigravity/commands/test.toml +17 -0
- package/antigravity/commands/ui-audit.toml +17 -0
- package/antigravity/commands/ui-polish.toml +17 -0
- package/antigravity/plugin.json +13 -1
- package/assistant-adapters/antigravity.md +7 -0
- package/checklists/ui-acceptance-rubric.md +58 -0
- package/checklists/ui-detectors.md +75 -0
- package/dist/index.js +796 -458
- package/dist/index.js.map +1 -1
- package/dist/studio/office/assets/office.css +109 -28
- package/dist/studio/office/assets/office.js +14 -63
- package/dist/studio/wizard/assets/wizard.css +105 -26
- package/dist/studio/wizard/assets/wizard.js +22 -85
- package/examples/next-supabase-installed/.agent-kit/agent-roster.json +53 -14
- package/examples/next-supabase-installed/.agent-kit/manifest.json +12 -12
- package/examples/next-supabase-installed/audit-output.json +380 -375
- package/package.json +21 -5
- package/prompts/lifecycle-command-index.md +180 -0
- package/prompts/ui-command-index.md +124 -0
- package/rosters/next-supabase-default-council.json +53 -14
- package/runtime-skills/ui-improvement-harness/SKILL.md +12 -0
- package/skills/ui-improvement-harness.md +96 -0
- package/templates/next-supabase/AGENT_ROSTER.md +6 -3
- package/templates/next-supabase/ASSISTANT_ADAPTERS.md +3 -1
- package/templates/next-supabase/DECISIONS.md +14 -0
- package/templates/next-supabase/DESIGN.md +3 -0
- package/templates/next-supabase/DOCS.md +5 -1
- package/templates/next-supabase/QUALITY_GATES.md +4 -2
- package/templates/next-supabase/SKILLS.md +14 -0
- package/templates/next-supabase/SPEC.md +5 -1
- package/templates/next-supabase/STYLE_GUIDE.md +3 -1
- package/templates/next-supabase/TESTING.md +4 -0
package/dist/index.js
CHANGED
|
@@ -1,23 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli/index.ts
|
|
4
|
+
import { existsSync as existsSync23, readFileSync as readFileSync24, writeFileSync as writeFileSync2 } from "fs";
|
|
5
|
+
import { join as join27 } from "path";
|
|
4
6
|
import { Command } from "commander";
|
|
5
7
|
|
|
6
8
|
// src/install/add-skill.ts
|
|
7
|
-
import { existsSync as existsSync3 } from "fs";
|
|
9
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
8
10
|
import { join as join3 } from "path";
|
|
9
11
|
|
|
10
12
|
// src/utils/fs.ts
|
|
11
13
|
import { createHash } from "crypto";
|
|
12
|
-
import {
|
|
13
|
-
cpSync,
|
|
14
|
-
existsSync,
|
|
15
|
-
lstatSync,
|
|
16
|
-
mkdirSync,
|
|
17
|
-
readFileSync,
|
|
18
|
-
readdirSync,
|
|
19
|
-
writeFileSync
|
|
20
|
-
} from "fs";
|
|
14
|
+
import { cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "fs";
|
|
21
15
|
import { basename, dirname, isAbsolute, join, relative, resolve } from "path";
|
|
22
16
|
function ensureDir(path) {
|
|
23
17
|
mkdirSync(path, { recursive: true });
|
|
@@ -133,20 +127,30 @@ function addSkill(cwd, skillName, options = {}) {
|
|
|
133
127
|
const available = listSkills().join(", ");
|
|
134
128
|
throw new Error(`Unknown skill "${skillName}". Available skills: ${available}`);
|
|
135
129
|
}
|
|
136
|
-
const
|
|
130
|
+
const targetRelativePath = join3(".agent-kit", "skills", normalized);
|
|
131
|
+
if (options.dryRun) {
|
|
132
|
+
const existing = readTextIfExists(join3(cwd, targetRelativePath));
|
|
133
|
+
const sourceContent = readFileSync2(sourcePath, "utf8");
|
|
134
|
+
let action;
|
|
135
|
+
if (existing === null) action = "created";
|
|
136
|
+
else if (sha256(existing) === sha256(sourceContent)) action = "unchanged";
|
|
137
|
+
else action = options.force ? "overwritten" : "conflict";
|
|
138
|
+
return { action, target: targetRelativePath, dryRun: true };
|
|
139
|
+
}
|
|
140
|
+
const result = copyTextWithConflict(sourcePath, cwd, targetRelativePath, {
|
|
137
141
|
force: Boolean(options.force),
|
|
138
142
|
conflictRoot: join3(cwd, ".agent-kit", "conflicts")
|
|
139
143
|
});
|
|
140
|
-
return
|
|
144
|
+
return { ...result, dryRun: false };
|
|
141
145
|
}
|
|
142
146
|
|
|
143
147
|
// src/install/adapter-validate.ts
|
|
144
|
-
import { existsSync as existsSync12, readFileSync as
|
|
148
|
+
import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
|
|
145
149
|
import { join as join12, normalize } from "path";
|
|
146
150
|
|
|
147
151
|
// src/config/defaults.ts
|
|
148
152
|
var PACKAGE_NAME = "@appsforgood/next-supabase-kit";
|
|
149
|
-
var PACKAGE_VERSION = "0.1.
|
|
153
|
+
var PACKAGE_VERSION = "0.1.7";
|
|
150
154
|
var DEFAULT_CONFIG = {
|
|
151
155
|
stack: "next-supabase",
|
|
152
156
|
projectType: "saas",
|
|
@@ -264,7 +268,7 @@ var CI_TEMPLATE_FILES = [
|
|
|
264
268
|
];
|
|
265
269
|
|
|
266
270
|
// src/studio/shared.ts
|
|
267
|
-
import { appendFileSync, existsSync as existsSync4, readFileSync as
|
|
271
|
+
import { appendFileSync, existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
268
272
|
import { basename as basename2, dirname as dirname3, join as join4 } from "path";
|
|
269
273
|
var AGENT_KIT_DIR = ".agent-kit";
|
|
270
274
|
var CONTEXT_JSON = ".agent-kit/project-context.json";
|
|
@@ -315,7 +319,7 @@ function ensureStudioDirs(cwd) {
|
|
|
315
319
|
function readJsonFile(cwd, relativePath) {
|
|
316
320
|
const path = resolveInside(cwd, relativePath);
|
|
317
321
|
if (!existsSync4(path)) return null;
|
|
318
|
-
return JSON.parse(
|
|
322
|
+
return JSON.parse(readFileSync3(path, "utf8"));
|
|
319
323
|
}
|
|
320
324
|
function writeJsonFile(cwd, relativePath, value) {
|
|
321
325
|
writeText(resolveInside(cwd, relativePath), `${JSON.stringify(value, null, 2)}
|
|
@@ -330,7 +334,7 @@ function appendJsonLine(cwd, relativePath, value) {
|
|
|
330
334
|
function readJsonLines(cwd, relativePath) {
|
|
331
335
|
const text = readTextIfExists(resolveInside(cwd, relativePath));
|
|
332
336
|
if (!text) return [];
|
|
333
|
-
return text.split(/\r?\n/).filter((
|
|
337
|
+
return text.split(/\r?\n/).filter((line2) => line2.trim().length > 0).map((line2) => JSON.parse(line2));
|
|
334
338
|
}
|
|
335
339
|
function writeTextFile(cwd, relativePath, content) {
|
|
336
340
|
writeText(resolveInside(cwd, relativePath), content);
|
|
@@ -360,7 +364,7 @@ function unique(values) {
|
|
|
360
364
|
}
|
|
361
365
|
|
|
362
366
|
// src/install/audit.ts
|
|
363
|
-
import { existsSync as existsSync11, readFileSync as
|
|
367
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9, statSync } from "fs";
|
|
364
368
|
import { join as join11 } from "path";
|
|
365
369
|
|
|
366
370
|
// src/config/contracts.ts
|
|
@@ -631,14 +635,7 @@ var SessionEventContract = z.object({
|
|
|
631
635
|
}
|
|
632
636
|
});
|
|
633
637
|
var AgenticLevelCore = z.union([z.literal(3), z.literal(4), z.literal(5), z.literal(6)]);
|
|
634
|
-
var AgenticLevelTarget = z.union([
|
|
635
|
-
z.literal(3),
|
|
636
|
-
z.literal(4),
|
|
637
|
-
z.literal(5),
|
|
638
|
-
z.literal(6),
|
|
639
|
-
z.literal(7),
|
|
640
|
-
z.literal(8)
|
|
641
|
-
]);
|
|
638
|
+
var AgenticLevelTarget = z.union([z.literal(3), z.literal(4), z.literal(5), z.literal(6), z.literal(7), z.literal(8)]);
|
|
642
639
|
var OnboardingStateContract = z.object({
|
|
643
640
|
schemaVersion: z.literal(1),
|
|
644
641
|
depth: z.enum(["quick", "standard", "complete", "undecided"]),
|
|
@@ -686,12 +683,12 @@ import { existsSync as existsSync6 } from "fs";
|
|
|
686
683
|
import { join as join6 } from "path";
|
|
687
684
|
|
|
688
685
|
// src/studio/context.ts
|
|
689
|
-
import { existsSync as existsSync5, readFileSync as
|
|
686
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
|
|
690
687
|
import { join as join5 } from "path";
|
|
691
688
|
function readPackageJson(cwd) {
|
|
692
689
|
const path = join5(cwd, "package.json");
|
|
693
690
|
if (!existsSync5(path)) return null;
|
|
694
|
-
return JSON.parse(
|
|
691
|
+
return JSON.parse(readFileSync4(path, "utf8"));
|
|
695
692
|
}
|
|
696
693
|
function detectPackageManager(cwd) {
|
|
697
694
|
if (existsSync5(join5(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
@@ -710,7 +707,7 @@ function detectFromDependencies(packageJson, names) {
|
|
|
710
707
|
function readEnvExampleKeys(cwd) {
|
|
711
708
|
const envText = readTextIfExists(join5(cwd, ".env.example")) ?? "";
|
|
712
709
|
return unique(
|
|
713
|
-
envText.split(/\r?\n/).map((
|
|
710
|
+
envText.split(/\r?\n/).map((line2) => line2.trim()).filter((line2) => line2 && !line2.startsWith("#") && line2.includes("=")).map((line2) => line2.split("=")[0]?.trim() ?? "").filter(Boolean)
|
|
714
711
|
);
|
|
715
712
|
}
|
|
716
713
|
function inferOpenQuestions(context2) {
|
|
@@ -1144,19 +1141,19 @@ function onboardingStateExists(cwd) {
|
|
|
1144
1141
|
}
|
|
1145
1142
|
|
|
1146
1143
|
// src/install/install.ts
|
|
1147
|
-
import { existsSync as existsSync10, readFileSync as
|
|
1144
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
|
|
1148
1145
|
import { join as join10 } from "path";
|
|
1149
1146
|
|
|
1150
1147
|
// src/install/ide-activate.ts
|
|
1151
|
-
import { existsSync as existsSync9, readFileSync as
|
|
1148
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
|
|
1152
1149
|
import { join as join9 } from "path";
|
|
1153
1150
|
|
|
1154
1151
|
// src/install/roster-adapters.ts
|
|
1155
|
-
import { existsSync as existsSync8, readFileSync as
|
|
1152
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6, readdirSync as readdirSync2 } from "fs";
|
|
1156
1153
|
import { join as join8 } from "path";
|
|
1157
1154
|
|
|
1158
1155
|
// src/studio/wizard/roster.ts
|
|
1159
|
-
import { existsSync as existsSync7, readFileSync as
|
|
1156
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
|
|
1160
1157
|
import { join as join7 } from "path";
|
|
1161
1158
|
var AGENT_ROSTER_JSON = ".agent-kit/agent-roster.json";
|
|
1162
1159
|
var FALLBACK_SUMMARIES = {
|
|
@@ -1176,7 +1173,7 @@ function readPurposeFromAgentFile(cwd, relPath) {
|
|
|
1176
1173
|
if (!relPath) return null;
|
|
1177
1174
|
const path = join7(cwd, relPath);
|
|
1178
1175
|
if (!existsSync7(path)) return null;
|
|
1179
|
-
const text =
|
|
1176
|
+
const text = readFileSync5(path, "utf8");
|
|
1180
1177
|
const match = text.match(/## Purpose\s*\n+\s*([^\n#]+)/);
|
|
1181
1178
|
return match?.[1]?.trim() ?? null;
|
|
1182
1179
|
}
|
|
@@ -1216,20 +1213,18 @@ function buildAgentWizardSteps(cwd) {
|
|
|
1216
1213
|
depth: depths,
|
|
1217
1214
|
optional: true
|
|
1218
1215
|
},
|
|
1219
|
-
...agents.map(
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
})
|
|
1232
|
-
)
|
|
1216
|
+
...agents.map((agent) => ({
|
|
1217
|
+
id: `brief-${agent.id}`,
|
|
1218
|
+
section: "team",
|
|
1219
|
+
title: `Brief ${agent.name}`,
|
|
1220
|
+
why: `${agent.roleSummary} What should they know about this project that is not obvious from the repo?`,
|
|
1221
|
+
fields: [`agentBrief_${agent.id}`],
|
|
1222
|
+
agentId: agent.id,
|
|
1223
|
+
agentName: agent.name,
|
|
1224
|
+
roleSummary: agent.roleSummary,
|
|
1225
|
+
depth: depths,
|
|
1226
|
+
optional: true
|
|
1227
|
+
}))
|
|
1233
1228
|
];
|
|
1234
1229
|
}
|
|
1235
1230
|
function agentBriefFieldName(agentId) {
|
|
@@ -1238,8 +1233,8 @@ function agentBriefFieldName(agentId) {
|
|
|
1238
1233
|
|
|
1239
1234
|
// src/install/assistant-adapters-table.ts
|
|
1240
1235
|
function extractAssistantAdapterRow(adaptersDoc, toolLabel) {
|
|
1241
|
-
for (const
|
|
1242
|
-
const trimmed =
|
|
1236
|
+
for (const line2 of adaptersDoc.split("\n")) {
|
|
1237
|
+
const trimmed = line2.trim();
|
|
1243
1238
|
if (!trimmed.startsWith("|")) continue;
|
|
1244
1239
|
const cells = trimmed.split("|").map((cell) => cell.trim()).filter((cell) => cell.length > 0);
|
|
1245
1240
|
if (cells[0] === toolLabel) return trimmed;
|
|
@@ -1314,7 +1309,7 @@ Record meaningful decisions, risks, handoffs, human corrections, artifacts, evid
|
|
|
1314
1309
|
function writeGeneratedAgentFile(cwd, relativePath, content, force, result) {
|
|
1315
1310
|
const targetPath = join8(cwd, relativePath);
|
|
1316
1311
|
if (!force && existsSync8(targetPath)) {
|
|
1317
|
-
const existing =
|
|
1312
|
+
const existing = readFileSync6(targetPath, "utf8");
|
|
1318
1313
|
if (existing === content) {
|
|
1319
1314
|
result.unchanged.push(relativePath);
|
|
1320
1315
|
return;
|
|
@@ -1363,7 +1358,7 @@ function loadAgentReasoningEffortMap(cwd) {
|
|
|
1363
1358
|
const map = /* @__PURE__ */ new Map();
|
|
1364
1359
|
if (!existsSync8(path)) return map;
|
|
1365
1360
|
try {
|
|
1366
|
-
const parsed = JSON.parse(
|
|
1361
|
+
const parsed = JSON.parse(readFileSync6(path, "utf8"));
|
|
1367
1362
|
const profileEffort = /* @__PURE__ */ new Map();
|
|
1368
1363
|
for (const profile of parsed.profiles ?? []) {
|
|
1369
1364
|
if (profile.id && profile.reasoningEffort) {
|
|
@@ -1447,7 +1442,7 @@ function generateCursorSkillsFromKit(cwd, force, result) {
|
|
|
1447
1442
|
if (!existsSync8(skillsRoot)) return;
|
|
1448
1443
|
for (const file of readdirSync2(skillsRoot).filter((name) => name.endsWith(".md"))) {
|
|
1449
1444
|
const skillId = file.replace(/\.md$/, "");
|
|
1450
|
-
const kitMarkdown =
|
|
1445
|
+
const kitMarkdown = readFileSync6(join8(skillsRoot, file), "utf8");
|
|
1451
1446
|
const relativePath = `.cursor/skills/${skillId}/SKILL.md`;
|
|
1452
1447
|
writeGeneratedAgentFile(cwd, relativePath, kitSkillToCursorSkill(skillId, kitMarkdown), force, result);
|
|
1453
1448
|
}
|
|
@@ -1494,27 +1489,13 @@ function installAntigravityAdapter(cwd, packageRoot, force, result) {
|
|
|
1494
1489
|
for (const file of ANTIGRAVITY_PLUGIN_FILES) {
|
|
1495
1490
|
copyAdapterFile(cwd, packageRoot, file.source, file.target, force, result);
|
|
1496
1491
|
}
|
|
1497
|
-
copyDirectoryAsConflicts(
|
|
1498
|
-
|
|
1499
|
-
packageRoot,
|
|
1500
|
-
ANTIGRAVITY_COMMANDS_SOURCE_DIR,
|
|
1501
|
-
ANTIGRAVITY_COMMANDS_TARGET_DIR,
|
|
1502
|
-
force,
|
|
1503
|
-
result
|
|
1504
|
-
);
|
|
1505
|
-
copyDirectoryAsConflicts(
|
|
1506
|
-
cwd,
|
|
1507
|
-
packageRoot,
|
|
1508
|
-
RUNTIME_SKILLS_SOURCE_DIR,
|
|
1509
|
-
ANTIGRAVITY_RUNTIME_SKILLS_TARGET_DIR,
|
|
1510
|
-
force,
|
|
1511
|
-
result
|
|
1512
|
-
);
|
|
1492
|
+
copyDirectoryAsConflicts(cwd, packageRoot, ANTIGRAVITY_COMMANDS_SOURCE_DIR, ANTIGRAVITY_COMMANDS_TARGET_DIR, force, result);
|
|
1493
|
+
copyDirectoryAsConflicts(cwd, packageRoot, RUNTIME_SKILLS_SOURCE_DIR, ANTIGRAVITY_RUNTIME_SKILLS_TARGET_DIR, force, result);
|
|
1513
1494
|
}
|
|
1514
1495
|
function updateAssistantAdaptersTable(cwd, activated) {
|
|
1515
1496
|
const path = join9(cwd, "ASSISTANT_ADAPTERS.md");
|
|
1516
1497
|
if (!existsSync9(path)) return;
|
|
1517
|
-
let content =
|
|
1498
|
+
let content = readFileSync7(path, "utf8");
|
|
1518
1499
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
1519
1500
|
if (activated.has("cursor") && content.includes("| Cursor |")) {
|
|
1520
1501
|
content = content.replace(
|
|
@@ -1625,7 +1606,7 @@ function initProject(options) {
|
|
|
1625
1606
|
const templateHashes = {};
|
|
1626
1607
|
for (const doc of ROOT_DOCS) {
|
|
1627
1608
|
const templatePath = join10(templateRoot, doc);
|
|
1628
|
-
templateHashes[doc] = sha256(
|
|
1609
|
+
templateHashes[doc] = sha256(readFileSync8(templatePath, "utf8"));
|
|
1629
1610
|
const copyResult = copyTextWithConflict(templatePath, cwd, doc, {
|
|
1630
1611
|
force: Boolean(options.force),
|
|
1631
1612
|
conflictRoot: join10(cwd, ".agent-kit", "conflicts")
|
|
@@ -1715,7 +1696,7 @@ function initProject(options) {
|
|
|
1715
1696
|
function readManifest(cwd) {
|
|
1716
1697
|
const manifestPath = join10(cwd, ".agent-kit", "manifest.json");
|
|
1717
1698
|
if (!existsSync10(manifestPath)) return null;
|
|
1718
|
-
return JSON.parse(
|
|
1699
|
+
return JSON.parse(readFileSync8(manifestPath, "utf8"));
|
|
1719
1700
|
}
|
|
1720
1701
|
|
|
1721
1702
|
// src/install/audit.ts
|
|
@@ -1745,6 +1726,7 @@ var REQUIRED_SKILL_IDS = [
|
|
|
1745
1726
|
"frontend-distinctiveness-benchmark",
|
|
1746
1727
|
"frontend-product-quality-rubric",
|
|
1747
1728
|
"frontend-design-system",
|
|
1729
|
+
"ui-improvement-harness",
|
|
1748
1730
|
"visual-regression-qa",
|
|
1749
1731
|
"positioning-messaging",
|
|
1750
1732
|
"conversion-copywriting",
|
|
@@ -1786,13 +1768,13 @@ function includesAll(text, values) {
|
|
|
1786
1768
|
}
|
|
1787
1769
|
function readDoc(cwd, file) {
|
|
1788
1770
|
const path = join11(cwd, file);
|
|
1789
|
-
return existsSync11(path) ?
|
|
1771
|
+
return existsSync11(path) ? readFileSync9(path, "utf8") : "";
|
|
1790
1772
|
}
|
|
1791
1773
|
function isPackageRepository(cwd) {
|
|
1792
1774
|
const packagePath = join11(cwd, "package.json");
|
|
1793
1775
|
if (!existsSync11(packagePath)) return false;
|
|
1794
1776
|
try {
|
|
1795
|
-
const packageJson = JSON.parse(
|
|
1777
|
+
const packageJson = JSON.parse(readFileSync9(packagePath, "utf8"));
|
|
1796
1778
|
return packageJson.name === "@appsforgood/next-supabase-kit" && existsSync11(join11(cwd, "src", "cli", "index.ts")) && existsSync11(join11(cwd, "templates", "next-supabase")) && existsSync11(join11(cwd, "rosters", "next-supabase-default-council.json"));
|
|
1797
1779
|
} catch {
|
|
1798
1780
|
return false;
|
|
@@ -1802,7 +1784,7 @@ function readOverrides(cwd) {
|
|
|
1802
1784
|
const path = join11(cwd, ".agent-kit", "overrides.json");
|
|
1803
1785
|
if (!existsSync11(path)) return {};
|
|
1804
1786
|
try {
|
|
1805
|
-
const parsed = JSON.parse(
|
|
1787
|
+
const parsed = JSON.parse(readFileSync9(path, "utf8"));
|
|
1806
1788
|
const templates = parsed.templates ?? {};
|
|
1807
1789
|
return Object.fromEntries(
|
|
1808
1790
|
Object.entries(templates).map(([file, override]) => [
|
|
@@ -1816,7 +1798,7 @@ function readOverrides(cwd) {
|
|
|
1816
1798
|
}
|
|
1817
1799
|
function readTemplate(stack, file) {
|
|
1818
1800
|
const path = join11(findPackageRoot(), "templates", stack, file);
|
|
1819
|
-
return existsSync11(path) ?
|
|
1801
|
+
return existsSync11(path) ? readFileSync9(path, "utf8") : null;
|
|
1820
1802
|
}
|
|
1821
1803
|
function asStringArray(value) {
|
|
1822
1804
|
if (!Array.isArray(value)) return [];
|
|
@@ -1838,7 +1820,7 @@ function addAgentRosterFindings(cwd, findings, rosterRelativePath = DEFAULT_AGEN
|
|
|
1838
1820
|
}
|
|
1839
1821
|
let roster;
|
|
1840
1822
|
try {
|
|
1841
|
-
const parsed = JSON.parse(
|
|
1823
|
+
const parsed = JSON.parse(readFileSync9(rosterPath, "utf8"));
|
|
1842
1824
|
if (!isRecord(parsed)) throw new Error("Roster must be a JSON object.");
|
|
1843
1825
|
const contractResult = AgentRosterContract.safeParse(parsed);
|
|
1844
1826
|
if (!contractResult.success) {
|
|
@@ -2033,7 +2015,7 @@ function addCouncilSessionRecordFindings(cwd, findings) {
|
|
|
2033
2015
|
for (const sessionFile of sessionFiles) {
|
|
2034
2016
|
const displayPath = `${COUNCIL_SESSION_DIR}/${sessionFile}`;
|
|
2035
2017
|
try {
|
|
2036
|
-
const parsed = JSON.parse(
|
|
2018
|
+
const parsed = JSON.parse(readFileSync9(join11(sessionsRoot, sessionFile), "utf8"));
|
|
2037
2019
|
const contractResult = CouncilSessionContract.safeParse(parsed);
|
|
2038
2020
|
if (!contractResult.success) {
|
|
2039
2021
|
invalidCount += 1;
|
|
@@ -2075,7 +2057,7 @@ function addSchemaFindings(cwd, findings, schemaRootRelativePath = ".agent-kit/s
|
|
|
2075
2057
|
continue;
|
|
2076
2058
|
}
|
|
2077
2059
|
try {
|
|
2078
|
-
const parsed = JSON.parse(
|
|
2060
|
+
const parsed = JSON.parse(readFileSync9(schemaPath, "utf8"));
|
|
2079
2061
|
if (!isRecord(parsed) || typeof parsed.$schema !== "string" || !isRecord(parsed.properties)) {
|
|
2080
2062
|
throw new Error("Schema file is missing JSON Schema metadata.");
|
|
2081
2063
|
}
|
|
@@ -2105,7 +2087,7 @@ function addAgentStudioFindings(cwd, findings) {
|
|
|
2105
2087
|
});
|
|
2106
2088
|
} else {
|
|
2107
2089
|
try {
|
|
2108
|
-
const parsed = JSON.parse(
|
|
2090
|
+
const parsed = JSON.parse(readFileSync9(contextPath, "utf8"));
|
|
2109
2091
|
const result = ProjectContextContract.safeParse(parsed);
|
|
2110
2092
|
if (!result.success) {
|
|
2111
2093
|
findings.push({
|
|
@@ -2182,7 +2164,7 @@ function addAgentStudioFindings(cwd, findings) {
|
|
|
2182
2164
|
const path = join11(cwd, relativePath);
|
|
2183
2165
|
if (!existsSync11(path)) continue;
|
|
2184
2166
|
try {
|
|
2185
|
-
const parsed = JSON.parse(
|
|
2167
|
+
const parsed = JSON.parse(readFileSync9(path, "utf8"));
|
|
2186
2168
|
const result = CorrectionRulesContract.safeParse(parsed);
|
|
2187
2169
|
if (!result.success) {
|
|
2188
2170
|
findings.push({
|
|
@@ -2209,7 +2191,7 @@ function addAgentStudioFindings(cwd, findings) {
|
|
|
2209
2191
|
}
|
|
2210
2192
|
const studioExportPath = join11(cwd, STUDIO_EXPORT_HTML);
|
|
2211
2193
|
if (existsSync11(studioExportPath)) {
|
|
2212
|
-
const exportHtml =
|
|
2194
|
+
const exportHtml = readFileSync9(studioExportPath, "utf8");
|
|
2213
2195
|
if (containsLikelySecret(exportHtml)) {
|
|
2214
2196
|
findings.push({
|
|
2215
2197
|
level: "fail",
|
|
@@ -2242,12 +2224,10 @@ function addAgentStudioFindings(cwd, findings) {
|
|
|
2242
2224
|
const sessionDir2 = sessionFile.replace(/[\\/]session\.json$/, "");
|
|
2243
2225
|
const normalizedSessionDir = sessionDir2.replace(/\\/g, "/");
|
|
2244
2226
|
const eventsRelative = `${COUNCIL_SESSION_DIR}/${normalizedSessionDir}/events.jsonl`;
|
|
2245
|
-
const indexRelative = `${COUNCIL_SESSION_DIR}/${normalizedSessionDir}/index.md`;
|
|
2246
|
-
const transcriptRelative = `${COUNCIL_SESSION_DIR}/${normalizedSessionDir}/transcript.md`;
|
|
2247
2227
|
const sessionDirPath = join11(sessionsRoot, sessionDir2);
|
|
2248
2228
|
let sessionResult = null;
|
|
2249
2229
|
try {
|
|
2250
|
-
sessionResult = StudioSessionContract.safeParse(JSON.parse(
|
|
2230
|
+
sessionResult = StudioSessionContract.safeParse(JSON.parse(readFileSync9(join11(sessionDirPath, "session.json"), "utf8")));
|
|
2251
2231
|
if (!sessionResult.success) {
|
|
2252
2232
|
findings.push({
|
|
2253
2233
|
level: "fail",
|
|
@@ -2276,7 +2256,7 @@ function addAgentStudioFindings(cwd, findings) {
|
|
|
2276
2256
|
});
|
|
2277
2257
|
continue;
|
|
2278
2258
|
}
|
|
2279
|
-
const eventText =
|
|
2259
|
+
const eventText = readFileSync9(eventsPath2, "utf8");
|
|
2280
2260
|
if (containsLikelySecret(eventText)) {
|
|
2281
2261
|
findings.push({
|
|
2282
2262
|
level: "fail",
|
|
@@ -2285,12 +2265,12 @@ function addAgentStudioFindings(cwd, findings) {
|
|
|
2285
2265
|
remediation: "Redact tokens, database URLs, env values, and private customer data from session logs."
|
|
2286
2266
|
});
|
|
2287
2267
|
}
|
|
2288
|
-
const eventLines = eventText.split(/\r?\n/).filter((
|
|
2268
|
+
const eventLines = eventText.split(/\r?\n/).filter((line2) => line2.trim().length > 0);
|
|
2289
2269
|
let validEvents = 0;
|
|
2290
2270
|
let verificationCount = 0;
|
|
2291
|
-
for (const [index,
|
|
2271
|
+
for (const [index, line2] of eventLines.entries()) {
|
|
2292
2272
|
try {
|
|
2293
|
-
const result = SessionEventContract.safeParse(JSON.parse(
|
|
2273
|
+
const result = SessionEventContract.safeParse(JSON.parse(line2));
|
|
2294
2274
|
if (!result.success) {
|
|
2295
2275
|
findings.push({
|
|
2296
2276
|
level: "fail",
|
|
@@ -2319,8 +2299,8 @@ function addAgentStudioFindings(cwd, findings) {
|
|
|
2319
2299
|
remediation: "Run agent-kit session render so humans can inspect the current agent transcript and handoffs."
|
|
2320
2300
|
});
|
|
2321
2301
|
} else {
|
|
2322
|
-
const indexText =
|
|
2323
|
-
const transcriptText =
|
|
2302
|
+
const indexText = readFileSync9(join11(sessionDirPath, "index.md"), "utf8");
|
|
2303
|
+
const transcriptText = readFileSync9(join11(sessionDirPath, "transcript.md"), "utf8");
|
|
2324
2304
|
if (containsLikelySecret(indexText) || containsLikelySecret(transcriptText)) {
|
|
2325
2305
|
findings.push({
|
|
2326
2306
|
level: "fail",
|
|
@@ -2477,7 +2457,7 @@ function addModelRoutingFindings(cwd, findings, routingRelativePath = DEFAULT_MO
|
|
|
2477
2457
|
}
|
|
2478
2458
|
let routing;
|
|
2479
2459
|
try {
|
|
2480
|
-
routing = JSON.parse(
|
|
2460
|
+
routing = JSON.parse(readFileSync9(routingPath, "utf8"));
|
|
2481
2461
|
} catch {
|
|
2482
2462
|
findings.push({
|
|
2483
2463
|
level: "warn",
|
|
@@ -2539,7 +2519,7 @@ function addTemplateHashFindings(cwd, findings) {
|
|
|
2539
2519
|
if (!existsSync11(targetPath)) continue;
|
|
2540
2520
|
const currentTemplate = readTemplate(manifest.stack, doc);
|
|
2541
2521
|
if (!currentTemplate) continue;
|
|
2542
|
-
const targetHash = sha256(
|
|
2522
|
+
const targetHash = sha256(readFileSync9(targetPath, "utf8"));
|
|
2543
2523
|
const currentTemplateHash = sha256(currentTemplate);
|
|
2544
2524
|
const installedTemplateHash = manifest.templateHashes?.[doc];
|
|
2545
2525
|
const override = overrides[doc];
|
|
@@ -2766,14 +2746,7 @@ function addUpgradeFindings(cwd, findings) {
|
|
|
2766
2746
|
});
|
|
2767
2747
|
}
|
|
2768
2748
|
}
|
|
2769
|
-
var STARTER_EVIDENCE_PATTERNS = [
|
|
2770
|
-
/\bTBD\b/i,
|
|
2771
|
-
/replace with real/i,
|
|
2772
|
-
/example_table/i,
|
|
2773
|
-
/describe the product/i,
|
|
2774
|
-
/document required/i,
|
|
2775
|
-
/pass\/fail\/skipped/i
|
|
2776
|
-
];
|
|
2749
|
+
var STARTER_EVIDENCE_PATTERNS = [/\bTBD\b/i, /replace with real/i, /example_table/i, /describe the product/i, /document required/i, /pass\/fail\/skipped/i];
|
|
2777
2750
|
var EVIDENCE_DOCS = [
|
|
2778
2751
|
"COUNCIL.md",
|
|
2779
2752
|
"SPEC.md",
|
|
@@ -2944,7 +2917,7 @@ function readPackageJson2(cwd) {
|
|
|
2944
2917
|
const path = join11(cwd, "package.json");
|
|
2945
2918
|
if (!existsSync11(path)) return null;
|
|
2946
2919
|
try {
|
|
2947
|
-
return JSON.parse(
|
|
2920
|
+
return JSON.parse(readFileSync9(path, "utf8"));
|
|
2948
2921
|
} catch {
|
|
2949
2922
|
return null;
|
|
2950
2923
|
}
|
|
@@ -2970,7 +2943,7 @@ function addProjectRealityFindings(cwd, findings, options = {}) {
|
|
|
2970
2943
|
});
|
|
2971
2944
|
} else {
|
|
2972
2945
|
const rlsFiles = sqlFiles.filter((file) => {
|
|
2973
|
-
const content =
|
|
2946
|
+
const content = readFileSync9(join11(migrationsDir, file), "utf8");
|
|
2974
2947
|
return /enable\s+row\s+level\s+security/i.test(content);
|
|
2975
2948
|
});
|
|
2976
2949
|
if (rlsFiles.length === 0) {
|
|
@@ -3020,7 +2993,7 @@ function addProjectRealityFindings(cwd, findings, options = {}) {
|
|
|
3020
2993
|
return /\.(ts|tsx|js|jsx|env|json)$/.test(file);
|
|
3021
2994
|
});
|
|
3022
2995
|
const secretHits = trackedSourceFiles.map((file) => {
|
|
3023
|
-
const content =
|
|
2996
|
+
const content = readFileSync9(join11(cwd, file), "utf8");
|
|
3024
2997
|
return containsLikelySecretForAudit(file, content) ? file : null;
|
|
3025
2998
|
}).filter((file) => file !== null).slice(0, 5);
|
|
3026
2999
|
if (secretHits.length > 0) {
|
|
@@ -3095,7 +3068,28 @@ function createAuditReport(cwd) {
|
|
|
3095
3068
|
}
|
|
3096
3069
|
|
|
3097
3070
|
// src/install/adapter-validate.ts
|
|
3098
|
-
var REQUIRED_COMMANDS = [
|
|
3071
|
+
var REQUIRED_COMMANDS = [
|
|
3072
|
+
"setup",
|
|
3073
|
+
"spec",
|
|
3074
|
+
"audit",
|
|
3075
|
+
"plan",
|
|
3076
|
+
"handoff",
|
|
3077
|
+
"frontend",
|
|
3078
|
+
"ui-audit",
|
|
3079
|
+
"ui-polish",
|
|
3080
|
+
"layout-cleanup",
|
|
3081
|
+
"responsive-cleanup",
|
|
3082
|
+
"accessibility-pass",
|
|
3083
|
+
"distinctiveness-pass",
|
|
3084
|
+
"screenshot-critique",
|
|
3085
|
+
"browser-qa",
|
|
3086
|
+
"test",
|
|
3087
|
+
"review",
|
|
3088
|
+
"security",
|
|
3089
|
+
"copy",
|
|
3090
|
+
"ship",
|
|
3091
|
+
"upgrade"
|
|
3092
|
+
];
|
|
3099
3093
|
var REQUIRED_SOURCE_REFERENCES = ["AGENTS.md", ".agent-kit/agent-roster.json", "QUALITY_GATES.md"];
|
|
3100
3094
|
function summary(findings) {
|
|
3101
3095
|
return {
|
|
@@ -3109,7 +3103,7 @@ function report(target, findings) {
|
|
|
3109
3103
|
}
|
|
3110
3104
|
function readJson(path) {
|
|
3111
3105
|
try {
|
|
3112
|
-
return JSON.parse(
|
|
3106
|
+
return JSON.parse(readFileSync10(path, "utf8"));
|
|
3113
3107
|
} catch {
|
|
3114
3108
|
return null;
|
|
3115
3109
|
}
|
|
@@ -3170,11 +3164,11 @@ function validateAntigravityCommands(layout, findings) {
|
|
|
3170
3164
|
level: "fail",
|
|
3171
3165
|
area: "commands",
|
|
3172
3166
|
message: `Missing Antigravity command ${relativePath}.`,
|
|
3173
|
-
remediation: "Restore the full native command set
|
|
3167
|
+
remediation: "Restore the full native command set, including frontend and UI improvement commands."
|
|
3174
3168
|
});
|
|
3175
3169
|
continue;
|
|
3176
3170
|
}
|
|
3177
|
-
const text =
|
|
3171
|
+
const text = readFileSync10(path, "utf8");
|
|
3178
3172
|
addSecretFinding(relativePath, text, findings);
|
|
3179
3173
|
const name = commandField(text, "name");
|
|
3180
3174
|
const description = commandField(text, "description");
|
|
@@ -3263,10 +3257,11 @@ function validateAntigravityPlugin(layout, findings) {
|
|
|
3263
3257
|
for (const entry of [...commands, ...skills]) {
|
|
3264
3258
|
const path = typeof entry.path === "string" ? entry.path : "";
|
|
3265
3259
|
if (!path || !isSafeRelativePath(path)) {
|
|
3260
|
+
const entryName = typeof entry.name === "string" ? entry.name : "unknown";
|
|
3266
3261
|
findings.push({
|
|
3267
3262
|
level: "fail",
|
|
3268
3263
|
area: "manifest",
|
|
3269
|
-
message: `plugin.json has an unsafe or missing relative path for ${
|
|
3264
|
+
message: `plugin.json has an unsafe or missing relative path for ${entryName}.`,
|
|
3270
3265
|
remediation: "Use relative paths that stay inside the plugin/runtime skill bundle."
|
|
3271
3266
|
});
|
|
3272
3267
|
continue;
|
|
@@ -3281,7 +3276,7 @@ function validateAntigravityPlugin(layout, findings) {
|
|
|
3281
3276
|
});
|
|
3282
3277
|
}
|
|
3283
3278
|
}
|
|
3284
|
-
const pluginText =
|
|
3279
|
+
const pluginText = readFileSync10(pluginPath, "utf8");
|
|
3285
3280
|
addSecretFinding("plugin.json", pluginText, findings);
|
|
3286
3281
|
if (Array.isArray(plugin.sourceOfTruth) && plugin.sourceOfTruth.includes("AGENTS.md") && plugin.sourceOfTruth.includes(".agent-kit/agent-roster.json")) {
|
|
3287
3282
|
findings.push({
|
|
@@ -3314,7 +3309,7 @@ function validateRuntimeSkills(cwd, layout, findings) {
|
|
|
3314
3309
|
});
|
|
3315
3310
|
continue;
|
|
3316
3311
|
}
|
|
3317
|
-
const text =
|
|
3312
|
+
const text = readFileSync10(runtimePath, "utf8");
|
|
3318
3313
|
addSecretFinding(`${skillName}/SKILL.md`, text, findings);
|
|
3319
3314
|
if (!/^---\nname: .+\ndescription: .+\n---/m.test(text)) {
|
|
3320
3315
|
findings.push({
|
|
@@ -3363,7 +3358,7 @@ function validateAntigravity(cwd) {
|
|
|
3363
3358
|
}
|
|
3364
3359
|
]);
|
|
3365
3360
|
}
|
|
3366
|
-
const adapterDoc = existsSync12(layout.adapterDocPath) ?
|
|
3361
|
+
const adapterDoc = existsSync12(layout.adapterDocPath) ? readFileSync10(layout.adapterDocPath, "utf8") : "";
|
|
3367
3362
|
if (!adapterDoc) {
|
|
3368
3363
|
findings.push({
|
|
3369
3364
|
level: "fail",
|
|
@@ -3439,7 +3434,7 @@ function validateBasicAdapter(cwd, target) {
|
|
|
3439
3434
|
});
|
|
3440
3435
|
continue;
|
|
3441
3436
|
}
|
|
3442
|
-
const text =
|
|
3437
|
+
const text = readFileSync10(path, "utf8");
|
|
3443
3438
|
addSecretFinding(relativePath, text, findings);
|
|
3444
3439
|
if (!text.includes("AGENTS.md") && !text.includes("MODEL_ROUTING.md")) {
|
|
3445
3440
|
findings.push({
|
|
@@ -3464,7 +3459,7 @@ function validateBasicAdapter(cwd, target) {
|
|
|
3464
3459
|
}
|
|
3465
3460
|
function readAssistantAdaptersDoc(cwd) {
|
|
3466
3461
|
const path = join12(cwd, "ASSISTANT_ADAPTERS.md");
|
|
3467
|
-
return existsSync12(path) ?
|
|
3462
|
+
return existsSync12(path) ? readFileSync10(path, "utf8") : "";
|
|
3468
3463
|
}
|
|
3469
3464
|
function adaptersRowIsActive(doc, toolLabel) {
|
|
3470
3465
|
return assistantAdapterRowIsActive(doc, toolLabel);
|
|
@@ -3482,7 +3477,7 @@ function validateInstalledIdeAdapter(cwd, target) {
|
|
|
3482
3477
|
remediation: "Run agent-kit init or agent-kit init --activate cursor."
|
|
3483
3478
|
});
|
|
3484
3479
|
} else {
|
|
3485
|
-
addSecretFinding(".cursor/rules/cursor-agent-kit.mdc",
|
|
3480
|
+
addSecretFinding(".cursor/rules/cursor-agent-kit.mdc", readFileSync10(rulesPath, "utf8"), findings);
|
|
3486
3481
|
}
|
|
3487
3482
|
const plannerAgent = join12(cwd, ".cursor/agents/planner.md");
|
|
3488
3483
|
if (existsSync12(plannerAgent)) {
|
|
@@ -3585,7 +3580,7 @@ function validatePackage(cwd) {
|
|
|
3585
3580
|
findings.push(...validateAntigravity(cwd).findings);
|
|
3586
3581
|
for (const doc of ["README.md", "DOCS.md", "SPEC.md", "DECISIONS.md", "QUALITY_GATES.md", "TESTING.md", "UPGRADE.md"]) {
|
|
3587
3582
|
const path = join12(cwd, doc);
|
|
3588
|
-
const text = existsSync12(path) ?
|
|
3583
|
+
const text = existsSync12(path) ? readFileSync10(path, "utf8") : "";
|
|
3589
3584
|
const lower = text.toLowerCase();
|
|
3590
3585
|
if (!lower.includes("antigravity") && !lower.includes("runtime command") && !lower.includes("runtime adapter")) {
|
|
3591
3586
|
findings.push({
|
|
@@ -3637,12 +3632,12 @@ function validatePackage(cwd) {
|
|
|
3637
3632
|
}
|
|
3638
3633
|
|
|
3639
3634
|
// src/install/diff.ts
|
|
3640
|
-
import { existsSync as existsSync13, readFileSync as
|
|
3635
|
+
import { existsSync as existsSync13, readFileSync as readFileSync11 } from "fs";
|
|
3641
3636
|
import { join as join13 } from "path";
|
|
3642
3637
|
function statusForTextFile(target, template) {
|
|
3643
3638
|
if (!existsSync13(target)) return "missing";
|
|
3644
|
-
const targetHash = sha256(
|
|
3645
|
-
const templateHash = sha256(
|
|
3639
|
+
const targetHash = sha256(readFileSync11(target, "utf8"));
|
|
3640
|
+
const templateHash = sha256(readFileSync11(template, "utf8"));
|
|
3646
3641
|
return targetHash === templateHash ? "unchanged" : "changed";
|
|
3647
3642
|
}
|
|
3648
3643
|
function diffProject(cwd, stack = "next-supabase") {
|
|
@@ -3711,10 +3706,176 @@ function diffProject(cwd, stack = "next-supabase") {
|
|
|
3711
3706
|
return result;
|
|
3712
3707
|
}
|
|
3713
3708
|
|
|
3709
|
+
// src/install/update.ts
|
|
3710
|
+
import { existsSync as existsSync14, readFileSync as readFileSync12 } from "fs";
|
|
3711
|
+
import { join as join14, relative as relative2 } from "path";
|
|
3712
|
+
function planFileUpdate(cwd, input) {
|
|
3713
|
+
const sourceContent = readFileSync12(input.sourcePath, "utf8");
|
|
3714
|
+
const sourceHash = sha256(sourceContent);
|
|
3715
|
+
const targetPath = resolveInside(cwd, input.target);
|
|
3716
|
+
if (!existsSync14(targetPath)) {
|
|
3717
|
+
return { target: input.target, action: "created", reason: "File is missing locally.", sourceContent };
|
|
3718
|
+
}
|
|
3719
|
+
const localHash = sha256(readFileSync12(targetPath, "utf8"));
|
|
3720
|
+
if (localHash === sourceHash) {
|
|
3721
|
+
return { target: input.target, action: "unchanged", reason: "File already matches the current template.", sourceContent };
|
|
3722
|
+
}
|
|
3723
|
+
if (input.installedHash && localHash === input.installedHash) {
|
|
3724
|
+
return { target: input.target, action: "updated", reason: "File was unmodified since install; applied the newer template.", sourceContent };
|
|
3725
|
+
}
|
|
3726
|
+
if (input.force) {
|
|
3727
|
+
return { target: input.target, action: "overwritten", reason: "Local changes overwritten because --force was used.", sourceContent };
|
|
3728
|
+
}
|
|
3729
|
+
if (input.installedHash && input.installedHash === sourceHash) {
|
|
3730
|
+
return { target: input.target, action: "kept-local", reason: "File is locally customized and the template has not changed.", sourceContent };
|
|
3731
|
+
}
|
|
3732
|
+
return {
|
|
3733
|
+
target: input.target,
|
|
3734
|
+
action: "conflict",
|
|
3735
|
+
reason: "File is locally customized and the bundled template changed; review the conflict copy.",
|
|
3736
|
+
sourceContent
|
|
3737
|
+
};
|
|
3738
|
+
}
|
|
3739
|
+
function writeConflictCopy(cwd, target, content) {
|
|
3740
|
+
const conflictRoot = join14(cwd, ".agent-kit", "conflicts");
|
|
3741
|
+
const safeName = `${Date.now()}-${target.replace(/[^a-zA-Z0-9_.-]/g, "_")}`;
|
|
3742
|
+
const conflictPath = join14(conflictRoot, safeName);
|
|
3743
|
+
writeText(conflictPath, content);
|
|
3744
|
+
return relative2(cwd, conflictPath).replace(/\\/g, "/");
|
|
3745
|
+
}
|
|
3746
|
+
function updateProject(options) {
|
|
3747
|
+
const cwd = options.cwd;
|
|
3748
|
+
const force = Boolean(options.force);
|
|
3749
|
+
const dryRun = Boolean(options.dryRun);
|
|
3750
|
+
const manifest = readManifest(cwd);
|
|
3751
|
+
if (!manifest) {
|
|
3752
|
+
if (dryRun) {
|
|
3753
|
+
throw new Error("No .agent-kit/manifest.json found. Run agent-kit init first (or run update without --dry-run to install).");
|
|
3754
|
+
}
|
|
3755
|
+
const initResult = initProject({ cwd, force });
|
|
3756
|
+
const files2 = [
|
|
3757
|
+
...initResult.copied.map((target) => ({ target, action: "created", reason: "Installed by init fallback." })),
|
|
3758
|
+
...initResult.unchanged.map((target) => ({ target, action: "unchanged", reason: "Already matched the template." })),
|
|
3759
|
+
...initResult.overwritten.map((target) => ({ target, action: "overwritten", reason: "Overwritten by init --force fallback." })),
|
|
3760
|
+
...initResult.conflicts.map((entry) => {
|
|
3761
|
+
const [target, conflictPath] = entry.split(" -> ");
|
|
3762
|
+
return {
|
|
3763
|
+
target: target ?? entry,
|
|
3764
|
+
action: "conflict",
|
|
3765
|
+
reason: "Local file differed from the template during init fallback.",
|
|
3766
|
+
...conflictPath ? { conflictPath } : {}
|
|
3767
|
+
};
|
|
3768
|
+
})
|
|
3769
|
+
];
|
|
3770
|
+
return {
|
|
3771
|
+
dryRun,
|
|
3772
|
+
files: files2,
|
|
3773
|
+
libraryFoldersRefreshed: [...LIBRARY_FOLDERS],
|
|
3774
|
+
manifestPath: ".agent-kit/manifest.json",
|
|
3775
|
+
summary: summarize(files2)
|
|
3776
|
+
};
|
|
3777
|
+
}
|
|
3778
|
+
const packageRoot = findPackageRoot();
|
|
3779
|
+
const stack = manifest.stack ?? "next-supabase";
|
|
3780
|
+
const templateRoot = join14(packageRoot, "templates", stack);
|
|
3781
|
+
if (!existsSync14(templateRoot)) {
|
|
3782
|
+
throw new Error(`Unsupported stack profile in manifest: ${stack}`);
|
|
3783
|
+
}
|
|
3784
|
+
const files = [];
|
|
3785
|
+
const templateHashes = {};
|
|
3786
|
+
const plans = [];
|
|
3787
|
+
for (const doc of ROOT_DOCS) {
|
|
3788
|
+
const sourcePath = join14(templateRoot, doc);
|
|
3789
|
+
templateHashes[doc] = sha256(readFileSync12(sourcePath, "utf8"));
|
|
3790
|
+
plans.push(
|
|
3791
|
+
planFileUpdate(cwd, {
|
|
3792
|
+
target: doc,
|
|
3793
|
+
sourcePath,
|
|
3794
|
+
installedHash: manifest.templateHashes?.[doc],
|
|
3795
|
+
force
|
|
3796
|
+
})
|
|
3797
|
+
);
|
|
3798
|
+
}
|
|
3799
|
+
for (const adapter2 of CURSOR_ADAPTER_FILES) {
|
|
3800
|
+
plans.push(
|
|
3801
|
+
planFileUpdate(cwd, {
|
|
3802
|
+
target: adapter2.target,
|
|
3803
|
+
sourcePath: join14(packageRoot, adapter2.source),
|
|
3804
|
+
installedHash: void 0,
|
|
3805
|
+
force
|
|
3806
|
+
})
|
|
3807
|
+
);
|
|
3808
|
+
}
|
|
3809
|
+
plans.push(
|
|
3810
|
+
planFileUpdate(cwd, {
|
|
3811
|
+
target: DEFAULT_AGENT_ROSTER_TARGET,
|
|
3812
|
+
sourcePath: join14(packageRoot, DEFAULT_AGENT_ROSTER_SOURCE),
|
|
3813
|
+
installedHash: void 0,
|
|
3814
|
+
force
|
|
3815
|
+
}),
|
|
3816
|
+
planFileUpdate(cwd, {
|
|
3817
|
+
target: DEFAULT_MODEL_ROUTING_TARGET,
|
|
3818
|
+
sourcePath: join14(packageRoot, DEFAULT_MODEL_ROUTING_SOURCE),
|
|
3819
|
+
installedHash: void 0,
|
|
3820
|
+
force
|
|
3821
|
+
})
|
|
3822
|
+
);
|
|
3823
|
+
for (const plan of plans) {
|
|
3824
|
+
const { sourceContent, ...fileResult } = plan;
|
|
3825
|
+
if (!dryRun) {
|
|
3826
|
+
if (plan.action === "created" || plan.action === "updated" || plan.action === "overwritten") {
|
|
3827
|
+
writeText(resolveInside(cwd, plan.target), sourceContent);
|
|
3828
|
+
} else if (plan.action === "conflict") {
|
|
3829
|
+
fileResult.conflictPath = writeConflictCopy(cwd, plan.target, sourceContent);
|
|
3830
|
+
}
|
|
3831
|
+
}
|
|
3832
|
+
files.push(fileResult);
|
|
3833
|
+
}
|
|
3834
|
+
if (!dryRun) {
|
|
3835
|
+
ensureDir(join14(cwd, ".agent-kit"));
|
|
3836
|
+
for (const folder of LIBRARY_FOLDERS) {
|
|
3837
|
+
copyDirectory(join14(packageRoot, folder), join14(cwd, ".agent-kit", folder));
|
|
3838
|
+
}
|
|
3839
|
+
const updatedManifest = {
|
|
3840
|
+
packageName: PACKAGE_NAME,
|
|
3841
|
+
packageVersion: PACKAGE_VERSION,
|
|
3842
|
+
stack,
|
|
3843
|
+
installedAt: manifest.installedAt,
|
|
3844
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3845
|
+
docs: [...ROOT_DOCS],
|
|
3846
|
+
libraryFolders: [...LIBRARY_FOLDERS],
|
|
3847
|
+
agentRoster: DEFAULT_AGENT_ROSTER_TARGET,
|
|
3848
|
+
modelRouting: DEFAULT_MODEL_ROUTING_TARGET,
|
|
3849
|
+
templateHashes
|
|
3850
|
+
};
|
|
3851
|
+
writeText(join14(cwd, ".agent-kit", "manifest.json"), `${JSON.stringify(updatedManifest, null, 2)}
|
|
3852
|
+
`);
|
|
3853
|
+
}
|
|
3854
|
+
return {
|
|
3855
|
+
dryRun,
|
|
3856
|
+
files,
|
|
3857
|
+
libraryFoldersRefreshed: [...LIBRARY_FOLDERS],
|
|
3858
|
+
manifestPath: ".agent-kit/manifest.json",
|
|
3859
|
+
summary: summarize(files)
|
|
3860
|
+
};
|
|
3861
|
+
}
|
|
3862
|
+
function summarize(files) {
|
|
3863
|
+
const summary2 = {
|
|
3864
|
+
created: 0,
|
|
3865
|
+
updated: 0,
|
|
3866
|
+
unchanged: 0,
|
|
3867
|
+
"kept-local": 0,
|
|
3868
|
+
conflict: 0,
|
|
3869
|
+
overwritten: 0
|
|
3870
|
+
};
|
|
3871
|
+
for (const file of files) summary2[file.action] += 1;
|
|
3872
|
+
return summary2;
|
|
3873
|
+
}
|
|
3874
|
+
|
|
3714
3875
|
// src/research/discover.ts
|
|
3715
3876
|
import { Octokit } from "@octokit/rest";
|
|
3716
|
-
import { readFileSync as
|
|
3717
|
-
import { join as
|
|
3877
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
3878
|
+
import { join as join15 } from "path";
|
|
3718
3879
|
|
|
3719
3880
|
// src/research/config.ts
|
|
3720
3881
|
import { z as z2 } from "zod";
|
|
@@ -3739,8 +3900,8 @@ var researchConfigSchema = z2.object({
|
|
|
3739
3900
|
// src/research/discover.ts
|
|
3740
3901
|
async function discoverRepos(options) {
|
|
3741
3902
|
const packageRoot = findPackageRoot();
|
|
3742
|
-
const configPath =
|
|
3743
|
-
const config = researchConfigSchema.parse(JSON.parse(
|
|
3903
|
+
const configPath = join15(packageRoot, "research", "scan-config.json");
|
|
3904
|
+
const config = researchConfigSchema.parse(JSON.parse(readFileSync13(configPath, "utf8")));
|
|
3744
3905
|
const token = options.token ?? process.env.GITHUB_TOKEN;
|
|
3745
3906
|
if (!token) {
|
|
3746
3907
|
throw new Error("GITHUB_TOKEN is required for GitHub API research discovery.");
|
|
@@ -3801,20 +3962,20 @@ async function discoverRepos(options) {
|
|
|
3801
3962
|
}
|
|
3802
3963
|
}
|
|
3803
3964
|
const candidates = [...deduped.values()].slice(0, maxRepos);
|
|
3804
|
-
const output = options.output ??
|
|
3965
|
+
const output = options.output ?? join15(options.cwd, "research", "repo-candidates.json");
|
|
3805
3966
|
writeText(output, `${JSON.stringify(candidates, null, 2)}
|
|
3806
3967
|
`);
|
|
3807
3968
|
return candidates;
|
|
3808
3969
|
}
|
|
3809
3970
|
|
|
3810
3971
|
// src/research/scan.ts
|
|
3811
|
-
import { existsSync as existsSync16, mkdirSync as mkdirSync2, readFileSync as
|
|
3812
|
-
import { join as
|
|
3972
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync2, readFileSync as readFileSync15, rmSync } from "fs";
|
|
3973
|
+
import { join as join17 } from "path";
|
|
3813
3974
|
import { simpleGit } from "simple-git";
|
|
3814
3975
|
|
|
3815
3976
|
// src/research/analyze.ts
|
|
3816
|
-
import { existsSync as existsSync15, readFileSync as
|
|
3817
|
-
import { join as
|
|
3977
|
+
import { existsSync as existsSync15, readFileSync as readFileSync14 } from "fs";
|
|
3978
|
+
import { join as join16 } from "path";
|
|
3818
3979
|
function normalizeRelativePath(file) {
|
|
3819
3980
|
return file.replace(/\\/g, "/");
|
|
3820
3981
|
}
|
|
@@ -3822,8 +3983,8 @@ function hasFile(files, matcher) {
|
|
|
3822
3983
|
return files.some((file) => matcher.test(normalizeRelativePath(file)));
|
|
3823
3984
|
}
|
|
3824
3985
|
function fileText(root, file) {
|
|
3825
|
-
const path =
|
|
3826
|
-
return existsSync15(path) ?
|
|
3986
|
+
const path = join16(root, file);
|
|
3987
|
+
return existsSync15(path) ? readFileSync14(path, "utf8") : "";
|
|
3827
3988
|
}
|
|
3828
3989
|
function textIncludes(root, files, matcher, terms) {
|
|
3829
3990
|
const lowerTerms = terms.map((term) => term.toLowerCase());
|
|
@@ -3954,24 +4115,24 @@ ${finding.impactOnKit.map((item) => `- ${item}`).join("\n")}
|
|
|
3954
4115
|
`;
|
|
3955
4116
|
}
|
|
3956
4117
|
async function scanRepos(options) {
|
|
3957
|
-
const candidatesPath = options.candidatesPath ??
|
|
4118
|
+
const candidatesPath = options.candidatesPath ?? join17(options.cwd, "research", "repo-candidates.json");
|
|
3958
4119
|
if (!existsSync16(candidatesPath)) {
|
|
3959
4120
|
throw new Error(`Candidates file not found: ${candidatesPath}`);
|
|
3960
4121
|
}
|
|
3961
|
-
const candidates = JSON.parse(
|
|
3962
|
-
const workdir = options.workdir ??
|
|
4122
|
+
const candidates = JSON.parse(readFileSync15(candidatesPath, "utf8"));
|
|
4123
|
+
const workdir = options.workdir ?? join17(options.cwd, "research", "workdir");
|
|
3963
4124
|
mkdirSync2(workdir, { recursive: true });
|
|
3964
|
-
mkdirSync2(
|
|
4125
|
+
mkdirSync2(join17(options.cwd, "research", "findings"), { recursive: true });
|
|
3965
4126
|
const findings = [];
|
|
3966
4127
|
const git = simpleGit();
|
|
3967
4128
|
for (const candidate of candidates) {
|
|
3968
4129
|
const repoSlug = candidate.fullName.replace("/", "__");
|
|
3969
|
-
const repoPath =
|
|
4130
|
+
const repoPath = join17(workdir, repoSlug);
|
|
3970
4131
|
if (existsSync16(repoPath)) rmSync(repoPath, { recursive: true, force: true });
|
|
3971
4132
|
await git.raw(["clone", "--depth", "1", candidate.htmlUrl, repoPath]);
|
|
3972
4133
|
const finding = analyzeRepository(candidate, repoPath);
|
|
3973
4134
|
findings.push(finding);
|
|
3974
|
-
writeText(
|
|
4135
|
+
writeText(join17(options.cwd, "research", "findings", `${repoSlug}.md`), findingToMarkdown(finding));
|
|
3975
4136
|
if (!options.keepClones) {
|
|
3976
4137
|
rmSync(repoPath, { recursive: true, force: true });
|
|
3977
4138
|
}
|
|
@@ -3980,8 +4141,8 @@ async function scanRepos(options) {
|
|
|
3980
4141
|
}
|
|
3981
4142
|
|
|
3982
4143
|
// src/research/summarize.ts
|
|
3983
|
-
import { existsSync as existsSync17, readFileSync as
|
|
3984
|
-
import { join as
|
|
4144
|
+
import { existsSync as existsSync17, readFileSync as readFileSync16, readdirSync as readdirSync3 } from "fs";
|
|
4145
|
+
import { join as join18 } from "path";
|
|
3985
4146
|
var SUMMARY_TARGETS = {
|
|
3986
4147
|
"nextjs-patterns": {
|
|
3987
4148
|
title: "Next.js Patterns",
|
|
@@ -4043,7 +4204,7 @@ function sectionBullets(text, start, end) {
|
|
|
4043
4204
|
const afterStart = text.slice(startIndex + start.length);
|
|
4044
4205
|
const endIndex = afterStart.indexOf(end);
|
|
4045
4206
|
const section = endIndex === -1 ? afterStart : afterStart.slice(0, endIndex);
|
|
4046
|
-
return section.split("\n").map((
|
|
4207
|
+
return section.split("\n").map((line2) => line2.trim()).filter((line2) => line2.startsWith("- ") && !line2.includes("None detected")).map((line2) => line2.slice(2));
|
|
4047
4208
|
}
|
|
4048
4209
|
function parseFinding(file, text) {
|
|
4049
4210
|
const fullName = text.match(/^# Repo Finding: (.+)$/m)?.[1];
|
|
@@ -4084,12 +4245,12 @@ function renderRepoList(findings, scoreKeys) {
|
|
|
4084
4245
|
return findings.slice().sort((a, b) => scoreFor(b, scoreKeys) - scoreFor(a, scoreKeys) || b.totalScore - a.totalScore || b.stars - a.stars).slice(0, 12).map((finding) => `- ${finding.fullName} (${finding.category}) - focus score ${scoreFor(finding, scoreKeys)}, total ${finding.totalScore}/${maxTotalScore}`).join("\n");
|
|
4085
4246
|
}
|
|
4086
4247
|
function summarizeFindings(cwd) {
|
|
4087
|
-
const findingsDir =
|
|
4248
|
+
const findingsDir = join18(cwd, "research", "findings");
|
|
4088
4249
|
if (!existsSync17(findingsDir)) {
|
|
4089
4250
|
throw new Error("No research/findings directory exists. Run agent-kit research scan first.");
|
|
4090
4251
|
}
|
|
4091
4252
|
const findingFiles = readdirSync3(findingsDir).filter((file) => file.endsWith(".md"));
|
|
4092
|
-
const findings = findingFiles.map((file) => parseFinding(file,
|
|
4253
|
+
const findings = findingFiles.map((file) => parseFinding(file, readFileSync16(join18(findingsDir, file), "utf8"))).filter((finding) => finding !== null);
|
|
4093
4254
|
const categoryCounts = countBy(findings.map((finding) => finding.category));
|
|
4094
4255
|
const outputs = [];
|
|
4095
4256
|
const overview = `# Research Scan Overview
|
|
@@ -4108,13 +4269,13 @@ ${countBy(findings.flatMap((finding) => finding.strongPractices)).slice(0, 12).m
|
|
|
4108
4269
|
## Most Repeated Gaps
|
|
4109
4270
|
${countBy(findings.flatMap((finding) => finding.weakPractices)).slice(0, 12).map(([practice, count]) => `- ${practice} (${count})`).join("\n")}
|
|
4110
4271
|
`;
|
|
4111
|
-
const overviewPath =
|
|
4272
|
+
const overviewPath = join18(cwd, "research", "summaries", "scan-overview.md");
|
|
4112
4273
|
writeText(overviewPath, overview);
|
|
4113
4274
|
outputs.push(overviewPath);
|
|
4114
4275
|
for (const [target, config] of Object.entries(SUMMARY_TARGETS)) {
|
|
4115
4276
|
const categories = config.categories;
|
|
4116
4277
|
const scopedFindings = findings.filter((finding) => categories.includes(finding.category));
|
|
4117
|
-
const path =
|
|
4278
|
+
const path = join18(cwd, "research", "summaries", `${target}.md`);
|
|
4118
4279
|
const summary2 = `# ${config.title}
|
|
4119
4280
|
|
|
4120
4281
|
Generated from ${scopedFindings.length} relevant repository findings.
|
|
@@ -4155,12 +4316,19 @@ Review the generated research summaries, then convert repeated best practices in
|
|
|
4155
4316
|
|
|
4156
4317
|
Do not copy source code from scanned repositories. Adopt only generalized practices with clear rationale.
|
|
4157
4318
|
`;
|
|
4158
|
-
const path =
|
|
4319
|
+
const path = join18(cwd, "research", "proposed-updates.md");
|
|
4159
4320
|
writeText(path, output);
|
|
4160
4321
|
return path;
|
|
4161
4322
|
}
|
|
4162
4323
|
|
|
4163
4324
|
// src/studio/corrections.ts
|
|
4325
|
+
var VALID_CORRECTION_SCOPES = ["session", "project", "agent", "upstream-proposal"];
|
|
4326
|
+
function parseCorrectionScope(scope) {
|
|
4327
|
+
if (typeof scope === "string" && VALID_CORRECTION_SCOPES.includes(scope)) {
|
|
4328
|
+
return scope;
|
|
4329
|
+
}
|
|
4330
|
+
throw new Error(`Invalid correction scope: expected one of ${VALID_CORRECTION_SCOPES.join(", ")}`);
|
|
4331
|
+
}
|
|
4164
4332
|
function fileForScope(scope) {
|
|
4165
4333
|
if (scope === "agent") return AGENT_RULES_JSON;
|
|
4166
4334
|
if (scope === "upstream-proposal") return UPSTREAM_PROPOSALS_JSON;
|
|
@@ -4184,14 +4352,15 @@ function ensureCorrectionFiles(cwd) {
|
|
|
4184
4352
|
}
|
|
4185
4353
|
}
|
|
4186
4354
|
function addCorrection(cwd, options) {
|
|
4355
|
+
const scope = parseCorrectionScope(options.scope);
|
|
4187
4356
|
ensureCorrectionFiles(cwd);
|
|
4188
|
-
const targetPath = fileForScope(
|
|
4357
|
+
const targetPath = fileForScope(scope);
|
|
4189
4358
|
const rules = readCorrectionRules(cwd, targetPath);
|
|
4190
4359
|
const id = options.id ?? safeSlug(options.text).slice(0, 48);
|
|
4191
4360
|
const rule = {
|
|
4192
4361
|
id,
|
|
4193
|
-
scope
|
|
4194
|
-
status:
|
|
4362
|
+
scope,
|
|
4363
|
+
status: scope === "upstream-proposal" ? "proposed" : "active",
|
|
4195
4364
|
text: redactSensitive(options.text),
|
|
4196
4365
|
...options.agentId ? { agentId: options.agentId, appliesToAgents: [options.agentId] } : {},
|
|
4197
4366
|
...options.sourceSessionId ? { sourceSessionId: options.sourceSessionId } : {},
|
|
@@ -4264,8 +4433,8 @@ function proposeCorrectionUpstream(cwd, id) {
|
|
|
4264
4433
|
}
|
|
4265
4434
|
|
|
4266
4435
|
// src/studio/session.ts
|
|
4267
|
-
import { existsSync as existsSync18, readFileSync as
|
|
4268
|
-
import { join as
|
|
4436
|
+
import { existsSync as existsSync18, readFileSync as readFileSync17, readdirSync as readdirSync4, statSync as statSync2 } from "fs";
|
|
4437
|
+
import { join as join19 } from "path";
|
|
4269
4438
|
function sessionDir(sessionId) {
|
|
4270
4439
|
return `${COUNCIL_SESSIONS_DIR}/${safeSlug(sessionId)}`;
|
|
4271
4440
|
}
|
|
@@ -4322,9 +4491,9 @@ function startSession(cwd, options) {
|
|
|
4322
4491
|
return { sessionId, sessionPath: sessionDir(sessionId) };
|
|
4323
4492
|
}
|
|
4324
4493
|
function listSessions(cwd) {
|
|
4325
|
-
const root =
|
|
4494
|
+
const root = join19(cwd, COUNCIL_SESSIONS_DIR);
|
|
4326
4495
|
if (!existsSync18(root)) return [];
|
|
4327
|
-
return readdirSync4(root).filter((entry) => entry !== "active").map((entry) =>
|
|
4496
|
+
return readdirSync4(root).filter((entry) => entry !== "active").map((entry) => join19(root, entry, "session.json")).filter((path) => existsSync18(path) && statSync2(path).isFile()).map((path) => StudioSessionContract.parse(JSON.parse(readFileSync17(path, "utf8")))).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
4328
4497
|
}
|
|
4329
4498
|
function getActiveSessionId(cwd) {
|
|
4330
4499
|
const active = readTextFile(cwd, ACTIVE_SESSION_FILE)?.trim();
|
|
@@ -4581,8 +4750,8 @@ function renderSessionTranscript(session2, events) {
|
|
|
4581
4750
|
}
|
|
4582
4751
|
const sections = [...byAgent.entries()].map(([agentId, agentEvents]) => {
|
|
4583
4752
|
const rows = agentEvents.map((event) => {
|
|
4584
|
-
const
|
|
4585
|
-
return `- ${event.createdAt} \`${event.type}\`: ${escapeMarkdownText(
|
|
4753
|
+
const detail2 = event.text ?? event.decision ?? event.command ?? event.artifactPath ?? (event.outputName ? `${event.outputName}: ${event.outputStatus ?? ""}` : void 0) ?? event.status ?? "";
|
|
4754
|
+
return `- ${event.createdAt} \`${event.type}\`: ${escapeMarkdownText(detail2)}`;
|
|
4586
4755
|
});
|
|
4587
4756
|
return `## ${escapeMarkdownText(agentId)}
|
|
4588
4757
|
|
|
@@ -4745,7 +4914,9 @@ function renderCorrections(data) {
|
|
|
4745
4914
|
return `<table>
|
|
4746
4915
|
<thead><tr><th>Scope</th><th>Agent</th><th>Correction</th></tr></thead>
|
|
4747
4916
|
<tbody>
|
|
4748
|
-
${rules.map(
|
|
4917
|
+
${rules.map(
|
|
4918
|
+
(rule) => `<tr><td>${escapeHtml(rule.scope)}</td><td>${escapeHtml(rule.agentId ?? rule.appliesToAgents?.join(", ") ?? "all")}</td><td>${escapeHtml(rule.text)}</td></tr>`
|
|
4919
|
+
).join("\n")}
|
|
4749
4920
|
</tbody>
|
|
4750
4921
|
</table>`;
|
|
4751
4922
|
}
|
|
@@ -4794,13 +4965,16 @@ function renderAgentStreams(item) {
|
|
|
4794
4965
|
const agent = event.agentId ?? event.fromAgentId ?? "session";
|
|
4795
4966
|
byAgent.set(agent, [...byAgent.get(agent) ?? [], event]);
|
|
4796
4967
|
}
|
|
4797
|
-
return [...byAgent.entries()].map(
|
|
4968
|
+
return [...byAgent.entries()].map(
|
|
4969
|
+
([agent, events]) => `<details class="agent-stream"><summary>${escapeHtml(agent)} (${events.length})</summary><div class="stream-body">${renderEventList(events)}</div></details>`
|
|
4970
|
+
).join("\n");
|
|
4798
4971
|
}
|
|
4799
4972
|
function renderEventList(events) {
|
|
4800
4973
|
return `<ol class="event-list">${events.map((event) => `<li><time>${escapeHtml(event.createdAt)}</time> <code>${escapeHtml(event.type)}</code>: ${escapeHtml(eventDetail(event))}</li>`).join("\n")}</ol>`;
|
|
4801
4974
|
}
|
|
4802
4975
|
function eventDetail(event) {
|
|
4803
|
-
if (event.type === "handoff")
|
|
4976
|
+
if (event.type === "handoff")
|
|
4977
|
+
return `${event.fromAgentId ?? "unknown"} -> ${event.toAgentId ?? "unknown"}: ${event.decision ?? ""} Risk: ${event.risk ?? ""}`;
|
|
4804
4978
|
if (event.type === "required_output_updated") return `${event.outputName ?? "output"}: ${event.outputStatus ?? "unknown"}`;
|
|
4805
4979
|
return event.text ?? event.decision ?? event.command ?? event.artifactPath ?? event.status ?? "";
|
|
4806
4980
|
}
|
|
@@ -4871,28 +5045,6 @@ function openBrowser(url) {
|
|
|
4871
5045
|
|
|
4872
5046
|
// src/studio/setup-init.ts
|
|
4873
5047
|
import { createInterface } from "readline";
|
|
4874
|
-
function formatInitSummary(result) {
|
|
4875
|
-
const lines = [
|
|
4876
|
-
`${PACKAGE_NAME} v${PACKAGE_VERSION} installed.`,
|
|
4877
|
-
"",
|
|
4878
|
-
`Created/updated: ${result.copied.length} file(s)`,
|
|
4879
|
-
`Unchanged: ${result.unchanged.length} file(s)`
|
|
4880
|
-
];
|
|
4881
|
-
if (result.conflicts.length > 0) {
|
|
4882
|
-
lines.push(`Conflicts to review: ${result.conflicts.length} \u2192 see .agent-kit/conflicts/`);
|
|
4883
|
-
}
|
|
4884
|
-
if (result.contextPath) {
|
|
4885
|
-
lines.push(`Project context: ${result.contextPath}`);
|
|
4886
|
-
}
|
|
4887
|
-
if (result.activation?.activated.length) {
|
|
4888
|
-
lines.push(`IDE activation: ${result.activation.activated.join(", ")}`);
|
|
4889
|
-
}
|
|
4890
|
-
if ([...result.copied, ...result.unchanged].some((path) => path.includes("agent-kit-audit.yml"))) {
|
|
4891
|
-
lines.push("CI template: .github/workflows/agent-kit-audit.yml");
|
|
4892
|
-
}
|
|
4893
|
-
lines.push("", "Next: teach agents about your project with the setup wizard (~5 min).", " agent-kit setup --open");
|
|
4894
|
-
return lines.join("\n");
|
|
4895
|
-
}
|
|
4896
5048
|
async function promptStartSetup(defaultYes = true) {
|
|
4897
5049
|
if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
|
|
4898
5050
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -4914,7 +5066,7 @@ import { createServer } from "http";
|
|
|
4914
5066
|
// src/studio/setup-form.ts
|
|
4915
5067
|
var RECOMMENDED_SUPABASE_AUTH = "Supabase Auth with server-set session cookies via @supabase/ssr. Authorization is enforced in Postgres RLS for private tables, not only in UI code. Service-role keys stay server-only. Document how privileged admin or operator roles are granted and verified before changing auth boundaries.";
|
|
4916
5068
|
function splitLines(value) {
|
|
4917
|
-
return value.split(/\r?\n/).map((
|
|
5069
|
+
return value.split(/\r?\n/).map((line2) => line2.trim()).filter(Boolean);
|
|
4918
5070
|
}
|
|
4919
5071
|
function uniqueStrings(values) {
|
|
4920
5072
|
return [...new Set(values.filter(Boolean))];
|
|
@@ -4968,10 +5120,7 @@ function applySetupFormAnswers(cwd, payload) {
|
|
|
4968
5120
|
qualityTarget: payload.qualityTarget,
|
|
4969
5121
|
owners,
|
|
4970
5122
|
lastReviewedAt: nowIso(),
|
|
4971
|
-
evidence: uniqueEvidence2([
|
|
4972
|
-
...base.evidence,
|
|
4973
|
-
{ source: "agent-kit setup wizard", note: "Project context updated through the local web setup wizard." }
|
|
4974
|
-
])
|
|
5123
|
+
evidence: uniqueEvidence2([...base.evidence, { source: "agent-kit setup wizard", note: "Project context updated through the local web setup wizard." }])
|
|
4975
5124
|
};
|
|
4976
5125
|
return writeProjectContext(cwd, updated);
|
|
4977
5126
|
}
|
|
@@ -5022,8 +5171,8 @@ function parseSetupFormPayload(raw) {
|
|
|
5022
5171
|
}
|
|
5023
5172
|
|
|
5024
5173
|
// src/studio/wizard/checklist.ts
|
|
5025
|
-
import { existsSync as existsSync19, readFileSync as
|
|
5026
|
-
import { join as
|
|
5174
|
+
import { existsSync as existsSync19, readFileSync as readFileSync18 } from "fs";
|
|
5175
|
+
import { join as join20 } from "path";
|
|
5027
5176
|
var IDE_PATHS = {
|
|
5028
5177
|
cursor: ".cursor/agents/planner.md",
|
|
5029
5178
|
copilot: ".github/copilot-instructions.md",
|
|
@@ -5044,12 +5193,12 @@ function saveIdeChecklist(cwd, ideSurface) {
|
|
|
5044
5193
|
function detectIdeRulePresent(cwd, ideSurface) {
|
|
5045
5194
|
const rel = IDE_PATHS[ideSurface];
|
|
5046
5195
|
if (ideSurface === "cursor") {
|
|
5047
|
-
return existsSync19(
|
|
5196
|
+
return existsSync19(join20(cwd, rel)) || existsSync19(join20(cwd, ".cursor/rules/cursor-agent-kit.mdc"));
|
|
5048
5197
|
}
|
|
5049
5198
|
if (rel.endsWith("/")) {
|
|
5050
|
-
return existsSync19(
|
|
5199
|
+
return existsSync19(join20(cwd, rel));
|
|
5051
5200
|
}
|
|
5052
|
-
return existsSync19(
|
|
5201
|
+
return existsSync19(join20(cwd, rel));
|
|
5053
5202
|
}
|
|
5054
5203
|
var VISUAL_QA_MARKER = "## Visual QA Tier";
|
|
5055
5204
|
var VISUAL_QA_BLOCKS = {
|
|
@@ -5077,11 +5226,11 @@ This project uses the **Mature** visual QA tier.
|
|
|
5077
5226
|
};
|
|
5078
5227
|
function writeVisualQaTier(cwd, tier) {
|
|
5079
5228
|
const path = "TESTING.md";
|
|
5080
|
-
const fullPath =
|
|
5229
|
+
const fullPath = join20(cwd, path);
|
|
5081
5230
|
if (!existsSync19(fullPath)) {
|
|
5082
5231
|
return { updated: false, path, reason: "TESTING.md not found in project root." };
|
|
5083
5232
|
}
|
|
5084
|
-
const current =
|
|
5233
|
+
const current = readFileSync18(fullPath, "utf8");
|
|
5085
5234
|
if (current.includes(VISUAL_QA_MARKER)) {
|
|
5086
5235
|
return {
|
|
5087
5236
|
updated: false,
|
|
@@ -5257,8 +5406,8 @@ function extractSetupFormFromWizardForm(form) {
|
|
|
5257
5406
|
}
|
|
5258
5407
|
|
|
5259
5408
|
// src/studio/wizard/drafts.ts
|
|
5260
|
-
import { existsSync as existsSync20, readFileSync as
|
|
5261
|
-
import { join as
|
|
5409
|
+
import { existsSync as existsSync20, readFileSync as readFileSync19 } from "fs";
|
|
5410
|
+
import { join as join21 } from "path";
|
|
5262
5411
|
var DESIGN_DRAFT_JSON = ".agent-kit/onboarding/design-draft.json";
|
|
5263
5412
|
var MESSAGING_DRAFT_JSON = ".agent-kit/onboarding/messaging-draft.json";
|
|
5264
5413
|
function loadDesignDraft(cwd) {
|
|
@@ -5303,11 +5452,11 @@ function previewMessagingMarkdown(draft) {
|
|
|
5303
5452
|
`;
|
|
5304
5453
|
}
|
|
5305
5454
|
function appendSectionToDoc(cwd, doc, sectionMarkdown) {
|
|
5306
|
-
const fullPath =
|
|
5455
|
+
const fullPath = join21(cwd, doc);
|
|
5307
5456
|
if (!existsSync20(fullPath)) {
|
|
5308
5457
|
return { target: doc, action: "missing" };
|
|
5309
5458
|
}
|
|
5310
|
-
const current =
|
|
5459
|
+
const current = readFileSync19(fullPath, "utf8");
|
|
5311
5460
|
if (current.includes("(wizard draft)")) {
|
|
5312
5461
|
return { target: doc, action: "conflict", conflictPath: `.agent-kit/conflicts/wizard-${doc}` };
|
|
5313
5462
|
}
|
|
@@ -5346,8 +5495,8 @@ function applyDrafts(cwd) {
|
|
|
5346
5495
|
}
|
|
5347
5496
|
|
|
5348
5497
|
// src/studio/office/render.ts
|
|
5349
|
-
import { readFileSync as
|
|
5350
|
-
import { join as
|
|
5498
|
+
import { readFileSync as readFileSync20 } from "fs";
|
|
5499
|
+
import { join as join22 } from "path";
|
|
5351
5500
|
|
|
5352
5501
|
// src/studio/office/map.ts
|
|
5353
5502
|
var MAP_WIDTH = 28;
|
|
@@ -5465,28 +5614,16 @@ function buildOfficeStations(agents) {
|
|
|
5465
5614
|
}
|
|
5466
5615
|
|
|
5467
5616
|
// src/studio/office/render.ts
|
|
5468
|
-
var PRODUCT_CATEGORIES = [
|
|
5469
|
-
"content-app",
|
|
5470
|
-
"saas",
|
|
5471
|
-
"admin",
|
|
5472
|
-
"marketplace",
|
|
5473
|
-
"tool",
|
|
5474
|
-
"ecommerce",
|
|
5475
|
-
"portfolio",
|
|
5476
|
-
"education",
|
|
5477
|
-
"community",
|
|
5478
|
-
"ai-workflow",
|
|
5479
|
-
"other"
|
|
5480
|
-
];
|
|
5617
|
+
var PRODUCT_CATEGORIES = ["content-app", "saas", "admin", "marketplace", "tool", "ecommerce", "portfolio", "education", "community", "ai-workflow", "other"];
|
|
5481
5618
|
var TENANT_MODELS = ["single-user", "team", "tenant", "marketplace", "admin", "public-content"];
|
|
5482
5619
|
function readOfficeAsset(name) {
|
|
5483
5620
|
const root = findPackageRoot();
|
|
5484
|
-
const distPath =
|
|
5485
|
-
const srcPath =
|
|
5621
|
+
const distPath = join22(root, "dist", "studio", "office", "assets", name);
|
|
5622
|
+
const srcPath = join22(root, "src", "studio", "office", "assets", name);
|
|
5486
5623
|
try {
|
|
5487
|
-
return
|
|
5624
|
+
return readFileSync20(distPath, "utf8");
|
|
5488
5625
|
} catch {
|
|
5489
|
-
return
|
|
5626
|
+
return readFileSync20(srcPath, "utf8");
|
|
5490
5627
|
}
|
|
5491
5628
|
}
|
|
5492
5629
|
function buildOfficeBootConfig(cwd, viewModel) {
|
|
@@ -5512,24 +5649,22 @@ function renderSetupOfficeHtml(boot) {
|
|
|
5512
5649
|
function renderOfficeHtml(boot, mode) {
|
|
5513
5650
|
const css = readOfficeAsset("office.css");
|
|
5514
5651
|
const js = readOfficeAsset("office.js");
|
|
5515
|
-
const bootJson = JSON.stringify(
|
|
5516
|
-
{
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
}
|
|
5532
|
-
).replace(/</g, "\\u003c");
|
|
5652
|
+
const bootJson = JSON.stringify({
|
|
5653
|
+
...boot ?? {
|
|
5654
|
+
mapWidth: MAP_WIDTH,
|
|
5655
|
+
mapHeight: MAP_HEIGHT,
|
|
5656
|
+
tileSize: TILE_SIZE,
|
|
5657
|
+
scale: CANVAS_SCALE,
|
|
5658
|
+
stations: [],
|
|
5659
|
+
agents: [],
|
|
5660
|
+
categories: PRODUCT_CATEGORIES,
|
|
5661
|
+
tenantModels: TENANT_MODELS,
|
|
5662
|
+
ideSurfaces: [],
|
|
5663
|
+
hasSupabase: false,
|
|
5664
|
+
stackSignals: []
|
|
5665
|
+
},
|
|
5666
|
+
mode
|
|
5667
|
+
}).replace(/</g, "\\u003c");
|
|
5533
5668
|
const isStudio = mode === "studio";
|
|
5534
5669
|
const title = isStudio ? "Agent Kit \u2014 Live Studio" : "Agent Kit \u2014 Setup Office";
|
|
5535
5670
|
const dataView = isStudio ? "studio-v1" : "office-v1";
|
|
@@ -5660,30 +5795,18 @@ function allAgentBriefsComplete(form, agentIds) {
|
|
|
5660
5795
|
}
|
|
5661
5796
|
|
|
5662
5797
|
// src/studio/wizard/render.ts
|
|
5663
|
-
import { readFileSync as
|
|
5664
|
-
import { join as
|
|
5665
|
-
var PRODUCT_CATEGORIES2 = [
|
|
5666
|
-
"content-app",
|
|
5667
|
-
"saas",
|
|
5668
|
-
"admin",
|
|
5669
|
-
"marketplace",
|
|
5670
|
-
"tool",
|
|
5671
|
-
"ecommerce",
|
|
5672
|
-
"portfolio",
|
|
5673
|
-
"education",
|
|
5674
|
-
"community",
|
|
5675
|
-
"ai-workflow",
|
|
5676
|
-
"other"
|
|
5677
|
-
];
|
|
5798
|
+
import { readFileSync as readFileSync21 } from "fs";
|
|
5799
|
+
import { join as join23 } from "path";
|
|
5800
|
+
var PRODUCT_CATEGORIES2 = ["content-app", "saas", "admin", "marketplace", "tool", "ecommerce", "portfolio", "education", "community", "ai-workflow", "other"];
|
|
5678
5801
|
var TENANT_MODELS2 = ["single-user", "team", "tenant", "marketplace", "admin", "public-content"];
|
|
5679
5802
|
function readWizardAsset(name) {
|
|
5680
5803
|
const root = findPackageRoot();
|
|
5681
|
-
const distPath =
|
|
5682
|
-
const srcPath =
|
|
5804
|
+
const distPath = join23(root, "dist", "studio", "wizard", "assets", name);
|
|
5805
|
+
const srcPath = join23(root, "src", "studio", "wizard", "assets", name);
|
|
5683
5806
|
try {
|
|
5684
|
-
return
|
|
5807
|
+
return readFileSync21(distPath, "utf8");
|
|
5685
5808
|
} catch {
|
|
5686
|
-
return
|
|
5809
|
+
return readFileSync21(srcPath, "utf8");
|
|
5687
5810
|
}
|
|
5688
5811
|
}
|
|
5689
5812
|
function mergeWizardSteps(cwd) {
|
|
@@ -5773,12 +5896,12 @@ function renderSetupWizardHtmlWithContext(cwd) {
|
|
|
5773
5896
|
}
|
|
5774
5897
|
|
|
5775
5898
|
// src/studio/agentic-level.ts
|
|
5776
|
-
import { existsSync as existsSync21, readFileSync as
|
|
5777
|
-
import { join as
|
|
5899
|
+
import { existsSync as existsSync21, readFileSync as readFileSync22 } from "fs";
|
|
5900
|
+
import { join as join24 } from "path";
|
|
5778
5901
|
var CACHE_TTL_MS = 3e4;
|
|
5779
5902
|
var cache = /* @__PURE__ */ new Map();
|
|
5780
5903
|
function isMaintainerSourceRepo(cwd) {
|
|
5781
|
-
return existsSync21(
|
|
5904
|
+
return existsSync21(join24(cwd, "package.json")) && existsSync21(join24(cwd, "src")) && existsSync21(join24(cwd, "templates"));
|
|
5782
5905
|
}
|
|
5783
5906
|
function signal(id, level, label, pass, evidence, remediation) {
|
|
5784
5907
|
return { id, level, label, pass, evidence, remediation };
|
|
@@ -5794,28 +5917,23 @@ function detectIdePresent(cwd) {
|
|
|
5794
5917
|
return { pass: true, evidence: `${surface} adapter files detected` };
|
|
5795
5918
|
}
|
|
5796
5919
|
}
|
|
5797
|
-
if (existsSync21(
|
|
5920
|
+
if (existsSync21(join24(cwd, ".cursor/rules/cursor-agent-kit.mdc"))) {
|
|
5798
5921
|
return { pass: true, evidence: "Cursor council rules from init" };
|
|
5799
5922
|
}
|
|
5800
5923
|
return { pass: false, evidence: "No IDE adapter rules or subagents detected" };
|
|
5801
5924
|
}
|
|
5802
5925
|
function detectTierBSubagents(cwd) {
|
|
5803
|
-
const paths = [
|
|
5804
|
-
|
|
5805
|
-
".codex/agents/planner.toml",
|
|
5806
|
-
".claude/agents/planner.md",
|
|
5807
|
-
".github/copilot-instructions.md"
|
|
5808
|
-
];
|
|
5809
|
-
const found = paths.filter((rel) => existsSync21(join23(cwd, rel)));
|
|
5926
|
+
const paths = [".cursor/agents/planner.md", ".codex/agents/planner.toml", ".claude/agents/planner.md", ".github/copilot-instructions.md"];
|
|
5927
|
+
const found = paths.filter((rel) => existsSync21(join24(cwd, rel)));
|
|
5810
5928
|
if (found.length > 0) {
|
|
5811
5929
|
return { pass: true, evidence: `Specialist surface: ${found[0]}` };
|
|
5812
5930
|
}
|
|
5813
5931
|
return { pass: false, evidence: "No council subagents or Copilot instructions installed" };
|
|
5814
5932
|
}
|
|
5815
5933
|
function readDocSnippet(cwd, name, needles) {
|
|
5816
|
-
const path =
|
|
5934
|
+
const path = join24(cwd, name);
|
|
5817
5935
|
if (!existsSync21(path)) return false;
|
|
5818
|
-
const lower =
|
|
5936
|
+
const lower = readFileSync22(path, "utf8").toLowerCase();
|
|
5819
5937
|
return needles.every((needle) => lower.includes(needle.toLowerCase()));
|
|
5820
5938
|
}
|
|
5821
5939
|
function adapterTargetForIde(ide) {
|
|
@@ -5843,8 +5961,8 @@ function buildSignals(cwd, maintainerProfile) {
|
|
|
5843
5961
|
"l4-agents-md",
|
|
5844
5962
|
4,
|
|
5845
5963
|
"Council contract (AGENTS.md)",
|
|
5846
|
-
existsSync21(
|
|
5847
|
-
existsSync21(
|
|
5964
|
+
existsSync21(join24(cwd, "AGENTS.md")),
|
|
5965
|
+
existsSync21(join24(cwd, "AGENTS.md")) ? "AGENTS.md installed" : "AGENTS.md missing",
|
|
5848
5966
|
"Run agent-kit init --stack next-supabase"
|
|
5849
5967
|
)
|
|
5850
5968
|
);
|
|
@@ -5853,8 +5971,8 @@ function buildSignals(cwd, maintainerProfile) {
|
|
|
5853
5971
|
"l4-adapters-doc",
|
|
5854
5972
|
4,
|
|
5855
5973
|
"Assistant activation doc",
|
|
5856
|
-
existsSync21(
|
|
5857
|
-
existsSync21(
|
|
5974
|
+
existsSync21(join24(cwd, "ASSISTANT_ADAPTERS.md")),
|
|
5975
|
+
existsSync21(join24(cwd, "ASSISTANT_ADAPTERS.md")) ? "ASSISTANT_ADAPTERS.md installed" : "ASSISTANT_ADAPTERS.md missing",
|
|
5858
5976
|
"Run agent-kit init or agent-kit update"
|
|
5859
5977
|
)
|
|
5860
5978
|
);
|
|
@@ -5863,8 +5981,8 @@ function buildSignals(cwd, maintainerProfile) {
|
|
|
5863
5981
|
"l4-roster",
|
|
5864
5982
|
4,
|
|
5865
5983
|
"Machine-readable council roster",
|
|
5866
|
-
existsSync21(
|
|
5867
|
-
existsSync21(
|
|
5984
|
+
existsSync21(join24(cwd, ".agent-kit/agent-roster.json")),
|
|
5985
|
+
existsSync21(join24(cwd, ".agent-kit/agent-roster.json")) ? ".agent-kit/agent-roster.json present" : "Roster missing",
|
|
5868
5986
|
"Run agent-kit init or agent-kit update"
|
|
5869
5987
|
)
|
|
5870
5988
|
);
|
|
@@ -5880,16 +5998,9 @@ function buildSignals(cwd, maintainerProfile) {
|
|
|
5880
5998
|
);
|
|
5881
5999
|
const tierB = detectTierBSubagents(cwd);
|
|
5882
6000
|
signals.push(
|
|
5883
|
-
signal(
|
|
5884
|
-
"l5-subagents",
|
|
5885
|
-
5,
|
|
5886
|
-
"Tier-B specialist activation",
|
|
5887
|
-
tierB.pass,
|
|
5888
|
-
tierB.evidence,
|
|
5889
|
-
"Run agent-kit init --activate cursor|codex|claude|copilot"
|
|
5890
|
-
)
|
|
6001
|
+
signal("l5-subagents", 5, "Tier-B specialist activation", tierB.pass, tierB.evidence, "Run agent-kit init --activate cursor|codex|claude|copilot")
|
|
5891
6002
|
);
|
|
5892
|
-
const loopCoding = existsSync21(
|
|
6003
|
+
const loopCoding = existsSync21(join24(cwd, "LOOP_CODING.md"));
|
|
5893
6004
|
signals.push(
|
|
5894
6005
|
signal(
|
|
5895
6006
|
"l6-loop-coding",
|
|
@@ -5920,12 +6031,12 @@ function buildSignals(cwd, maintainerProfile) {
|
|
|
5920
6031
|
)
|
|
5921
6032
|
);
|
|
5922
6033
|
if (maintainerProfile) {
|
|
5923
|
-
const pkgPath =
|
|
6034
|
+
const pkgPath = join24(cwd, "package.json");
|
|
5924
6035
|
let releaseCheck = false;
|
|
5925
6036
|
if (existsSync21(pkgPath)) {
|
|
5926
6037
|
try {
|
|
5927
|
-
const pkg = JSON.parse(
|
|
5928
|
-
releaseCheck = Boolean(pkg.scripts?.["release:check"]) && existsSync21(
|
|
6038
|
+
const pkg = JSON.parse(readFileSync22(pkgPath, "utf8"));
|
|
6039
|
+
releaseCheck = Boolean(pkg.scripts?.["release:check"]) && existsSync21(join24(cwd, "scripts/release-check.mjs"));
|
|
5929
6040
|
} catch {
|
|
5930
6041
|
releaseCheck = false;
|
|
5931
6042
|
}
|
|
@@ -5940,7 +6051,7 @@ function buildSignals(cwd, maintainerProfile) {
|
|
|
5940
6051
|
"Use npm run release:check before merge; see MAINTAINER_RELEASE.md"
|
|
5941
6052
|
)
|
|
5942
6053
|
);
|
|
5943
|
-
const maintainerDocs = existsSync21(
|
|
6054
|
+
const maintainerDocs = existsSync21(join24(cwd, "MAINTAINER_RELEASE.md")) || readDocSnippet(cwd, "DOCS.md", ["maintainer dogfood", "dogfood:init"]);
|
|
5944
6055
|
signals.push(
|
|
5945
6056
|
signal(
|
|
5946
6057
|
"l6-maintainer-docs",
|
|
@@ -5966,17 +6077,10 @@ function buildSignals(cwd, maintainerProfile) {
|
|
|
5966
6077
|
adapterEvidence = `cursor (detected): ${report2.summary.pass} pass / ${report2.summary.fail} fail`;
|
|
5967
6078
|
}
|
|
5968
6079
|
signals.push(
|
|
5969
|
-
signal(
|
|
5970
|
-
"l6-adapter-validate",
|
|
5971
|
-
6,
|
|
5972
|
-
"Adapter validate for active IDE",
|
|
5973
|
-
adapterPass,
|
|
5974
|
-
adapterEvidence,
|
|
5975
|
-
"Run agent-kit adapter validate cursor|codex|all"
|
|
5976
|
-
)
|
|
6080
|
+
signal("l6-adapter-validate", 6, "Adapter validate for active IDE", adapterPass, adapterEvidence, "Run agent-kit adapter validate cursor|codex|all")
|
|
5977
6081
|
);
|
|
5978
|
-
const ciWorkflow = existsSync21(
|
|
5979
|
-
const testingEval = existsSync21(
|
|
6082
|
+
const ciWorkflow = existsSync21(join24(cwd, ".github/workflows/agent-kit-audit.yml"));
|
|
6083
|
+
const testingEval = existsSync21(join24(cwd, "TESTING.md")) && readDocSnippet(cwd, "TESTING.md", ["agent-kit audit", "eval"]);
|
|
5980
6084
|
const evalLoop = ciWorkflow || testingEval;
|
|
5981
6085
|
signals.push(
|
|
5982
6086
|
signal(
|
|
@@ -6108,16 +6212,11 @@ function buildStatePayload(cwd, options = {}) {
|
|
|
6108
6212
|
const designDraft = loadDesignDraft(cwd);
|
|
6109
6213
|
const messagingDraft = loadMessagingDraft(cwd);
|
|
6110
6214
|
const draft = loadWizardDraft(cwd);
|
|
6111
|
-
const agenticLevel = computeAgenticLevel(
|
|
6112
|
-
cwd,
|
|
6113
|
-
options.forceAgenticRefresh ? { forceRefresh: true } : {}
|
|
6114
|
-
);
|
|
6215
|
+
const agenticLevel = computeAgenticLevel(cwd, options.forceAgenticRefresh ? { forceRefresh: true } : {});
|
|
6115
6216
|
return {
|
|
6116
6217
|
projectName: viewModel.projectName,
|
|
6117
6218
|
form: buildWizardFormState(cwd),
|
|
6118
|
-
hasExistingContext: Boolean(
|
|
6119
|
-
viewModel.form.productSummary.trim() || viewModel.form.primaryAudience.trim() || viewModel.form.valueProposition.trim()
|
|
6120
|
-
),
|
|
6219
|
+
hasExistingContext: Boolean(viewModel.form.productSummary.trim() || viewModel.form.primaryAudience.trim() || viewModel.form.valueProposition.trim()),
|
|
6121
6220
|
openQuestions: viewModel.openQuestions,
|
|
6122
6221
|
hasSupabase: viewModel.hasSupabase,
|
|
6123
6222
|
onboarding,
|
|
@@ -6380,7 +6479,7 @@ async function startSetupServer(options) {
|
|
|
6380
6479
|
// src/studio/studio-server.ts
|
|
6381
6480
|
import { watch } from "fs";
|
|
6382
6481
|
import { createServer as createServer2 } from "http";
|
|
6383
|
-
import { join as
|
|
6482
|
+
import { join as join25 } from "path";
|
|
6384
6483
|
var DEFAULT_PORT2 = 9331;
|
|
6385
6484
|
var DEFAULT_HOST2 = "127.0.0.1";
|
|
6386
6485
|
var sseClients = /* @__PURE__ */ new Set();
|
|
@@ -6422,7 +6521,7 @@ function stopWatcher() {
|
|
|
6422
6521
|
}
|
|
6423
6522
|
}
|
|
6424
6523
|
function watchSessionEvents(cwd, sessionId) {
|
|
6425
|
-
const eventsPath2 =
|
|
6524
|
+
const eventsPath2 = join25(cwd, COUNCIL_SESSIONS_DIR, sessionId, "events.jsonl");
|
|
6426
6525
|
if (watchedEventsPath === eventsPath2 && activeWatcher) return;
|
|
6427
6526
|
stopWatcher();
|
|
6428
6527
|
watchedEventsPath = eventsPath2;
|
|
@@ -6444,7 +6543,7 @@ function safeSessionId(raw) {
|
|
|
6444
6543
|
if (!/^[a-z0-9-]+$/i.test(raw)) return null;
|
|
6445
6544
|
return raw;
|
|
6446
6545
|
}
|
|
6447
|
-
|
|
6546
|
+
function handleRequest2(cwd, request, response) {
|
|
6448
6547
|
const url = new URL(request.url ?? "/", "http://127.0.0.1");
|
|
6449
6548
|
if (request.method === "GET" && (url.pathname === "/" || url.pathname === "/office")) {
|
|
6450
6549
|
sendHtml2(response, renderLiveStudioHtmlWithContext(cwd));
|
|
@@ -6539,9 +6638,11 @@ async function startStudioServer(options) {
|
|
|
6539
6638
|
const requestedPort = options.port ?? DEFAULT_PORT2;
|
|
6540
6639
|
ensureStudioDirs(options.cwd);
|
|
6541
6640
|
const server = createServer2((request, response) => {
|
|
6542
|
-
|
|
6641
|
+
try {
|
|
6642
|
+
handleRequest2(options.cwd, request, response);
|
|
6643
|
+
} catch (error) {
|
|
6543
6644
|
sendJson2(response, 500, { error: error instanceof Error ? error.message : String(error) });
|
|
6544
|
-
}
|
|
6645
|
+
}
|
|
6545
6646
|
});
|
|
6546
6647
|
let port = requestedPort;
|
|
6547
6648
|
let portFallback = false;
|
|
@@ -6578,33 +6679,33 @@ async function startStudioServer(options) {
|
|
|
6578
6679
|
}
|
|
6579
6680
|
|
|
6580
6681
|
// src/studio/session-checkpoint.ts
|
|
6581
|
-
import { existsSync as existsSync22, readFileSync as
|
|
6582
|
-
import { extname, join as
|
|
6682
|
+
import { existsSync as existsSync22, readFileSync as readFileSync23 } from "fs";
|
|
6683
|
+
import { extname, join as join26 } from "path";
|
|
6583
6684
|
function parseCheckpointMarkdown(content) {
|
|
6584
6685
|
const payload = { notes: [], decisions: [], handoffs: [], outputs: [] };
|
|
6585
6686
|
const sections = content.split(/^## /m).slice(1);
|
|
6586
6687
|
for (const section of sections) {
|
|
6587
6688
|
const [headingLine, ...bodyLines] = section.split("\n");
|
|
6588
6689
|
if (!headingLine) continue;
|
|
6589
|
-
const
|
|
6590
|
-
const lines = bodyLines.map((
|
|
6591
|
-
if (
|
|
6592
|
-
for (const
|
|
6593
|
-
const match =
|
|
6690
|
+
const heading2 = headingLine.trim().toLowerCase();
|
|
6691
|
+
const lines = bodyLines.map((line2) => line2.trim()).filter(Boolean);
|
|
6692
|
+
if (heading2 === "notes") {
|
|
6693
|
+
for (const line2 of lines) {
|
|
6694
|
+
const match = line2.match(/^-?\s*@(\S+):\s*(.+)$/);
|
|
6594
6695
|
if (match?.[1] && match[2]) payload.notes?.push({ agent: match[1], text: match[2] });
|
|
6595
6696
|
}
|
|
6596
6697
|
}
|
|
6597
|
-
if (
|
|
6598
|
-
for (const
|
|
6599
|
-
const match =
|
|
6698
|
+
if (heading2 === "decisions") {
|
|
6699
|
+
for (const line2 of lines) {
|
|
6700
|
+
const match = line2.match(/^-?\s*@(\S+):\s*(.+?)(?:\s+\(risk:\s*(.+)\))?$/i);
|
|
6600
6701
|
if (match?.[1] && match[2]) {
|
|
6601
6702
|
payload.decisions?.push({ agent: match[1], text: match[2], ...match[3] ? { risk: match[3] } : {} });
|
|
6602
6703
|
}
|
|
6603
6704
|
}
|
|
6604
6705
|
}
|
|
6605
|
-
if (
|
|
6606
|
-
for (const
|
|
6607
|
-
const match =
|
|
6706
|
+
if (heading2 === "handoffs") {
|
|
6707
|
+
for (const line2 of lines) {
|
|
6708
|
+
const match = line2.match(/^-?\s*(\S+)\s*->\s*(\S+):\s*(.+?)\s+\|\s*risk:\s*(.+)$/i);
|
|
6608
6709
|
if (match?.[1] && match?.[2] && match?.[3] && match?.[4]) {
|
|
6609
6710
|
payload.handoffs?.push({
|
|
6610
6711
|
fromAgentId: match[1],
|
|
@@ -6615,9 +6716,9 @@ function parseCheckpointMarkdown(content) {
|
|
|
6615
6716
|
}
|
|
6616
6717
|
}
|
|
6617
6718
|
}
|
|
6618
|
-
if (
|
|
6619
|
-
for (const
|
|
6620
|
-
const match =
|
|
6719
|
+
if (heading2 === "outputs") {
|
|
6720
|
+
for (const line2 of lines) {
|
|
6721
|
+
const match = line2.match(/^-?\s*(.+?):\s*(missing|partial|complete|not-applicable)(?:\s+\|\s*(.+))?$/i);
|
|
6621
6722
|
if (match?.[1] && match?.[2]) {
|
|
6622
6723
|
payload.outputs?.push({
|
|
6623
6724
|
name: match[1].trim(),
|
|
@@ -6627,15 +6728,15 @@ function parseCheckpointMarkdown(content) {
|
|
|
6627
6728
|
}
|
|
6628
6729
|
}
|
|
6629
6730
|
}
|
|
6630
|
-
if (
|
|
6631
|
-
if (lines.some((
|
|
6632
|
-
if (lines.some((
|
|
6731
|
+
if (heading2 === "options") {
|
|
6732
|
+
if (lines.some((line2) => /render:\s*true/i.test(line2))) payload.render = true;
|
|
6733
|
+
if (lines.some((line2) => /close:\s*true/i.test(line2))) payload.close = true;
|
|
6633
6734
|
}
|
|
6634
6735
|
}
|
|
6635
6736
|
return payload;
|
|
6636
6737
|
}
|
|
6637
6738
|
function parseCheckpointFile(filePath) {
|
|
6638
|
-
const content =
|
|
6739
|
+
const content = readFileSync23(filePath, "utf8");
|
|
6639
6740
|
const ext = extname(filePath).toLowerCase();
|
|
6640
6741
|
if (ext === ".json") {
|
|
6641
6742
|
const parsed = JSON.parse(content);
|
|
@@ -6711,11 +6812,55 @@ function applySessionCheckpoint(cwd, payload) {
|
|
|
6711
6812
|
};
|
|
6712
6813
|
}
|
|
6713
6814
|
function checkpointSessionFromFile(cwd, filePath) {
|
|
6714
|
-
const absolute =
|
|
6815
|
+
const absolute = join26(cwd, filePath);
|
|
6715
6816
|
if (!existsSync22(absolute)) throw new Error(`Checkpoint file not found: ${filePath}`);
|
|
6716
6817
|
return applySessionCheckpoint(cwd, parseCheckpointFile(absolute));
|
|
6717
6818
|
}
|
|
6718
6819
|
|
|
6820
|
+
// src/cli/output.ts
|
|
6821
|
+
import pc from "picocolors";
|
|
6822
|
+
var colorEnabled = process.env.NO_COLOR === void 0 && process.stdout.isTTY === true;
|
|
6823
|
+
function paint(painter, text) {
|
|
6824
|
+
return colorEnabled ? painter(text) : text;
|
|
6825
|
+
}
|
|
6826
|
+
var style = {
|
|
6827
|
+
heading: (text) => paint(pc.cyan, text),
|
|
6828
|
+
pass: (text) => paint(pc.green, text),
|
|
6829
|
+
warn: (text) => paint(pc.yellow, text),
|
|
6830
|
+
fail: (text) => paint(pc.red, text),
|
|
6831
|
+
dim: (text) => paint(pc.dim, text),
|
|
6832
|
+
bold: (text) => paint(pc.bold, text)
|
|
6833
|
+
};
|
|
6834
|
+
function levelLabel(level) {
|
|
6835
|
+
const label = level.toUpperCase().padEnd(4);
|
|
6836
|
+
if (level === "pass") return style.pass(label);
|
|
6837
|
+
if (level === "warn") return style.warn(label);
|
|
6838
|
+
return style.fail(label);
|
|
6839
|
+
}
|
|
6840
|
+
function printJson(value) {
|
|
6841
|
+
console.log(JSON.stringify(value, null, 2));
|
|
6842
|
+
}
|
|
6843
|
+
function heading(text) {
|
|
6844
|
+
console.log(style.heading(text));
|
|
6845
|
+
}
|
|
6846
|
+
function line(text = "") {
|
|
6847
|
+
console.log(text);
|
|
6848
|
+
}
|
|
6849
|
+
function detail(text) {
|
|
6850
|
+
console.log(style.dim(` ${text}`));
|
|
6851
|
+
}
|
|
6852
|
+
function listItem(text) {
|
|
6853
|
+
console.log(`- ${text}`);
|
|
6854
|
+
}
|
|
6855
|
+
function fileGroup(label, files) {
|
|
6856
|
+
if (files.length === 0) return;
|
|
6857
|
+
console.log(`${style.bold(label)} (${files.length})`);
|
|
6858
|
+
for (const file of files) console.log(` ${file}`);
|
|
6859
|
+
}
|
|
6860
|
+
function fail(message) {
|
|
6861
|
+
console.error(style.fail(`error: ${message}`));
|
|
6862
|
+
}
|
|
6863
|
+
|
|
6719
6864
|
// src/cli/index.ts
|
|
6720
6865
|
var program = new Command();
|
|
6721
6866
|
var requiredOutputStatuses = ["missing", "partial", "complete", "not-applicable"];
|
|
@@ -6723,6 +6868,37 @@ function isRequiredOutputStatus(value) {
|
|
|
6723
6868
|
return requiredOutputStatuses.includes(value);
|
|
6724
6869
|
}
|
|
6725
6870
|
program.name("agent-kit").description("Next.js + Supabase agent, skill, docs, design, and research kit.").version(PACKAGE_VERSION);
|
|
6871
|
+
async function runGuidedContextPrompts(cwd) {
|
|
6872
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) return;
|
|
6873
|
+
const clack = await import("@clack/prompts");
|
|
6874
|
+
clack.intro("agent-kit guided setup");
|
|
6875
|
+
const questions = [
|
|
6876
|
+
{ key: "productSummary", message: "What does this product do, in one concrete paragraph?" },
|
|
6877
|
+
{ key: "primaryAudience", message: "Who is the primary user or buyer?" },
|
|
6878
|
+
{ key: "authModel", message: "What authentication model should agents preserve?" },
|
|
6879
|
+
{ key: "tenantModel", message: "Is this single-user, team, tenant, marketplace, admin, or public content?" }
|
|
6880
|
+
];
|
|
6881
|
+
const answers = {};
|
|
6882
|
+
for (const question of questions) {
|
|
6883
|
+
const answer = await clack.text({ message: question.message, placeholder: "Leave empty to answer later" });
|
|
6884
|
+
if (clack.isCancel(answer)) {
|
|
6885
|
+
clack.cancel("Guided setup cancelled. Context files were still created; answer later with agent-kit context ask.");
|
|
6886
|
+
return;
|
|
6887
|
+
}
|
|
6888
|
+
if (typeof answer === "string" && answer.trim()) answers[question.key] = answer.trim();
|
|
6889
|
+
}
|
|
6890
|
+
if (Object.keys(answers).length > 0) {
|
|
6891
|
+
const contextPath = join27(cwd, ".agent-kit", "project-context.json");
|
|
6892
|
+
if (existsSync23(contextPath)) {
|
|
6893
|
+
const context2 = JSON.parse(readFileSync24(contextPath, "utf8"));
|
|
6894
|
+
Object.assign(context2, answers);
|
|
6895
|
+
writeFileSync2(contextPath, `${JSON.stringify(context2, null, 2)}
|
|
6896
|
+
`);
|
|
6897
|
+
renderProjectContext(cwd);
|
|
6898
|
+
}
|
|
6899
|
+
}
|
|
6900
|
+
clack.outro("Project context saved. Run agent-kit audit next.");
|
|
6901
|
+
}
|
|
6726
6902
|
async function runSetupServer(options) {
|
|
6727
6903
|
const handle = await startSetupServer({
|
|
6728
6904
|
cwd: process.cwd(),
|
|
@@ -6730,35 +6906,73 @@ async function runSetupServer(options) {
|
|
|
6730
6906
|
host: options.host
|
|
6731
6907
|
});
|
|
6732
6908
|
if (handle.portFallback) {
|
|
6733
|
-
console.warn(
|
|
6734
|
-
`Port ${handle.requestedPort} is in use \u2014 an old setup server may still be running. Kill it and restart to load the latest Agent Office.`
|
|
6735
|
-
);
|
|
6909
|
+
console.warn(`Port ${handle.requestedPort} is in use \u2014 an old setup server may still be running. Kill it and restart to load the latest Agent Office.`);
|
|
6736
6910
|
console.warn(`Using fallback port ${handle.port} instead.`);
|
|
6737
6911
|
}
|
|
6738
6912
|
console.log(`Agent Kit v${PACKAGE_VERSION} \u2014 ${handle.defaultView} view at ${handle.url}/`);
|
|
6739
6913
|
console.log(`Pixel office (default): ${handle.url}/ | Form fallback: ${handle.url}/wizard`);
|
|
6740
6914
|
console.log("Pick Quick, Standard, or Complete on first visit. Press Ctrl+C to stop.");
|
|
6741
|
-
if (options.open) openBrowser(`${handle.url}/`);
|
|
6915
|
+
if (options.open) void openBrowser(`${handle.url}/`);
|
|
6742
6916
|
await new Promise((resolve3) => {
|
|
6743
6917
|
const shutdown = () => {
|
|
6744
|
-
handle.close().finally(resolve3);
|
|
6918
|
+
void handle.close().finally(resolve3);
|
|
6745
6919
|
};
|
|
6746
6920
|
process.once("SIGINT", shutdown);
|
|
6747
6921
|
process.once("SIGTERM", shutdown);
|
|
6748
6922
|
});
|
|
6749
6923
|
}
|
|
6750
|
-
program.command("init").description("Install agent-kit docs and library files into a project.").option("--stack <stack>", "Stack profile to install.", "next-supabase").option("--force", "Overwrite existing docs instead of writing conflicts.").option("--activate <targets...>", "Promote IDE/runtime adapters: cursor, claude, codex, copilot, antigravity, or all.").option("--guided", "
|
|
6924
|
+
program.command("init").description("Install agent-kit docs and library files into a project.").option("--stack <stack>", "Stack profile to install.", "next-supabase").option("--force", "Overwrite existing docs instead of writing conflicts.").option("--activate <targets...>", "Promote IDE/runtime adapters: cursor, claude, codex, copilot, antigravity, or all.").option("--guided", "Also create local project context files (interactive on a terminal, scan-based otherwise).").option("--dry-run", "Preview what init would create or conflict on without writing files.").option("--json", "Print machine-readable JSON output.").option("--setup", "Start the setup wizard after install.").option("--no-setup", "Skip the post-install setup wizard prompt.").option("--open", "Open the setup wizard in your default browser.").action(async (options) => {
|
|
6751
6925
|
const cwd = process.cwd();
|
|
6926
|
+
if (options.dryRun) {
|
|
6927
|
+
const preview = diffProject(cwd, options.stack);
|
|
6928
|
+
if (options.json) {
|
|
6929
|
+
printJson({ dryRun: true, preview: preview.preview, missing: preview.missing, changed: preview.changed, unchanged: preview.unchanged });
|
|
6930
|
+
return;
|
|
6931
|
+
}
|
|
6932
|
+
heading("agent-kit init --dry-run");
|
|
6933
|
+
fileGroup("Would create", preview.preview.wouldCreate);
|
|
6934
|
+
fileGroup("Would write conflicts for", preview.preview.wouldWriteConflicts);
|
|
6935
|
+
fileGroup("Already up to date", preview.unchanged);
|
|
6936
|
+
line();
|
|
6937
|
+
line(`Run ${style.bold("agent-kit init")} to apply.`);
|
|
6938
|
+
return;
|
|
6939
|
+
}
|
|
6752
6940
|
const result = initProject({
|
|
6753
6941
|
cwd,
|
|
6754
6942
|
stack: options.stack,
|
|
6755
6943
|
force: Boolean(options.force),
|
|
6756
6944
|
...options.activate ? { activate: options.activate } : {}
|
|
6757
6945
|
});
|
|
6946
|
+
const context2 = options.guided ? initProjectContext(cwd) : null;
|
|
6758
6947
|
if (options.json) {
|
|
6759
|
-
|
|
6948
|
+
printJson(context2 ? { install: result, context: context2 } : result);
|
|
6760
6949
|
} else {
|
|
6761
|
-
|
|
6950
|
+
heading(`agent-kit ${PACKAGE_VERSION} installed (stack: ${options.stack})`);
|
|
6951
|
+
fileGroup("Created", result.copied);
|
|
6952
|
+
fileGroup("Unchanged", result.unchanged);
|
|
6953
|
+
fileGroup("Overwritten", result.overwritten);
|
|
6954
|
+
if (result.conflicts.length > 0) {
|
|
6955
|
+
fileGroup("Conflicts (local file kept, template saved for review)", result.conflicts);
|
|
6956
|
+
detail("Review .agent-kit/conflicts/ before adopting template changes.");
|
|
6957
|
+
}
|
|
6958
|
+
line();
|
|
6959
|
+
line(`Manifest: ${result.manifestPath}`);
|
|
6960
|
+
}
|
|
6961
|
+
if (options.guided && context2) {
|
|
6962
|
+
if (!options.json) {
|
|
6963
|
+
line();
|
|
6964
|
+
heading("Project context");
|
|
6965
|
+
line(`Context: ${context2.contextPath}`);
|
|
6966
|
+
if (context2.openQuestions.length > 0) {
|
|
6967
|
+
line("Open questions:");
|
|
6968
|
+
for (const question of context2.openQuestions) listItem(question);
|
|
6969
|
+
}
|
|
6970
|
+
}
|
|
6971
|
+
await runGuidedContextPrompts(cwd);
|
|
6972
|
+
}
|
|
6973
|
+
if (!options.json) {
|
|
6974
|
+
line();
|
|
6975
|
+
line(`Next: run ${style.bold("agent-kit audit")} to check readiness.`);
|
|
6762
6976
|
}
|
|
6763
6977
|
const shouldPrompt = !options.noSetup && !options.json;
|
|
6764
6978
|
const startWizard = Boolean(options.setup) || shouldPrompt && await promptStartSetup(true);
|
|
@@ -6771,26 +6985,26 @@ program.command("audit").description("Audit an existing project for agent-kit co
|
|
|
6771
6985
|
let minimumReadiness;
|
|
6772
6986
|
if (options.minReadiness) {
|
|
6773
6987
|
if (!isAuditReadinessLevel(options.minReadiness)) {
|
|
6774
|
-
|
|
6988
|
+
fail(`Invalid --min-readiness value "${options.minReadiness}". Expected one of: ${READINESS_ORDER.join(", ")}.`);
|
|
6775
6989
|
process.exitCode = 1;
|
|
6776
6990
|
return;
|
|
6777
6991
|
}
|
|
6778
6992
|
minimumReadiness = options.minReadiness;
|
|
6779
6993
|
}
|
|
6780
6994
|
if (options.json) {
|
|
6781
|
-
|
|
6995
|
+
printJson(report2);
|
|
6782
6996
|
} else {
|
|
6783
|
-
|
|
6784
|
-
|
|
6997
|
+
const readinessStyle = report2.summary.fail > 0 ? style.fail : report2.summary.warn > 0 ? style.warn : style.pass;
|
|
6998
|
+
line(`${style.bold("READINESS")} ${readinessStyle(report2.readiness.level)}: ${report2.readiness.summary}`);
|
|
6999
|
+
line(`${style.bold("SUMMARY")} pass=${report2.summary.pass} warn=${report2.summary.warn} fail=${report2.summary.fail}`);
|
|
6785
7000
|
if (report2.readiness.nextActions.length > 0) {
|
|
6786
|
-
|
|
6787
|
-
for (const action of report2.readiness.nextActions)
|
|
7001
|
+
line(style.bold("NEXT ACTIONS"));
|
|
7002
|
+
for (const action of report2.readiness.nextActions) listItem(action);
|
|
6788
7003
|
}
|
|
6789
|
-
|
|
7004
|
+
line();
|
|
6790
7005
|
for (const finding of report2.findings) {
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
if (finding.remediation) console.log(` remediation: ${finding.remediation}`);
|
|
7006
|
+
line(`${levelLabel(finding.level)} ${finding.area}: ${finding.message}`);
|
|
7007
|
+
if (finding.remediation) detail(`remediation: ${finding.remediation}`);
|
|
6794
7008
|
}
|
|
6795
7009
|
}
|
|
6796
7010
|
if (report2.summary.fail > 0) {
|
|
@@ -6801,32 +7015,88 @@ program.command("audit").description("Audit an existing project for agent-kit co
|
|
|
6801
7015
|
process.exitCode = 1;
|
|
6802
7016
|
}
|
|
6803
7017
|
});
|
|
6804
|
-
program.command("diff").description("Compare project docs against bundled templates.").action(() => {
|
|
6805
|
-
|
|
7018
|
+
program.command("diff").description("Compare project docs against bundled templates.").option("--json", "Print machine-readable JSON output.").action((options) => {
|
|
7019
|
+
const result = diffProject(process.cwd());
|
|
7020
|
+
if (options.json) {
|
|
7021
|
+
printJson(result);
|
|
7022
|
+
return;
|
|
7023
|
+
}
|
|
7024
|
+
heading("agent-kit diff");
|
|
7025
|
+
fileGroup("Missing (update would create)", result.missing);
|
|
7026
|
+
fileGroup("Changed locally (update would write conflicts)", result.changed);
|
|
7027
|
+
fileGroup("Unchanged", result.unchanged);
|
|
7028
|
+
line();
|
|
7029
|
+
line(`Agent roster: ${result.agentRoster}`);
|
|
7030
|
+
line(`Model routing: ${result.modelRouting}`);
|
|
7031
|
+
if (result.libraryFolders.missing.length > 0) {
|
|
7032
|
+
line(`Missing library folders: ${result.libraryFolders.missing.join(", ")}`);
|
|
7033
|
+
}
|
|
7034
|
+
line();
|
|
7035
|
+
line(`Next: run ${style.bold("agent-kit update --dry-run")} to preview the exact per-file plan.`);
|
|
6806
7036
|
});
|
|
6807
|
-
program.command("update").description("Update installed templates,
|
|
6808
|
-
const result =
|
|
6809
|
-
|
|
7037
|
+
program.command("update").description("Update installed templates: pristine docs are refreshed, local edits are preserved, and template conflicts are written for review.").option("--force", "Overwrite locally customized docs with the current templates.").option("--dry-run", "Report what would change without writing any files.").option("--json", "Print machine-readable JSON output.").action((options) => {
|
|
7038
|
+
const result = updateProject({ cwd: process.cwd(), force: Boolean(options.force), dryRun: Boolean(options.dryRun) });
|
|
7039
|
+
if (options.json) {
|
|
7040
|
+
printJson(result);
|
|
7041
|
+
return;
|
|
7042
|
+
}
|
|
7043
|
+
heading(result.dryRun ? "agent-kit update --dry-run" : "agent-kit update");
|
|
7044
|
+
const byAction = (action) => result.files.filter((file) => file.action === action).map((file) => file.target);
|
|
7045
|
+
fileGroup(result.dryRun ? "Would create" : "Created", byAction("created"));
|
|
7046
|
+
fileGroup(result.dryRun ? "Would update (pristine)" : "Updated (pristine)", byAction("updated"));
|
|
7047
|
+
fileGroup("Kept local customizations", byAction("kept-local"));
|
|
7048
|
+
fileGroup(result.dryRun ? "Would overwrite" : "Overwritten", byAction("overwritten"));
|
|
7049
|
+
const conflicts = result.files.filter((file) => file.action === "conflict");
|
|
7050
|
+
if (conflicts.length > 0) {
|
|
7051
|
+
line(`${style.bold("Conflicts")} (${conflicts.length})`);
|
|
7052
|
+
for (const file of conflicts) {
|
|
7053
|
+
line(` ${file.target}${file.conflictPath ? ` -> ${file.conflictPath}` : ""}`);
|
|
7054
|
+
}
|
|
7055
|
+
detail("Local files were kept. Review the conflict copies before adopting template changes.");
|
|
7056
|
+
}
|
|
7057
|
+
detail(`unchanged: ${result.summary.unchanged} file(s) already match the current templates`);
|
|
7058
|
+
if (!result.dryRun) {
|
|
7059
|
+
line();
|
|
7060
|
+
line(`Library folders refreshed: ${result.libraryFoldersRefreshed.length}`);
|
|
7061
|
+
line(`Manifest: ${result.manifestPath}`);
|
|
7062
|
+
}
|
|
6810
7063
|
});
|
|
6811
7064
|
var addCommand = program.command("add").description("Add one agent-kit asset.");
|
|
6812
|
-
addCommand.command("skill <name>").description("Add a single skill into .agent-kit/skills.").option("--force", "Overwrite existing skill.").action((name, options) => {
|
|
6813
|
-
|
|
7065
|
+
addCommand.command("skill <name>").description("Add a single skill into .agent-kit/skills.").option("--force", "Overwrite existing skill.").option("--dry-run", "Report what would happen without writing.").option("--json", "Print machine-readable JSON output.").action((name, options) => {
|
|
7066
|
+
const result = addSkill(process.cwd(), name, { force: Boolean(options.force), dryRun: Boolean(options.dryRun) });
|
|
7067
|
+
if (options.json) {
|
|
7068
|
+
printJson(result);
|
|
7069
|
+
return;
|
|
7070
|
+
}
|
|
7071
|
+
line(`${result.action}: ${result.target}${result.conflictPath ? ` -> ${result.conflictPath}` : ""}`);
|
|
7072
|
+
if (options.dryRun) detail("dry run: no files were written");
|
|
6814
7073
|
});
|
|
6815
|
-
program.command("doctor").description("Validate local CLI runtime prerequisites.").action(() => {
|
|
7074
|
+
program.command("doctor").description("Validate local CLI runtime prerequisites.").option("--json", "Print machine-readable JSON output.").action((options) => {
|
|
6816
7075
|
const cwd = process.cwd();
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
|
|
7076
|
+
const report2 = {
|
|
7077
|
+
version: PACKAGE_VERSION,
|
|
7078
|
+
node: process.version,
|
|
7079
|
+
availableSkills: listSkills().length,
|
|
7080
|
+
setupProgress: onboardingStateExists(cwd) ? getSetupProgress(cwd) : null,
|
|
7081
|
+
status: "ok"
|
|
7082
|
+
};
|
|
7083
|
+
if (options.json) {
|
|
7084
|
+
printJson(report2);
|
|
7085
|
+
return;
|
|
7086
|
+
}
|
|
7087
|
+
heading("agent-kit doctor");
|
|
7088
|
+
line(`version: ${report2.version}`);
|
|
7089
|
+
line(`node: ${report2.node}`);
|
|
7090
|
+
line(`available skills: ${report2.availableSkills}`);
|
|
7091
|
+
if (report2.setupProgress) {
|
|
7092
|
+
line(`setup progress: ${report2.setupProgress.percent}% (depth: ${report2.setupProgress.depth})`);
|
|
7093
|
+
if (!report2.setupProgress.quickComplete) {
|
|
7094
|
+
detail("run agent-kit setup --open to finish project context onboarding.");
|
|
6825
7095
|
}
|
|
6826
7096
|
} else {
|
|
6827
|
-
|
|
7097
|
+
detail("run agent-kit init then agent-kit setup to onboard this project.");
|
|
6828
7098
|
}
|
|
6829
|
-
|
|
7099
|
+
line(`status: ${style.pass(report2.status)}`);
|
|
6830
7100
|
});
|
|
6831
7101
|
function printValidationReport(report2, json) {
|
|
6832
7102
|
if (json) {
|
|
@@ -6859,8 +7129,19 @@ packageCommand.command("validate").description("Validate package assets, runtime
|
|
|
6859
7129
|
printValidationReport(report2, Boolean(options.json));
|
|
6860
7130
|
if (report2.summary.fail > 0) process.exitCode = 1;
|
|
6861
7131
|
});
|
|
6862
|
-
program.command("onboard").description("Create or refresh local project context files for installed agents.").option("--refresh", "Refresh inferred context from the current project state.").action(() => {
|
|
6863
|
-
|
|
7132
|
+
program.command("onboard").description("Create or refresh local project context files for installed agents.").option("--refresh", "Refresh inferred context from the current project state.").option("--json", "Print machine-readable JSON output.").action((options) => {
|
|
7133
|
+
const result = initProjectContext(process.cwd());
|
|
7134
|
+
if (options.json) {
|
|
7135
|
+
printJson(result);
|
|
7136
|
+
return;
|
|
7137
|
+
}
|
|
7138
|
+
heading("agent-kit onboard");
|
|
7139
|
+
line(`Context: ${result.contextPath}`);
|
|
7140
|
+
line(`Markdown: ${result.markdownPath}`);
|
|
7141
|
+
if (result.openQuestions.length > 0) {
|
|
7142
|
+
line("Open questions:");
|
|
7143
|
+
for (const question of result.openQuestions) listItem(question);
|
|
7144
|
+
}
|
|
6864
7145
|
});
|
|
6865
7146
|
program.command("setup").description("Start the local Agent Office setup view for project context.").option("--port <number>", "Port to listen on.", (value) => Number.parseInt(value, 10), 9321).option("--host <host>", "Host to bind.", "127.0.0.1").option("--open", "Open the wizard in your default browser.").option("--status", "Print setup progress and exit.").action(async (options) => {
|
|
6866
7147
|
const cwd = process.cwd();
|
|
@@ -6873,140 +7154,194 @@ program.command("setup").description("Start the local Agent Office setup view fo
|
|
|
6873
7154
|
await runSetupServer({ port: options.port, host: options.host, open: Boolean(options.open) });
|
|
6874
7155
|
});
|
|
6875
7156
|
var context = program.command("context").description("Manage local project context for Agent Studio.");
|
|
6876
|
-
context.command("init").description("Create project context from a local scan.").action(() => {
|
|
6877
|
-
|
|
7157
|
+
context.command("init").description("Create project context from a local scan.").option("--json", "Print machine-readable JSON output.").action((options) => {
|
|
7158
|
+
const result = initProjectContext(process.cwd());
|
|
7159
|
+
if (options.json) {
|
|
7160
|
+
printJson(result);
|
|
7161
|
+
return;
|
|
7162
|
+
}
|
|
7163
|
+
line(`Context written: ${result.contextPath}`);
|
|
7164
|
+
if (result.openQuestions.length > 0) {
|
|
7165
|
+
line("Open questions:");
|
|
7166
|
+
for (const question of result.openQuestions) listItem(question);
|
|
7167
|
+
}
|
|
6878
7168
|
});
|
|
6879
7169
|
context.command("scan").description("Print inferred project context without writing it.").action(() => {
|
|
6880
|
-
|
|
7170
|
+
printJson(scanProjectContext(process.cwd()));
|
|
6881
7171
|
});
|
|
6882
7172
|
context.command("ask").description("Print unanswered high-value project context questions.").action(() => {
|
|
6883
7173
|
const result = initProjectContext(process.cwd());
|
|
6884
7174
|
if (result.openQuestions.length === 0) {
|
|
6885
|
-
|
|
7175
|
+
line("No open project-context questions.");
|
|
6886
7176
|
return;
|
|
6887
7177
|
}
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
for (const question of result.openQuestions)
|
|
7178
|
+
line("Answer these in the web setup wizard with: agent-kit setup --open");
|
|
7179
|
+
detail("Check progress with: agent-kit setup --status");
|
|
7180
|
+
for (const question of result.openQuestions) listItem(question);
|
|
6891
7181
|
});
|
|
6892
|
-
context.command("render").description("Render .agent-kit/project-context.md from project-context.json.").action(() => {
|
|
6893
|
-
|
|
7182
|
+
context.command("render").description("Render .agent-kit/project-context.md from project-context.json.").option("--json", "Print machine-readable JSON output.").action((options) => {
|
|
7183
|
+
const result = renderProjectContext(process.cwd());
|
|
7184
|
+
if (options.json) {
|
|
7185
|
+
printJson(result);
|
|
7186
|
+
return;
|
|
7187
|
+
}
|
|
7188
|
+
line(`Rendered: ${result.markdownPath}`);
|
|
6894
7189
|
});
|
|
6895
|
-
context.command("validate").description("Validate .agent-kit/project-context.json.").action(() => {
|
|
6896
|
-
|
|
7190
|
+
context.command("validate").description("Validate .agent-kit/project-context.json.").option("--json", "Print machine-readable JSON output.").action((options) => {
|
|
7191
|
+
const result = validateProjectContext(process.cwd());
|
|
7192
|
+
if (options.json) {
|
|
7193
|
+
printJson(result);
|
|
7194
|
+
return;
|
|
7195
|
+
}
|
|
7196
|
+
line(`Valid: ${result.contextPath}`);
|
|
7197
|
+
if (result.openQuestions.length > 0) {
|
|
7198
|
+
line("Open questions:");
|
|
7199
|
+
for (const question of result.openQuestions) listItem(question);
|
|
7200
|
+
}
|
|
6897
7201
|
});
|
|
6898
7202
|
context.command("show").description("Print rendered project context markdown.").action(() => {
|
|
6899
7203
|
console.log(readTextFile(process.cwd(), ".agent-kit/project-context.md") ?? "");
|
|
6900
7204
|
});
|
|
6901
7205
|
var session = program.command("session").description("Record and render local Agent Studio council sessions.");
|
|
6902
|
-
session.command("start <title...>").description("Start a local council session.").option("--workflow <workflow>", "Workflow id.", "planning").option("--request <request>", "Original user request.").action((titleParts, options) => {
|
|
7206
|
+
session.command("start <title...>").description("Start a local council session.").option("--workflow <workflow>", "Workflow id.", "planning").option("--request <request>", "Original user request.").option("--json", "Print machine-readable JSON output.").action((titleParts, options) => {
|
|
6903
7207
|
const title = titleParts.join(" ");
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
|
|
6912
|
-
|
|
6913
|
-
|
|
6914
|
-
);
|
|
7208
|
+
const result = startSession(process.cwd(), {
|
|
7209
|
+
title,
|
|
7210
|
+
workflowId: options.workflow,
|
|
7211
|
+
...options.request ? { request: options.request } : {}
|
|
7212
|
+
});
|
|
7213
|
+
if (options.json) {
|
|
7214
|
+
printJson(result);
|
|
7215
|
+
return;
|
|
7216
|
+
}
|
|
7217
|
+
line(`Session started: ${result.sessionId}`);
|
|
7218
|
+
line(`Path: ${result.sessionPath}`);
|
|
6915
7219
|
});
|
|
6916
|
-
session.command("list").description("List local council sessions.").action(() => {
|
|
6917
|
-
|
|
7220
|
+
session.command("list").description("List local council sessions.").option("--json", "Print machine-readable JSON output.").action((options) => {
|
|
7221
|
+
const sessions = listSessions(process.cwd());
|
|
7222
|
+
if (options.json) {
|
|
7223
|
+
printJson(sessions);
|
|
7224
|
+
return;
|
|
7225
|
+
}
|
|
7226
|
+
if (sessions.length === 0) {
|
|
7227
|
+
line("No sessions yet. Start one with agent-kit session start <title>.");
|
|
7228
|
+
return;
|
|
7229
|
+
}
|
|
7230
|
+
for (const item of sessions) {
|
|
7231
|
+
line(`${item.sessionId} [${item.status}] ${item.title}`);
|
|
7232
|
+
}
|
|
6918
7233
|
});
|
|
6919
7234
|
session.command("active").description("Print the active council session id.").action(() => {
|
|
6920
7235
|
console.log(getActiveSessionId(process.cwd()));
|
|
6921
7236
|
});
|
|
6922
|
-
session.command("note <text...>").description("Record a visible agent message.").requiredOption("--agent <agent>", "Agent id.").action((textParts, options) => {
|
|
6923
|
-
|
|
7237
|
+
session.command("note <text...>").description("Record a visible agent message.").requiredOption("--agent <agent>", "Agent id.").option("--json", "Print machine-readable JSON output.").action((textParts, options) => {
|
|
7238
|
+
const result = recordNote(process.cwd(), options.agent, textParts.join(" "));
|
|
7239
|
+
if (options.json) printJson(result);
|
|
7240
|
+
else line(`Recorded note from ${options.agent}.`);
|
|
6924
7241
|
});
|
|
6925
|
-
session.command("decision <text...>").description("Record an agent decision.").requiredOption("--agent <agent>", "Agent id.").option("--risk <risk>", "Risk associated with the decision.").action((textParts, options) => {
|
|
6926
|
-
|
|
7242
|
+
session.command("decision <text...>").description("Record an agent decision.").requiredOption("--agent <agent>", "Agent id.").option("--risk <risk>", "Risk associated with the decision.").option("--json", "Print machine-readable JSON output.").action((textParts, options) => {
|
|
7243
|
+
const result = recordDecision(process.cwd(), options.agent, textParts.join(" "), options.risk);
|
|
7244
|
+
if (options.json) printJson(result);
|
|
7245
|
+
else line(`Recorded decision from ${options.agent}.`);
|
|
6927
7246
|
});
|
|
6928
|
-
session.command("handoff").description("Record an agent handoff.").requiredOption("--from <agent>", "Source agent id.").requiredOption("--to <agent>", "Target agent id.").requiredOption("--decision <decision>", "Decision being handed off.").requiredOption("--risk <risk>", "Risk that remains.").option("--evidence <evidence...>", "Evidence paths or notes.").action((options) => {
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
null,
|
|
6939
|
-
2
|
|
6940
|
-
)
|
|
6941
|
-
);
|
|
7247
|
+
session.command("handoff").description("Record an agent handoff.").requiredOption("--from <agent>", "Source agent id.").requiredOption("--to <agent>", "Target agent id.").requiredOption("--decision <decision>", "Decision being handed off.").requiredOption("--risk <risk>", "Risk that remains.").option("--evidence <evidence...>", "Evidence paths or notes.").option("--json", "Print machine-readable JSON output.").action((options) => {
|
|
7248
|
+
const result = recordHandoff(process.cwd(), {
|
|
7249
|
+
fromAgentId: options.from,
|
|
7250
|
+
toAgentId: options.to,
|
|
7251
|
+
decision: options.decision,
|
|
7252
|
+
risk: options.risk,
|
|
7253
|
+
...options.evidence ? { evidence: options.evidence } : {}
|
|
7254
|
+
});
|
|
7255
|
+
if (options.json) printJson(result);
|
|
7256
|
+
else line(`Recorded handoff ${options.from} -> ${options.to}.`);
|
|
6942
7257
|
});
|
|
6943
|
-
session.command("correct <text...>").description("Record a human correction and optionally promote it to durable rules.").option("--agent <agent>", "Agent id.").option("--scope <scope>", "Correction scope: session, project, agent, upstream-proposal.", "session").action((textParts, options) => {
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
null,
|
|
6952
|
-
2
|
|
6953
|
-
)
|
|
6954
|
-
);
|
|
7258
|
+
session.command("correct <text...>").description("Record a human correction and optionally promote it to durable rules.").option("--agent <agent>", "Agent id.").option("--scope <scope>", "Correction scope: session, project, agent, upstream-proposal.", "session").option("--json", "Print machine-readable JSON output.").action((textParts, options) => {
|
|
7259
|
+
const result = recordCorrection(process.cwd(), {
|
|
7260
|
+
...options.agent ? { agentId: options.agent } : {},
|
|
7261
|
+
scope: options.scope,
|
|
7262
|
+
text: textParts.join(" ")
|
|
7263
|
+
});
|
|
7264
|
+
if (options.json) printJson(result);
|
|
7265
|
+
else line(`Recorded ${options.scope}-scoped correction.`);
|
|
6955
7266
|
});
|
|
6956
|
-
session.command("artifact").description("Record a changed or relevant artifact path.").requiredOption("--file <file>", "Artifact file path.").option("--note <note>", "Artifact note.").action((options) => {
|
|
6957
|
-
|
|
7267
|
+
session.command("artifact").description("Record a changed or relevant artifact path.").requiredOption("--file <file>", "Artifact file path.").option("--note <note>", "Artifact note.").option("--json", "Print machine-readable JSON output.").action((options) => {
|
|
7268
|
+
const result = recordArtifact(process.cwd(), options.file, options.note);
|
|
7269
|
+
if (options.json) printJson(result);
|
|
7270
|
+
else line(`Recorded artifact ${options.file}.`);
|
|
6958
7271
|
});
|
|
6959
|
-
session.command("verify").description("Record verification evidence.").requiredOption("--command <command>", "Command or review performed.").requiredOption("--result <result>", "pass, fail, or skipped.").option("--notes <notes>", "Verification notes.").action((options) => {
|
|
6960
|
-
|
|
7272
|
+
session.command("verify").description("Record verification evidence.").requiredOption("--command <command>", "Command or review performed.").requiredOption("--result <result>", "pass, fail, or skipped.").option("--notes <notes>", "Verification notes.").option("--json", "Print machine-readable JSON output.").action((options) => {
|
|
7273
|
+
const result = recordVerification(process.cwd(), options.command, options.result, options.notes);
|
|
7274
|
+
if (options.json) printJson(result);
|
|
7275
|
+
else line(`Recorded verification (${options.result}): ${options.command}`);
|
|
6961
7276
|
});
|
|
6962
|
-
session.command("output <name...>").description("Mark a required session output status.").requiredOption("--status <status>", "missing, partial, complete, or not-applicable.").option("--evidence <evidence>", "Evidence path, command, or note.").action((nameParts, options) => {
|
|
7277
|
+
session.command("output <name...>").description("Mark a required session output status.").requiredOption("--status <status>", "missing, partial, complete, or not-applicable.").option("--evidence <evidence>", "Evidence path, command, or note.").option("--json", "Print machine-readable JSON output.").action((nameParts, options) => {
|
|
6963
7278
|
if (!isRequiredOutputStatus(options.status)) {
|
|
6964
|
-
|
|
7279
|
+
fail(`Invalid --status value "${options.status}". Expected one of: ${requiredOutputStatuses.join(", ")}.`);
|
|
6965
7280
|
process.exitCode = 1;
|
|
6966
7281
|
return;
|
|
6967
7282
|
}
|
|
6968
|
-
|
|
7283
|
+
const result = recordRequiredOutput(process.cwd(), nameParts.join(" "), options.status, options.evidence);
|
|
7284
|
+
if (options.json) printJson(result);
|
|
7285
|
+
else line(`Marked "${nameParts.join(" ")}" as ${options.status}.`);
|
|
6969
7286
|
});
|
|
6970
|
-
session.command("render").description("Render active session Markdown files.").action(() => {
|
|
6971
|
-
|
|
7287
|
+
session.command("render").description("Render active session Markdown files.").option("--json", "Print machine-readable JSON output.").action((options) => {
|
|
7288
|
+
const result = renderActiveSession(process.cwd());
|
|
7289
|
+
if (options.json) printJson(result);
|
|
7290
|
+
else line(`Rendered session ${result.sessionId} at ${result.sessionPath}.`);
|
|
6972
7291
|
});
|
|
6973
7292
|
session.command("checkpoint").description("Apply a batch of session events from a JSON or Markdown checkpoint file.").requiredOption("--file <file>", "Checkpoint file (.json or .md) relative to the project root.").action((options) => {
|
|
6974
7293
|
console.log(JSON.stringify(checkpointSessionFromFile(process.cwd(), options.file), null, 2));
|
|
6975
7294
|
});
|
|
6976
|
-
session.command("close").description("Close the active session.").option("--status <status>", "planned, in-progress, blocked, or complete.", "complete").action((options) => {
|
|
6977
|
-
|
|
7295
|
+
session.command("close").description("Close the active session.").option("--status <status>", "planned, in-progress, blocked, or complete.", "complete").option("--json", "Print machine-readable JSON output.").action((options) => {
|
|
7296
|
+
const result = closeSession(process.cwd(), options.status);
|
|
7297
|
+
if (options.json) printJson(result);
|
|
7298
|
+
else line(`Closed session ${result.sessionId} with status ${options.status}.`);
|
|
6978
7299
|
});
|
|
6979
7300
|
var correction = program.command("correction").description("Manage durable Agent Studio correction rules.");
|
|
6980
|
-
correction.command("list").description("List correction rules.").action(() => {
|
|
6981
|
-
|
|
7301
|
+
correction.command("list").description("List correction rules.").option("--json", "Print machine-readable JSON output.").action((options) => {
|
|
7302
|
+
const corrections = listCorrections(process.cwd());
|
|
7303
|
+
if (options.json) {
|
|
7304
|
+
printJson(corrections);
|
|
7305
|
+
return;
|
|
7306
|
+
}
|
|
7307
|
+
const rules = [...corrections.project, ...corrections.agent, ...corrections.upstream];
|
|
7308
|
+
if (rules.length === 0) {
|
|
7309
|
+
line("No correction rules yet. Add one with agent-kit correction add <text>.");
|
|
7310
|
+
return;
|
|
7311
|
+
}
|
|
7312
|
+
for (const rule of rules) {
|
|
7313
|
+
line(`${rule.id} [${rule.status}] (${rule.scope}) ${rule.text}`);
|
|
7314
|
+
}
|
|
6982
7315
|
});
|
|
6983
|
-
correction.command("add <text...>").description("Add a durable correction rule.").option("--scope <scope>", "Correction scope: project, agent, or upstream-proposal.", "project").option("--agent <agent>", "Agent id for agent-scoped corrections.").action((textParts, options) => {
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
6987
|
-
|
|
6988
|
-
|
|
6989
|
-
|
|
6990
|
-
|
|
6991
|
-
null,
|
|
6992
|
-
2
|
|
6993
|
-
)
|
|
6994
|
-
);
|
|
7316
|
+
correction.command("add <text...>").description("Add a durable correction rule.").option("--scope <scope>", "Correction scope: project, agent, or upstream-proposal.", "project").option("--agent <agent>", "Agent id for agent-scoped corrections.").option("--json", "Print machine-readable JSON output.").action((textParts, options) => {
|
|
7317
|
+
const result = addCorrection(process.cwd(), {
|
|
7318
|
+
scope: options.scope,
|
|
7319
|
+
...options.agent ? { agentId: options.agent } : {},
|
|
7320
|
+
text: textParts.join(" ")
|
|
7321
|
+
});
|
|
7322
|
+
if (options.json) printJson(result);
|
|
7323
|
+
else line(`Added ${options.scope}-scoped correction ${result.id}.`);
|
|
6995
7324
|
});
|
|
6996
|
-
correction.command("apply [id]").description("Mark a correction rule active and reviewed.").option("--id <id>", "Correction id.").action((idArgument, options) => {
|
|
7325
|
+
correction.command("apply [id]").description("Mark a correction rule active and reviewed.").option("--id <id>", "Correction id.").option("--json", "Print machine-readable JSON output.").action((idArgument, options) => {
|
|
6997
7326
|
const id = idArgument ?? options.id;
|
|
6998
7327
|
if (!id) {
|
|
6999
|
-
|
|
7328
|
+
fail("Missing correction id. Use agent-kit correction apply <id> or --id <id>.");
|
|
7000
7329
|
process.exitCode = 1;
|
|
7001
7330
|
return;
|
|
7002
7331
|
}
|
|
7003
|
-
|
|
7332
|
+
const result = applyCorrection(process.cwd(), id);
|
|
7333
|
+
if (options.json) printJson(result);
|
|
7334
|
+
else line(`Applied correction ${id}.`);
|
|
7004
7335
|
});
|
|
7005
|
-
correction.command("retire <id>").description("Retire a correction rule.").requiredOption("--reason <reason>", "Reason for retirement.").action((id, options) => {
|
|
7006
|
-
|
|
7336
|
+
correction.command("retire <id>").description("Retire a correction rule.").requiredOption("--reason <reason>", "Reason for retirement.").option("--json", "Print machine-readable JSON output.").action((id, options) => {
|
|
7337
|
+
const result = retireCorrection(process.cwd(), id, options.reason);
|
|
7338
|
+
if (options.json) printJson(result);
|
|
7339
|
+
else line(`Retired correction ${id}: ${options.reason}`);
|
|
7007
7340
|
});
|
|
7008
|
-
correction.command("propose-upstream <id>").description("Create an upstream proposal from a project or agent correction.").action((id) => {
|
|
7009
|
-
|
|
7341
|
+
correction.command("propose-upstream <id>").description("Create an upstream proposal from a project or agent correction.").option("--json", "Print machine-readable JSON output.").action((id, options) => {
|
|
7342
|
+
const result = proposeCorrectionUpstream(process.cwd(), id);
|
|
7343
|
+
if (options.json) printJson(result);
|
|
7344
|
+
else line(`Created upstream proposal from correction ${id}.`);
|
|
7010
7345
|
});
|
|
7011
7346
|
var studio = program.command("studio").description("Export and serve local Agent Studio views.");
|
|
7012
7347
|
async function runStudioServer(options) {
|
|
@@ -7016,16 +7351,14 @@ async function runStudioServer(options) {
|
|
|
7016
7351
|
host: options.host
|
|
7017
7352
|
});
|
|
7018
7353
|
if (handle.portFallback) {
|
|
7019
|
-
console.warn(
|
|
7020
|
-
`Port ${handle.requestedPort} is in use \u2014 using fallback port ${handle.port}. Kill the old process to avoid confusion.`
|
|
7021
|
-
);
|
|
7354
|
+
console.warn(`Port ${handle.requestedPort} is in use \u2014 using fallback port ${handle.port}. Kill the old process to avoid confusion.`);
|
|
7022
7355
|
}
|
|
7023
7356
|
console.log(`Agent Kit v${PACKAGE_VERSION} \u2014 live studio at ${handle.url}/`);
|
|
7024
7357
|
console.log("SSE: GET /api/events/stream | Press Ctrl+C to stop.");
|
|
7025
|
-
if (options.open) openBrowser(`${handle.url}/`);
|
|
7358
|
+
if (options.open) void openBrowser(`${handle.url}/`);
|
|
7026
7359
|
await new Promise((resolve3) => {
|
|
7027
7360
|
const shutdown = () => {
|
|
7028
|
-
handle.close().finally(resolve3);
|
|
7361
|
+
void handle.close().finally(resolve3);
|
|
7029
7362
|
};
|
|
7030
7363
|
process.once("SIGINT", shutdown);
|
|
7031
7364
|
process.once("SIGTERM", shutdown);
|
|
@@ -7034,8 +7367,13 @@ async function runStudioServer(options) {
|
|
|
7034
7367
|
studio.command("serve").description("Start localhost live Agent Studio viewer with SSE session events.").option("--port <number>", "Port to listen on.", (value) => Number.parseInt(value, 10), 9331).option("--host <host>", "Host to bind.", "127.0.0.1").option("--open", "Open the studio in your default browser.").action(async (options) => {
|
|
7035
7368
|
await runStudioServer(options);
|
|
7036
7369
|
});
|
|
7037
|
-
studio.command("export").description("Generate a self-contained static Agent Studio HTML file.").action(() => {
|
|
7038
|
-
|
|
7370
|
+
studio.command("export").description("Generate a self-contained static Agent Studio HTML file.").option("--json", "Print machine-readable JSON output.").action((options) => {
|
|
7371
|
+
const result = exportStaticStudio(process.cwd());
|
|
7372
|
+
if (options.json) {
|
|
7373
|
+
printJson(result);
|
|
7374
|
+
return;
|
|
7375
|
+
}
|
|
7376
|
+
line(`Exported ${result.sessionCount} session(s) to ${result.studioPath}.`);
|
|
7039
7377
|
});
|
|
7040
7378
|
var research = program.command("research").description("Research high-quality open-source repositories.");
|
|
7041
7379
|
research.command("discover").description("Discover GitHub repo candidates using configured queries.").option("--limit <number>", "Maximum repositories to write.", (value) => Number.parseInt(value, 10)).action(async (options) => {
|
|
@@ -7057,7 +7395,7 @@ research.command("propose-updates").description("Create a research-to-template u
|
|
|
7057
7395
|
console.log(proposeUpdates(process.cwd()));
|
|
7058
7396
|
});
|
|
7059
7397
|
program.parseAsync(process.argv).catch((error) => {
|
|
7060
|
-
|
|
7398
|
+
fail(error instanceof Error ? error.message : String(error));
|
|
7061
7399
|
process.exitCode = 1;
|
|
7062
7400
|
});
|
|
7063
7401
|
//# sourceMappingURL=index.js.map
|