@appsforgood/next-supabase-kit 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/DOGFOOD.md +9 -0
  3. package/README.md +40 -4
  4. package/REPOSITORY_SETTINGS.md +7 -3
  5. package/SUPPLY_CHAIN.md +5 -5
  6. package/UPGRADE.md +2 -1
  7. package/antigravity/commands/accessibility-pass.toml +16 -0
  8. package/antigravity/commands/browser-qa.toml +18 -0
  9. package/antigravity/commands/distinctiveness-pass.toml +16 -0
  10. package/antigravity/commands/frontend.toml +5 -4
  11. package/antigravity/commands/layout-cleanup.toml +16 -0
  12. package/antigravity/commands/responsive-cleanup.toml +16 -0
  13. package/antigravity/commands/screenshot-critique.toml +16 -0
  14. package/antigravity/commands/ui-audit.toml +17 -0
  15. package/antigravity/commands/ui-polish.toml +17 -0
  16. package/antigravity/plugin.json +9 -0
  17. package/checklists/ui-acceptance-rubric.md +58 -0
  18. package/checklists/ui-detectors.md +75 -0
  19. package/dist/index.js +793 -458
  20. package/dist/index.js.map +1 -1
  21. package/dist/studio/office/assets/office.css +109 -28
  22. package/dist/studio/office/assets/office.js +14 -63
  23. package/dist/studio/wizard/assets/wizard.css +105 -26
  24. package/dist/studio/wizard/assets/wizard.js +22 -85
  25. package/examples/next-supabase-installed/.agent-kit/agent-roster.json +7 -3
  26. package/examples/next-supabase-installed/.agent-kit/manifest.json +11 -11
  27. package/examples/next-supabase-installed/audit-output.json +7 -2
  28. package/package.json +21 -5
  29. package/prompts/ui-command-index.md +124 -0
  30. package/rosters/next-supabase-default-council.json +37 -12
  31. package/runtime-skills/ui-improvement-harness/SKILL.md +12 -0
  32. package/skills/ui-improvement-harness.md +96 -0
  33. package/templates/next-supabase/AGENT_ROSTER.md +6 -3
  34. package/templates/next-supabase/ASSISTANT_ADAPTERS.md +3 -1
  35. package/templates/next-supabase/DECISIONS.md +14 -0
  36. package/templates/next-supabase/DESIGN.md +3 -0
  37. package/templates/next-supabase/DOCS.md +5 -1
  38. package/templates/next-supabase/QUALITY_GATES.md +4 -2
  39. package/templates/next-supabase/SKILLS.md +14 -0
  40. package/templates/next-supabase/SPEC.md +5 -1
  41. package/templates/next-supabase/STYLE_GUIDE.md +3 -1
  42. 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 result = copyTextWithConflict(sourcePath, cwd, join3(".agent-kit", "skills", normalized), {
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 `${result.action}: ${result.target}`;
144
+ return { ...result, dryRun: false };
141
145
  }
142
146
 
143
147
  // src/install/adapter-validate.ts
144
- import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
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.5";
153
+ var PACKAGE_VERSION = "0.1.6";
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 readFileSync2 } from "fs";
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(readFileSync2(path, "utf8"));
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((line) => line.trim().length > 0).map((line) => JSON.parse(line));
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 readFileSync8, statSync } from "fs";
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 readFileSync3 } from "fs";
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(readFileSync3(path, "utf8"));
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((line) => line.trim()).filter((line) => line && !line.startsWith("#") && line.includes("=")).map((line) => line.split("=")[0]?.trim() ?? "").filter(Boolean)
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 readFileSync7 } from "fs";
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 readFileSync6 } from "fs";
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 readFileSync5, readdirSync as readdirSync2 } from "fs";
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 readFileSync4 } from "fs";
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 = readFileSync4(path, "utf8");
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
- (agent) => ({
1221
- id: `brief-${agent.id}`,
1222
- section: "team",
1223
- title: `Brief ${agent.name}`,
1224
- why: `${agent.roleSummary} What should they know about this project that is not obvious from the repo?`,
1225
- fields: [`agentBrief_${agent.id}`],
1226
- agentId: agent.id,
1227
- agentName: agent.name,
1228
- roleSummary: agent.roleSummary,
1229
- depth: depths,
1230
- optional: true
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 line of adaptersDoc.split("\n")) {
1242
- const trimmed = line.trim();
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 = readFileSync5(targetPath, "utf8");
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(readFileSync5(path, "utf8"));
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 = readFileSync5(join8(skillsRoot, file), "utf8");
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
- cwd,
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 = readFileSync6(path, "utf8");
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(readFileSync7(templatePath, "utf8"));
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(readFileSync7(manifestPath, "utf8"));
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) ? readFileSync8(path, "utf8") : "";
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(readFileSync8(packagePath, "utf8"));
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(readFileSync8(path, "utf8"));
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) ? readFileSync8(path, "utf8") : null;
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(readFileSync8(rosterPath, "utf8"));
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(readFileSync8(join11(sessionsRoot, sessionFile), "utf8"));
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(readFileSync8(schemaPath, "utf8"));
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(readFileSync8(contextPath, "utf8"));
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(readFileSync8(path, "utf8"));
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 = readFileSync8(studioExportPath, "utf8");
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(readFileSync8(join11(sessionDirPath, "session.json"), "utf8")));
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 = readFileSync8(eventsPath2, "utf8");
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((line) => line.trim().length > 0);
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, line] of eventLines.entries()) {
2271
+ for (const [index, line2] of eventLines.entries()) {
2292
2272
  try {
2293
- const result = SessionEventContract.safeParse(JSON.parse(line));
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 = readFileSync8(join11(sessionDirPath, "index.md"), "utf8");
2323
- const transcriptText = readFileSync8(join11(sessionDirPath, "transcript.md"), "utf8");
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(readFileSync8(routingPath, "utf8"));
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(readFileSync8(targetPath, "utf8"));
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(readFileSync8(path, "utf8"));
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 = readFileSync8(join11(migrationsDir, file), "utf8");
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 = readFileSync8(join11(cwd, file), "utf8");
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,25 @@ function createAuditReport(cwd) {
3095
3068
  }
3096
3069
 
3097
3070
  // src/install/adapter-validate.ts
3098
- var REQUIRED_COMMANDS = ["setup", "audit", "plan", "handoff", "frontend", "security", "copy", "ship", "upgrade"];
3071
+ var REQUIRED_COMMANDS = [
3072
+ "setup",
3073
+ "audit",
3074
+ "plan",
3075
+ "handoff",
3076
+ "frontend",
3077
+ "ui-audit",
3078
+ "ui-polish",
3079
+ "layout-cleanup",
3080
+ "responsive-cleanup",
3081
+ "accessibility-pass",
3082
+ "distinctiveness-pass",
3083
+ "screenshot-critique",
3084
+ "browser-qa",
3085
+ "security",
3086
+ "copy",
3087
+ "ship",
3088
+ "upgrade"
3089
+ ];
3099
3090
  var REQUIRED_SOURCE_REFERENCES = ["AGENTS.md", ".agent-kit/agent-roster.json", "QUALITY_GATES.md"];
3100
3091
  function summary(findings) {
3101
3092
  return {
@@ -3109,7 +3100,7 @@ function report(target, findings) {
3109
3100
  }
3110
3101
  function readJson(path) {
3111
3102
  try {
3112
- return JSON.parse(readFileSync9(path, "utf8"));
3103
+ return JSON.parse(readFileSync10(path, "utf8"));
3113
3104
  } catch {
3114
3105
  return null;
3115
3106
  }
@@ -3170,11 +3161,11 @@ function validateAntigravityCommands(layout, findings) {
3170
3161
  level: "fail",
3171
3162
  area: "commands",
3172
3163
  message: `Missing Antigravity command ${relativePath}.`,
3173
- remediation: "Restore the full native command set: setup, audit, plan, handoff, frontend, security, copy, ship, and upgrade."
3164
+ remediation: "Restore the full native command set, including frontend and UI improvement commands."
3174
3165
  });
3175
3166
  continue;
3176
3167
  }
3177
- const text = readFileSync9(path, "utf8");
3168
+ const text = readFileSync10(path, "utf8");
3178
3169
  addSecretFinding(relativePath, text, findings);
3179
3170
  const name = commandField(text, "name");
3180
3171
  const description = commandField(text, "description");
@@ -3263,10 +3254,11 @@ function validateAntigravityPlugin(layout, findings) {
3263
3254
  for (const entry of [...commands, ...skills]) {
3264
3255
  const path = typeof entry.path === "string" ? entry.path : "";
3265
3256
  if (!path || !isSafeRelativePath(path)) {
3257
+ const entryName = typeof entry.name === "string" ? entry.name : "unknown";
3266
3258
  findings.push({
3267
3259
  level: "fail",
3268
3260
  area: "manifest",
3269
- message: `plugin.json has an unsafe or missing relative path for ${String(entry.name ?? "unknown")}.`,
3261
+ message: `plugin.json has an unsafe or missing relative path for ${entryName}.`,
3270
3262
  remediation: "Use relative paths that stay inside the plugin/runtime skill bundle."
3271
3263
  });
3272
3264
  continue;
@@ -3281,7 +3273,7 @@ function validateAntigravityPlugin(layout, findings) {
3281
3273
  });
3282
3274
  }
3283
3275
  }
3284
- const pluginText = readFileSync9(pluginPath, "utf8");
3276
+ const pluginText = readFileSync10(pluginPath, "utf8");
3285
3277
  addSecretFinding("plugin.json", pluginText, findings);
3286
3278
  if (Array.isArray(plugin.sourceOfTruth) && plugin.sourceOfTruth.includes("AGENTS.md") && plugin.sourceOfTruth.includes(".agent-kit/agent-roster.json")) {
3287
3279
  findings.push({
@@ -3314,7 +3306,7 @@ function validateRuntimeSkills(cwd, layout, findings) {
3314
3306
  });
3315
3307
  continue;
3316
3308
  }
3317
- const text = readFileSync9(runtimePath, "utf8");
3309
+ const text = readFileSync10(runtimePath, "utf8");
3318
3310
  addSecretFinding(`${skillName}/SKILL.md`, text, findings);
3319
3311
  if (!/^---\nname: .+\ndescription: .+\n---/m.test(text)) {
3320
3312
  findings.push({
@@ -3363,7 +3355,7 @@ function validateAntigravity(cwd) {
3363
3355
  }
3364
3356
  ]);
3365
3357
  }
3366
- const adapterDoc = existsSync12(layout.adapterDocPath) ? readFileSync9(layout.adapterDocPath, "utf8") : "";
3358
+ const adapterDoc = existsSync12(layout.adapterDocPath) ? readFileSync10(layout.adapterDocPath, "utf8") : "";
3367
3359
  if (!adapterDoc) {
3368
3360
  findings.push({
3369
3361
  level: "fail",
@@ -3439,7 +3431,7 @@ function validateBasicAdapter(cwd, target) {
3439
3431
  });
3440
3432
  continue;
3441
3433
  }
3442
- const text = readFileSync9(path, "utf8");
3434
+ const text = readFileSync10(path, "utf8");
3443
3435
  addSecretFinding(relativePath, text, findings);
3444
3436
  if (!text.includes("AGENTS.md") && !text.includes("MODEL_ROUTING.md")) {
3445
3437
  findings.push({
@@ -3464,7 +3456,7 @@ function validateBasicAdapter(cwd, target) {
3464
3456
  }
3465
3457
  function readAssistantAdaptersDoc(cwd) {
3466
3458
  const path = join12(cwd, "ASSISTANT_ADAPTERS.md");
3467
- return existsSync12(path) ? readFileSync9(path, "utf8") : "";
3459
+ return existsSync12(path) ? readFileSync10(path, "utf8") : "";
3468
3460
  }
3469
3461
  function adaptersRowIsActive(doc, toolLabel) {
3470
3462
  return assistantAdapterRowIsActive(doc, toolLabel);
@@ -3482,7 +3474,7 @@ function validateInstalledIdeAdapter(cwd, target) {
3482
3474
  remediation: "Run agent-kit init or agent-kit init --activate cursor."
3483
3475
  });
3484
3476
  } else {
3485
- addSecretFinding(".cursor/rules/cursor-agent-kit.mdc", readFileSync9(rulesPath, "utf8"), findings);
3477
+ addSecretFinding(".cursor/rules/cursor-agent-kit.mdc", readFileSync10(rulesPath, "utf8"), findings);
3486
3478
  }
3487
3479
  const plannerAgent = join12(cwd, ".cursor/agents/planner.md");
3488
3480
  if (existsSync12(plannerAgent)) {
@@ -3585,7 +3577,7 @@ function validatePackage(cwd) {
3585
3577
  findings.push(...validateAntigravity(cwd).findings);
3586
3578
  for (const doc of ["README.md", "DOCS.md", "SPEC.md", "DECISIONS.md", "QUALITY_GATES.md", "TESTING.md", "UPGRADE.md"]) {
3587
3579
  const path = join12(cwd, doc);
3588
- const text = existsSync12(path) ? readFileSync9(path, "utf8") : "";
3580
+ const text = existsSync12(path) ? readFileSync10(path, "utf8") : "";
3589
3581
  const lower = text.toLowerCase();
3590
3582
  if (!lower.includes("antigravity") && !lower.includes("runtime command") && !lower.includes("runtime adapter")) {
3591
3583
  findings.push({
@@ -3637,12 +3629,12 @@ function validatePackage(cwd) {
3637
3629
  }
3638
3630
 
3639
3631
  // src/install/diff.ts
3640
- import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
3632
+ import { existsSync as existsSync13, readFileSync as readFileSync11 } from "fs";
3641
3633
  import { join as join13 } from "path";
3642
3634
  function statusForTextFile(target, template) {
3643
3635
  if (!existsSync13(target)) return "missing";
3644
- const targetHash = sha256(readFileSync10(target, "utf8"));
3645
- const templateHash = sha256(readFileSync10(template, "utf8"));
3636
+ const targetHash = sha256(readFileSync11(target, "utf8"));
3637
+ const templateHash = sha256(readFileSync11(template, "utf8"));
3646
3638
  return targetHash === templateHash ? "unchanged" : "changed";
3647
3639
  }
3648
3640
  function diffProject(cwd, stack = "next-supabase") {
@@ -3711,10 +3703,176 @@ function diffProject(cwd, stack = "next-supabase") {
3711
3703
  return result;
3712
3704
  }
3713
3705
 
3706
+ // src/install/update.ts
3707
+ import { existsSync as existsSync14, readFileSync as readFileSync12 } from "fs";
3708
+ import { join as join14, relative as relative2 } from "path";
3709
+ function planFileUpdate(cwd, input) {
3710
+ const sourceContent = readFileSync12(input.sourcePath, "utf8");
3711
+ const sourceHash = sha256(sourceContent);
3712
+ const targetPath = resolveInside(cwd, input.target);
3713
+ if (!existsSync14(targetPath)) {
3714
+ return { target: input.target, action: "created", reason: "File is missing locally.", sourceContent };
3715
+ }
3716
+ const localHash = sha256(readFileSync12(targetPath, "utf8"));
3717
+ if (localHash === sourceHash) {
3718
+ return { target: input.target, action: "unchanged", reason: "File already matches the current template.", sourceContent };
3719
+ }
3720
+ if (input.installedHash && localHash === input.installedHash) {
3721
+ return { target: input.target, action: "updated", reason: "File was unmodified since install; applied the newer template.", sourceContent };
3722
+ }
3723
+ if (input.force) {
3724
+ return { target: input.target, action: "overwritten", reason: "Local changes overwritten because --force was used.", sourceContent };
3725
+ }
3726
+ if (input.installedHash && input.installedHash === sourceHash) {
3727
+ return { target: input.target, action: "kept-local", reason: "File is locally customized and the template has not changed.", sourceContent };
3728
+ }
3729
+ return {
3730
+ target: input.target,
3731
+ action: "conflict",
3732
+ reason: "File is locally customized and the bundled template changed; review the conflict copy.",
3733
+ sourceContent
3734
+ };
3735
+ }
3736
+ function writeConflictCopy(cwd, target, content) {
3737
+ const conflictRoot = join14(cwd, ".agent-kit", "conflicts");
3738
+ const safeName = `${Date.now()}-${target.replace(/[^a-zA-Z0-9_.-]/g, "_")}`;
3739
+ const conflictPath = join14(conflictRoot, safeName);
3740
+ writeText(conflictPath, content);
3741
+ return relative2(cwd, conflictPath).replace(/\\/g, "/");
3742
+ }
3743
+ function updateProject(options) {
3744
+ const cwd = options.cwd;
3745
+ const force = Boolean(options.force);
3746
+ const dryRun = Boolean(options.dryRun);
3747
+ const manifest = readManifest(cwd);
3748
+ if (!manifest) {
3749
+ if (dryRun) {
3750
+ throw new Error("No .agent-kit/manifest.json found. Run agent-kit init first (or run update without --dry-run to install).");
3751
+ }
3752
+ const initResult = initProject({ cwd, force });
3753
+ const files2 = [
3754
+ ...initResult.copied.map((target) => ({ target, action: "created", reason: "Installed by init fallback." })),
3755
+ ...initResult.unchanged.map((target) => ({ target, action: "unchanged", reason: "Already matched the template." })),
3756
+ ...initResult.overwritten.map((target) => ({ target, action: "overwritten", reason: "Overwritten by init --force fallback." })),
3757
+ ...initResult.conflicts.map((entry) => {
3758
+ const [target, conflictPath] = entry.split(" -> ");
3759
+ return {
3760
+ target: target ?? entry,
3761
+ action: "conflict",
3762
+ reason: "Local file differed from the template during init fallback.",
3763
+ ...conflictPath ? { conflictPath } : {}
3764
+ };
3765
+ })
3766
+ ];
3767
+ return {
3768
+ dryRun,
3769
+ files: files2,
3770
+ libraryFoldersRefreshed: [...LIBRARY_FOLDERS],
3771
+ manifestPath: ".agent-kit/manifest.json",
3772
+ summary: summarize(files2)
3773
+ };
3774
+ }
3775
+ const packageRoot = findPackageRoot();
3776
+ const stack = manifest.stack ?? "next-supabase";
3777
+ const templateRoot = join14(packageRoot, "templates", stack);
3778
+ if (!existsSync14(templateRoot)) {
3779
+ throw new Error(`Unsupported stack profile in manifest: ${stack}`);
3780
+ }
3781
+ const files = [];
3782
+ const templateHashes = {};
3783
+ const plans = [];
3784
+ for (const doc of ROOT_DOCS) {
3785
+ const sourcePath = join14(templateRoot, doc);
3786
+ templateHashes[doc] = sha256(readFileSync12(sourcePath, "utf8"));
3787
+ plans.push(
3788
+ planFileUpdate(cwd, {
3789
+ target: doc,
3790
+ sourcePath,
3791
+ installedHash: manifest.templateHashes?.[doc],
3792
+ force
3793
+ })
3794
+ );
3795
+ }
3796
+ for (const adapter2 of CURSOR_ADAPTER_FILES) {
3797
+ plans.push(
3798
+ planFileUpdate(cwd, {
3799
+ target: adapter2.target,
3800
+ sourcePath: join14(packageRoot, adapter2.source),
3801
+ installedHash: void 0,
3802
+ force
3803
+ })
3804
+ );
3805
+ }
3806
+ plans.push(
3807
+ planFileUpdate(cwd, {
3808
+ target: DEFAULT_AGENT_ROSTER_TARGET,
3809
+ sourcePath: join14(packageRoot, DEFAULT_AGENT_ROSTER_SOURCE),
3810
+ installedHash: void 0,
3811
+ force
3812
+ }),
3813
+ planFileUpdate(cwd, {
3814
+ target: DEFAULT_MODEL_ROUTING_TARGET,
3815
+ sourcePath: join14(packageRoot, DEFAULT_MODEL_ROUTING_SOURCE),
3816
+ installedHash: void 0,
3817
+ force
3818
+ })
3819
+ );
3820
+ for (const plan of plans) {
3821
+ const { sourceContent, ...fileResult } = plan;
3822
+ if (!dryRun) {
3823
+ if (plan.action === "created" || plan.action === "updated" || plan.action === "overwritten") {
3824
+ writeText(resolveInside(cwd, plan.target), sourceContent);
3825
+ } else if (plan.action === "conflict") {
3826
+ fileResult.conflictPath = writeConflictCopy(cwd, plan.target, sourceContent);
3827
+ }
3828
+ }
3829
+ files.push(fileResult);
3830
+ }
3831
+ if (!dryRun) {
3832
+ ensureDir(join14(cwd, ".agent-kit"));
3833
+ for (const folder of LIBRARY_FOLDERS) {
3834
+ copyDirectory(join14(packageRoot, folder), join14(cwd, ".agent-kit", folder));
3835
+ }
3836
+ const updatedManifest = {
3837
+ packageName: PACKAGE_NAME,
3838
+ packageVersion: PACKAGE_VERSION,
3839
+ stack,
3840
+ installedAt: manifest.installedAt,
3841
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
3842
+ docs: [...ROOT_DOCS],
3843
+ libraryFolders: [...LIBRARY_FOLDERS],
3844
+ agentRoster: DEFAULT_AGENT_ROSTER_TARGET,
3845
+ modelRouting: DEFAULT_MODEL_ROUTING_TARGET,
3846
+ templateHashes
3847
+ };
3848
+ writeText(join14(cwd, ".agent-kit", "manifest.json"), `${JSON.stringify(updatedManifest, null, 2)}
3849
+ `);
3850
+ }
3851
+ return {
3852
+ dryRun,
3853
+ files,
3854
+ libraryFoldersRefreshed: [...LIBRARY_FOLDERS],
3855
+ manifestPath: ".agent-kit/manifest.json",
3856
+ summary: summarize(files)
3857
+ };
3858
+ }
3859
+ function summarize(files) {
3860
+ const summary2 = {
3861
+ created: 0,
3862
+ updated: 0,
3863
+ unchanged: 0,
3864
+ "kept-local": 0,
3865
+ conflict: 0,
3866
+ overwritten: 0
3867
+ };
3868
+ for (const file of files) summary2[file.action] += 1;
3869
+ return summary2;
3870
+ }
3871
+
3714
3872
  // src/research/discover.ts
3715
3873
  import { Octokit } from "@octokit/rest";
3716
- import { readFileSync as readFileSync11 } from "fs";
3717
- import { join as join14 } from "path";
3874
+ import { readFileSync as readFileSync13 } from "fs";
3875
+ import { join as join15 } from "path";
3718
3876
 
3719
3877
  // src/research/config.ts
3720
3878
  import { z as z2 } from "zod";
@@ -3739,8 +3897,8 @@ var researchConfigSchema = z2.object({
3739
3897
  // src/research/discover.ts
3740
3898
  async function discoverRepos(options) {
3741
3899
  const packageRoot = findPackageRoot();
3742
- const configPath = join14(packageRoot, "research", "scan-config.json");
3743
- const config = researchConfigSchema.parse(JSON.parse(readFileSync11(configPath, "utf8")));
3900
+ const configPath = join15(packageRoot, "research", "scan-config.json");
3901
+ const config = researchConfigSchema.parse(JSON.parse(readFileSync13(configPath, "utf8")));
3744
3902
  const token = options.token ?? process.env.GITHUB_TOKEN;
3745
3903
  if (!token) {
3746
3904
  throw new Error("GITHUB_TOKEN is required for GitHub API research discovery.");
@@ -3801,20 +3959,20 @@ async function discoverRepos(options) {
3801
3959
  }
3802
3960
  }
3803
3961
  const candidates = [...deduped.values()].slice(0, maxRepos);
3804
- const output = options.output ?? join14(options.cwd, "research", "repo-candidates.json");
3962
+ const output = options.output ?? join15(options.cwd, "research", "repo-candidates.json");
3805
3963
  writeText(output, `${JSON.stringify(candidates, null, 2)}
3806
3964
  `);
3807
3965
  return candidates;
3808
3966
  }
3809
3967
 
3810
3968
  // src/research/scan.ts
3811
- import { existsSync as existsSync16, mkdirSync as mkdirSync2, readFileSync as readFileSync13, rmSync } from "fs";
3812
- import { join as join16 } from "path";
3969
+ import { existsSync as existsSync16, mkdirSync as mkdirSync2, readFileSync as readFileSync15, rmSync } from "fs";
3970
+ import { join as join17 } from "path";
3813
3971
  import { simpleGit } from "simple-git";
3814
3972
 
3815
3973
  // src/research/analyze.ts
3816
- import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
3817
- import { join as join15 } from "path";
3974
+ import { existsSync as existsSync15, readFileSync as readFileSync14 } from "fs";
3975
+ import { join as join16 } from "path";
3818
3976
  function normalizeRelativePath(file) {
3819
3977
  return file.replace(/\\/g, "/");
3820
3978
  }
@@ -3822,8 +3980,8 @@ function hasFile(files, matcher) {
3822
3980
  return files.some((file) => matcher.test(normalizeRelativePath(file)));
3823
3981
  }
3824
3982
  function fileText(root, file) {
3825
- const path = join15(root, file);
3826
- return existsSync15(path) ? readFileSync12(path, "utf8") : "";
3983
+ const path = join16(root, file);
3984
+ return existsSync15(path) ? readFileSync14(path, "utf8") : "";
3827
3985
  }
3828
3986
  function textIncludes(root, files, matcher, terms) {
3829
3987
  const lowerTerms = terms.map((term) => term.toLowerCase());
@@ -3954,24 +4112,24 @@ ${finding.impactOnKit.map((item) => `- ${item}`).join("\n")}
3954
4112
  `;
3955
4113
  }
3956
4114
  async function scanRepos(options) {
3957
- const candidatesPath = options.candidatesPath ?? join16(options.cwd, "research", "repo-candidates.json");
4115
+ const candidatesPath = options.candidatesPath ?? join17(options.cwd, "research", "repo-candidates.json");
3958
4116
  if (!existsSync16(candidatesPath)) {
3959
4117
  throw new Error(`Candidates file not found: ${candidatesPath}`);
3960
4118
  }
3961
- const candidates = JSON.parse(readFileSync13(candidatesPath, "utf8"));
3962
- const workdir = options.workdir ?? join16(options.cwd, "research", "workdir");
4119
+ const candidates = JSON.parse(readFileSync15(candidatesPath, "utf8"));
4120
+ const workdir = options.workdir ?? join17(options.cwd, "research", "workdir");
3963
4121
  mkdirSync2(workdir, { recursive: true });
3964
- mkdirSync2(join16(options.cwd, "research", "findings"), { recursive: true });
4122
+ mkdirSync2(join17(options.cwd, "research", "findings"), { recursive: true });
3965
4123
  const findings = [];
3966
4124
  const git = simpleGit();
3967
4125
  for (const candidate of candidates) {
3968
4126
  const repoSlug = candidate.fullName.replace("/", "__");
3969
- const repoPath = join16(workdir, repoSlug);
4127
+ const repoPath = join17(workdir, repoSlug);
3970
4128
  if (existsSync16(repoPath)) rmSync(repoPath, { recursive: true, force: true });
3971
4129
  await git.raw(["clone", "--depth", "1", candidate.htmlUrl, repoPath]);
3972
4130
  const finding = analyzeRepository(candidate, repoPath);
3973
4131
  findings.push(finding);
3974
- writeText(join16(options.cwd, "research", "findings", `${repoSlug}.md`), findingToMarkdown(finding));
4132
+ writeText(join17(options.cwd, "research", "findings", `${repoSlug}.md`), findingToMarkdown(finding));
3975
4133
  if (!options.keepClones) {
3976
4134
  rmSync(repoPath, { recursive: true, force: true });
3977
4135
  }
@@ -3980,8 +4138,8 @@ async function scanRepos(options) {
3980
4138
  }
3981
4139
 
3982
4140
  // src/research/summarize.ts
3983
- import { existsSync as existsSync17, readFileSync as readFileSync14, readdirSync as readdirSync3 } from "fs";
3984
- import { join as join17 } from "path";
4141
+ import { existsSync as existsSync17, readFileSync as readFileSync16, readdirSync as readdirSync3 } from "fs";
4142
+ import { join as join18 } from "path";
3985
4143
  var SUMMARY_TARGETS = {
3986
4144
  "nextjs-patterns": {
3987
4145
  title: "Next.js Patterns",
@@ -4043,7 +4201,7 @@ function sectionBullets(text, start, end) {
4043
4201
  const afterStart = text.slice(startIndex + start.length);
4044
4202
  const endIndex = afterStart.indexOf(end);
4045
4203
  const section = endIndex === -1 ? afterStart : afterStart.slice(0, endIndex);
4046
- return section.split("\n").map((line) => line.trim()).filter((line) => line.startsWith("- ") && !line.includes("None detected")).map((line) => line.slice(2));
4204
+ return section.split("\n").map((line2) => line2.trim()).filter((line2) => line2.startsWith("- ") && !line2.includes("None detected")).map((line2) => line2.slice(2));
4047
4205
  }
4048
4206
  function parseFinding(file, text) {
4049
4207
  const fullName = text.match(/^# Repo Finding: (.+)$/m)?.[1];
@@ -4084,12 +4242,12 @@ function renderRepoList(findings, scoreKeys) {
4084
4242
  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
4243
  }
4086
4244
  function summarizeFindings(cwd) {
4087
- const findingsDir = join17(cwd, "research", "findings");
4245
+ const findingsDir = join18(cwd, "research", "findings");
4088
4246
  if (!existsSync17(findingsDir)) {
4089
4247
  throw new Error("No research/findings directory exists. Run agent-kit research scan first.");
4090
4248
  }
4091
4249
  const findingFiles = readdirSync3(findingsDir).filter((file) => file.endsWith(".md"));
4092
- const findings = findingFiles.map((file) => parseFinding(file, readFileSync14(join17(findingsDir, file), "utf8"))).filter((finding) => finding !== null);
4250
+ const findings = findingFiles.map((file) => parseFinding(file, readFileSync16(join18(findingsDir, file), "utf8"))).filter((finding) => finding !== null);
4093
4251
  const categoryCounts = countBy(findings.map((finding) => finding.category));
4094
4252
  const outputs = [];
4095
4253
  const overview = `# Research Scan Overview
@@ -4108,13 +4266,13 @@ ${countBy(findings.flatMap((finding) => finding.strongPractices)).slice(0, 12).m
4108
4266
  ## Most Repeated Gaps
4109
4267
  ${countBy(findings.flatMap((finding) => finding.weakPractices)).slice(0, 12).map(([practice, count]) => `- ${practice} (${count})`).join("\n")}
4110
4268
  `;
4111
- const overviewPath = join17(cwd, "research", "summaries", "scan-overview.md");
4269
+ const overviewPath = join18(cwd, "research", "summaries", "scan-overview.md");
4112
4270
  writeText(overviewPath, overview);
4113
4271
  outputs.push(overviewPath);
4114
4272
  for (const [target, config] of Object.entries(SUMMARY_TARGETS)) {
4115
4273
  const categories = config.categories;
4116
4274
  const scopedFindings = findings.filter((finding) => categories.includes(finding.category));
4117
- const path = join17(cwd, "research", "summaries", `${target}.md`);
4275
+ const path = join18(cwd, "research", "summaries", `${target}.md`);
4118
4276
  const summary2 = `# ${config.title}
4119
4277
 
4120
4278
  Generated from ${scopedFindings.length} relevant repository findings.
@@ -4155,12 +4313,19 @@ Review the generated research summaries, then convert repeated best practices in
4155
4313
 
4156
4314
  Do not copy source code from scanned repositories. Adopt only generalized practices with clear rationale.
4157
4315
  `;
4158
- const path = join17(cwd, "research", "proposed-updates.md");
4316
+ const path = join18(cwd, "research", "proposed-updates.md");
4159
4317
  writeText(path, output);
4160
4318
  return path;
4161
4319
  }
4162
4320
 
4163
4321
  // src/studio/corrections.ts
4322
+ var VALID_CORRECTION_SCOPES = ["session", "project", "agent", "upstream-proposal"];
4323
+ function parseCorrectionScope(scope) {
4324
+ if (typeof scope === "string" && VALID_CORRECTION_SCOPES.includes(scope)) {
4325
+ return scope;
4326
+ }
4327
+ throw new Error(`Invalid correction scope: expected one of ${VALID_CORRECTION_SCOPES.join(", ")}`);
4328
+ }
4164
4329
  function fileForScope(scope) {
4165
4330
  if (scope === "agent") return AGENT_RULES_JSON;
4166
4331
  if (scope === "upstream-proposal") return UPSTREAM_PROPOSALS_JSON;
@@ -4184,14 +4349,15 @@ function ensureCorrectionFiles(cwd) {
4184
4349
  }
4185
4350
  }
4186
4351
  function addCorrection(cwd, options) {
4352
+ const scope = parseCorrectionScope(options.scope);
4187
4353
  ensureCorrectionFiles(cwd);
4188
- const targetPath = fileForScope(options.scope);
4354
+ const targetPath = fileForScope(scope);
4189
4355
  const rules = readCorrectionRules(cwd, targetPath);
4190
4356
  const id = options.id ?? safeSlug(options.text).slice(0, 48);
4191
4357
  const rule = {
4192
4358
  id,
4193
- scope: options.scope,
4194
- status: options.scope === "upstream-proposal" ? "proposed" : "active",
4359
+ scope,
4360
+ status: scope === "upstream-proposal" ? "proposed" : "active",
4195
4361
  text: redactSensitive(options.text),
4196
4362
  ...options.agentId ? { agentId: options.agentId, appliesToAgents: [options.agentId] } : {},
4197
4363
  ...options.sourceSessionId ? { sourceSessionId: options.sourceSessionId } : {},
@@ -4264,8 +4430,8 @@ function proposeCorrectionUpstream(cwd, id) {
4264
4430
  }
4265
4431
 
4266
4432
  // src/studio/session.ts
4267
- import { existsSync as existsSync18, readFileSync as readFileSync15, readdirSync as readdirSync4, statSync as statSync2 } from "fs";
4268
- import { join as join18 } from "path";
4433
+ import { existsSync as existsSync18, readFileSync as readFileSync17, readdirSync as readdirSync4, statSync as statSync2 } from "fs";
4434
+ import { join as join19 } from "path";
4269
4435
  function sessionDir(sessionId) {
4270
4436
  return `${COUNCIL_SESSIONS_DIR}/${safeSlug(sessionId)}`;
4271
4437
  }
@@ -4322,9 +4488,9 @@ function startSession(cwd, options) {
4322
4488
  return { sessionId, sessionPath: sessionDir(sessionId) };
4323
4489
  }
4324
4490
  function listSessions(cwd) {
4325
- const root = join18(cwd, COUNCIL_SESSIONS_DIR);
4491
+ const root = join19(cwd, COUNCIL_SESSIONS_DIR);
4326
4492
  if (!existsSync18(root)) return [];
4327
- return readdirSync4(root).filter((entry) => entry !== "active").map((entry) => join18(root, entry, "session.json")).filter((path) => existsSync18(path) && statSync2(path).isFile()).map((path) => StudioSessionContract.parse(JSON.parse(readFileSync15(path, "utf8")))).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
4493
+ 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
4494
  }
4329
4495
  function getActiveSessionId(cwd) {
4330
4496
  const active = readTextFile(cwd, ACTIVE_SESSION_FILE)?.trim();
@@ -4581,8 +4747,8 @@ function renderSessionTranscript(session2, events) {
4581
4747
  }
4582
4748
  const sections = [...byAgent.entries()].map(([agentId, agentEvents]) => {
4583
4749
  const rows = agentEvents.map((event) => {
4584
- const detail = event.text ?? event.decision ?? event.command ?? event.artifactPath ?? (event.outputName ? `${event.outputName}: ${event.outputStatus ?? ""}` : void 0) ?? event.status ?? "";
4585
- return `- ${event.createdAt} \`${event.type}\`: ${escapeMarkdownText(detail)}`;
4750
+ const detail2 = event.text ?? event.decision ?? event.command ?? event.artifactPath ?? (event.outputName ? `${event.outputName}: ${event.outputStatus ?? ""}` : void 0) ?? event.status ?? "";
4751
+ return `- ${event.createdAt} \`${event.type}\`: ${escapeMarkdownText(detail2)}`;
4586
4752
  });
4587
4753
  return `## ${escapeMarkdownText(agentId)}
4588
4754
 
@@ -4745,7 +4911,9 @@ function renderCorrections(data) {
4745
4911
  return `<table>
4746
4912
  <thead><tr><th>Scope</th><th>Agent</th><th>Correction</th></tr></thead>
4747
4913
  <tbody>
4748
- ${rules.map((rule) => `<tr><td>${escapeHtml(rule.scope)}</td><td>${escapeHtml(rule.agentId ?? rule.appliesToAgents?.join(", ") ?? "all")}</td><td>${escapeHtml(rule.text)}</td></tr>`).join("\n")}
4914
+ ${rules.map(
4915
+ (rule) => `<tr><td>${escapeHtml(rule.scope)}</td><td>${escapeHtml(rule.agentId ?? rule.appliesToAgents?.join(", ") ?? "all")}</td><td>${escapeHtml(rule.text)}</td></tr>`
4916
+ ).join("\n")}
4749
4917
  </tbody>
4750
4918
  </table>`;
4751
4919
  }
@@ -4794,13 +4962,16 @@ function renderAgentStreams(item) {
4794
4962
  const agent = event.agentId ?? event.fromAgentId ?? "session";
4795
4963
  byAgent.set(agent, [...byAgent.get(agent) ?? [], event]);
4796
4964
  }
4797
- return [...byAgent.entries()].map(([agent, events]) => `<details class="agent-stream"><summary>${escapeHtml(agent)} (${events.length})</summary><div class="stream-body">${renderEventList(events)}</div></details>`).join("\n");
4965
+ return [...byAgent.entries()].map(
4966
+ ([agent, events]) => `<details class="agent-stream"><summary>${escapeHtml(agent)} (${events.length})</summary><div class="stream-body">${renderEventList(events)}</div></details>`
4967
+ ).join("\n");
4798
4968
  }
4799
4969
  function renderEventList(events) {
4800
4970
  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
4971
  }
4802
4972
  function eventDetail(event) {
4803
- if (event.type === "handoff") return `${event.fromAgentId ?? "unknown"} -> ${event.toAgentId ?? "unknown"}: ${event.decision ?? ""} Risk: ${event.risk ?? ""}`;
4973
+ if (event.type === "handoff")
4974
+ return `${event.fromAgentId ?? "unknown"} -> ${event.toAgentId ?? "unknown"}: ${event.decision ?? ""} Risk: ${event.risk ?? ""}`;
4804
4975
  if (event.type === "required_output_updated") return `${event.outputName ?? "output"}: ${event.outputStatus ?? "unknown"}`;
4805
4976
  return event.text ?? event.decision ?? event.command ?? event.artifactPath ?? event.status ?? "";
4806
4977
  }
@@ -4871,28 +5042,6 @@ function openBrowser(url) {
4871
5042
 
4872
5043
  // src/studio/setup-init.ts
4873
5044
  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
5045
  async function promptStartSetup(defaultYes = true) {
4897
5046
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
4898
5047
  const rl = createInterface({ input: process.stdin, output: process.stdout });
@@ -4914,7 +5063,7 @@ import { createServer } from "http";
4914
5063
  // src/studio/setup-form.ts
4915
5064
  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
5065
  function splitLines(value) {
4917
- return value.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
5066
+ return value.split(/\r?\n/).map((line2) => line2.trim()).filter(Boolean);
4918
5067
  }
4919
5068
  function uniqueStrings(values) {
4920
5069
  return [...new Set(values.filter(Boolean))];
@@ -4968,10 +5117,7 @@ function applySetupFormAnswers(cwd, payload) {
4968
5117
  qualityTarget: payload.qualityTarget,
4969
5118
  owners,
4970
5119
  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
- ])
5120
+ evidence: uniqueEvidence2([...base.evidence, { source: "agent-kit setup wizard", note: "Project context updated through the local web setup wizard." }])
4975
5121
  };
4976
5122
  return writeProjectContext(cwd, updated);
4977
5123
  }
@@ -5022,8 +5168,8 @@ function parseSetupFormPayload(raw) {
5022
5168
  }
5023
5169
 
5024
5170
  // src/studio/wizard/checklist.ts
5025
- import { existsSync as existsSync19, readFileSync as readFileSync16 } from "fs";
5026
- import { join as join19 } from "path";
5171
+ import { existsSync as existsSync19, readFileSync as readFileSync18 } from "fs";
5172
+ import { join as join20 } from "path";
5027
5173
  var IDE_PATHS = {
5028
5174
  cursor: ".cursor/agents/planner.md",
5029
5175
  copilot: ".github/copilot-instructions.md",
@@ -5044,12 +5190,12 @@ function saveIdeChecklist(cwd, ideSurface) {
5044
5190
  function detectIdeRulePresent(cwd, ideSurface) {
5045
5191
  const rel = IDE_PATHS[ideSurface];
5046
5192
  if (ideSurface === "cursor") {
5047
- return existsSync19(join19(cwd, rel)) || existsSync19(join19(cwd, ".cursor/rules/cursor-agent-kit.mdc"));
5193
+ return existsSync19(join20(cwd, rel)) || existsSync19(join20(cwd, ".cursor/rules/cursor-agent-kit.mdc"));
5048
5194
  }
5049
5195
  if (rel.endsWith("/")) {
5050
- return existsSync19(join19(cwd, rel));
5196
+ return existsSync19(join20(cwd, rel));
5051
5197
  }
5052
- return existsSync19(join19(cwd, rel));
5198
+ return existsSync19(join20(cwd, rel));
5053
5199
  }
5054
5200
  var VISUAL_QA_MARKER = "## Visual QA Tier";
5055
5201
  var VISUAL_QA_BLOCKS = {
@@ -5077,11 +5223,11 @@ This project uses the **Mature** visual QA tier.
5077
5223
  };
5078
5224
  function writeVisualQaTier(cwd, tier) {
5079
5225
  const path = "TESTING.md";
5080
- const fullPath = join19(cwd, path);
5226
+ const fullPath = join20(cwd, path);
5081
5227
  if (!existsSync19(fullPath)) {
5082
5228
  return { updated: false, path, reason: "TESTING.md not found in project root." };
5083
5229
  }
5084
- const current = readFileSync16(fullPath, "utf8");
5230
+ const current = readFileSync18(fullPath, "utf8");
5085
5231
  if (current.includes(VISUAL_QA_MARKER)) {
5086
5232
  return {
5087
5233
  updated: false,
@@ -5257,8 +5403,8 @@ function extractSetupFormFromWizardForm(form) {
5257
5403
  }
5258
5404
 
5259
5405
  // src/studio/wizard/drafts.ts
5260
- import { existsSync as existsSync20, readFileSync as readFileSync17 } from "fs";
5261
- import { join as join20 } from "path";
5406
+ import { existsSync as existsSync20, readFileSync as readFileSync19 } from "fs";
5407
+ import { join as join21 } from "path";
5262
5408
  var DESIGN_DRAFT_JSON = ".agent-kit/onboarding/design-draft.json";
5263
5409
  var MESSAGING_DRAFT_JSON = ".agent-kit/onboarding/messaging-draft.json";
5264
5410
  function loadDesignDraft(cwd) {
@@ -5303,11 +5449,11 @@ function previewMessagingMarkdown(draft) {
5303
5449
  `;
5304
5450
  }
5305
5451
  function appendSectionToDoc(cwd, doc, sectionMarkdown) {
5306
- const fullPath = join20(cwd, doc);
5452
+ const fullPath = join21(cwd, doc);
5307
5453
  if (!existsSync20(fullPath)) {
5308
5454
  return { target: doc, action: "missing" };
5309
5455
  }
5310
- const current = readFileSync17(fullPath, "utf8");
5456
+ const current = readFileSync19(fullPath, "utf8");
5311
5457
  if (current.includes("(wizard draft)")) {
5312
5458
  return { target: doc, action: "conflict", conflictPath: `.agent-kit/conflicts/wizard-${doc}` };
5313
5459
  }
@@ -5346,8 +5492,8 @@ function applyDrafts(cwd) {
5346
5492
  }
5347
5493
 
5348
5494
  // src/studio/office/render.ts
5349
- import { readFileSync as readFileSync18 } from "fs";
5350
- import { join as join21 } from "path";
5495
+ import { readFileSync as readFileSync20 } from "fs";
5496
+ import { join as join22 } from "path";
5351
5497
 
5352
5498
  // src/studio/office/map.ts
5353
5499
  var MAP_WIDTH = 28;
@@ -5465,28 +5611,16 @@ function buildOfficeStations(agents) {
5465
5611
  }
5466
5612
 
5467
5613
  // 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
- ];
5614
+ var PRODUCT_CATEGORIES = ["content-app", "saas", "admin", "marketplace", "tool", "ecommerce", "portfolio", "education", "community", "ai-workflow", "other"];
5481
5615
  var TENANT_MODELS = ["single-user", "team", "tenant", "marketplace", "admin", "public-content"];
5482
5616
  function readOfficeAsset(name) {
5483
5617
  const root = findPackageRoot();
5484
- const distPath = join21(root, "dist", "studio", "office", "assets", name);
5485
- const srcPath = join21(root, "src", "studio", "office", "assets", name);
5618
+ const distPath = join22(root, "dist", "studio", "office", "assets", name);
5619
+ const srcPath = join22(root, "src", "studio", "office", "assets", name);
5486
5620
  try {
5487
- return readFileSync18(distPath, "utf8");
5621
+ return readFileSync20(distPath, "utf8");
5488
5622
  } catch {
5489
- return readFileSync18(srcPath, "utf8");
5623
+ return readFileSync20(srcPath, "utf8");
5490
5624
  }
5491
5625
  }
5492
5626
  function buildOfficeBootConfig(cwd, viewModel) {
@@ -5512,24 +5646,22 @@ function renderSetupOfficeHtml(boot) {
5512
5646
  function renderOfficeHtml(boot, mode) {
5513
5647
  const css = readOfficeAsset("office.css");
5514
5648
  const js = readOfficeAsset("office.js");
5515
- const bootJson = JSON.stringify(
5516
- {
5517
- ...boot ?? {
5518
- mapWidth: MAP_WIDTH,
5519
- mapHeight: MAP_HEIGHT,
5520
- tileSize: TILE_SIZE,
5521
- scale: CANVAS_SCALE,
5522
- stations: [],
5523
- agents: [],
5524
- categories: PRODUCT_CATEGORIES,
5525
- tenantModels: TENANT_MODELS,
5526
- ideSurfaces: [],
5527
- hasSupabase: false,
5528
- stackSignals: []
5529
- },
5530
- mode
5531
- }
5532
- ).replace(/</g, "\\u003c");
5649
+ const bootJson = JSON.stringify({
5650
+ ...boot ?? {
5651
+ mapWidth: MAP_WIDTH,
5652
+ mapHeight: MAP_HEIGHT,
5653
+ tileSize: TILE_SIZE,
5654
+ scale: CANVAS_SCALE,
5655
+ stations: [],
5656
+ agents: [],
5657
+ categories: PRODUCT_CATEGORIES,
5658
+ tenantModels: TENANT_MODELS,
5659
+ ideSurfaces: [],
5660
+ hasSupabase: false,
5661
+ stackSignals: []
5662
+ },
5663
+ mode
5664
+ }).replace(/</g, "\\u003c");
5533
5665
  const isStudio = mode === "studio";
5534
5666
  const title = isStudio ? "Agent Kit \u2014 Live Studio" : "Agent Kit \u2014 Setup Office";
5535
5667
  const dataView = isStudio ? "studio-v1" : "office-v1";
@@ -5660,30 +5792,18 @@ function allAgentBriefsComplete(form, agentIds) {
5660
5792
  }
5661
5793
 
5662
5794
  // src/studio/wizard/render.ts
5663
- import { readFileSync as readFileSync19 } from "fs";
5664
- import { join as join22 } from "path";
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
- ];
5795
+ import { readFileSync as readFileSync21 } from "fs";
5796
+ import { join as join23 } from "path";
5797
+ var PRODUCT_CATEGORIES2 = ["content-app", "saas", "admin", "marketplace", "tool", "ecommerce", "portfolio", "education", "community", "ai-workflow", "other"];
5678
5798
  var TENANT_MODELS2 = ["single-user", "team", "tenant", "marketplace", "admin", "public-content"];
5679
5799
  function readWizardAsset(name) {
5680
5800
  const root = findPackageRoot();
5681
- const distPath = join22(root, "dist", "studio", "wizard", "assets", name);
5682
- const srcPath = join22(root, "src", "studio", "wizard", "assets", name);
5801
+ const distPath = join23(root, "dist", "studio", "wizard", "assets", name);
5802
+ const srcPath = join23(root, "src", "studio", "wizard", "assets", name);
5683
5803
  try {
5684
- return readFileSync19(distPath, "utf8");
5804
+ return readFileSync21(distPath, "utf8");
5685
5805
  } catch {
5686
- return readFileSync19(srcPath, "utf8");
5806
+ return readFileSync21(srcPath, "utf8");
5687
5807
  }
5688
5808
  }
5689
5809
  function mergeWizardSteps(cwd) {
@@ -5773,12 +5893,12 @@ function renderSetupWizardHtmlWithContext(cwd) {
5773
5893
  }
5774
5894
 
5775
5895
  // src/studio/agentic-level.ts
5776
- import { existsSync as existsSync21, readFileSync as readFileSync20 } from "fs";
5777
- import { join as join23 } from "path";
5896
+ import { existsSync as existsSync21, readFileSync as readFileSync22 } from "fs";
5897
+ import { join as join24 } from "path";
5778
5898
  var CACHE_TTL_MS = 3e4;
5779
5899
  var cache = /* @__PURE__ */ new Map();
5780
5900
  function isMaintainerSourceRepo(cwd) {
5781
- return existsSync21(join23(cwd, "package.json")) && existsSync21(join23(cwd, "src")) && existsSync21(join23(cwd, "templates"));
5901
+ return existsSync21(join24(cwd, "package.json")) && existsSync21(join24(cwd, "src")) && existsSync21(join24(cwd, "templates"));
5782
5902
  }
5783
5903
  function signal(id, level, label, pass, evidence, remediation) {
5784
5904
  return { id, level, label, pass, evidence, remediation };
@@ -5794,28 +5914,23 @@ function detectIdePresent(cwd) {
5794
5914
  return { pass: true, evidence: `${surface} adapter files detected` };
5795
5915
  }
5796
5916
  }
5797
- if (existsSync21(join23(cwd, ".cursor/rules/cursor-agent-kit.mdc"))) {
5917
+ if (existsSync21(join24(cwd, ".cursor/rules/cursor-agent-kit.mdc"))) {
5798
5918
  return { pass: true, evidence: "Cursor council rules from init" };
5799
5919
  }
5800
5920
  return { pass: false, evidence: "No IDE adapter rules or subagents detected" };
5801
5921
  }
5802
5922
  function detectTierBSubagents(cwd) {
5803
- const paths = [
5804
- ".cursor/agents/planner.md",
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)));
5923
+ const paths = [".cursor/agents/planner.md", ".codex/agents/planner.toml", ".claude/agents/planner.md", ".github/copilot-instructions.md"];
5924
+ const found = paths.filter((rel) => existsSync21(join24(cwd, rel)));
5810
5925
  if (found.length > 0) {
5811
5926
  return { pass: true, evidence: `Specialist surface: ${found[0]}` };
5812
5927
  }
5813
5928
  return { pass: false, evidence: "No council subagents or Copilot instructions installed" };
5814
5929
  }
5815
5930
  function readDocSnippet(cwd, name, needles) {
5816
- const path = join23(cwd, name);
5931
+ const path = join24(cwd, name);
5817
5932
  if (!existsSync21(path)) return false;
5818
- const lower = readFileSync20(path, "utf8").toLowerCase();
5933
+ const lower = readFileSync22(path, "utf8").toLowerCase();
5819
5934
  return needles.every((needle) => lower.includes(needle.toLowerCase()));
5820
5935
  }
5821
5936
  function adapterTargetForIde(ide) {
@@ -5843,8 +5958,8 @@ function buildSignals(cwd, maintainerProfile) {
5843
5958
  "l4-agents-md",
5844
5959
  4,
5845
5960
  "Council contract (AGENTS.md)",
5846
- existsSync21(join23(cwd, "AGENTS.md")),
5847
- existsSync21(join23(cwd, "AGENTS.md")) ? "AGENTS.md installed" : "AGENTS.md missing",
5961
+ existsSync21(join24(cwd, "AGENTS.md")),
5962
+ existsSync21(join24(cwd, "AGENTS.md")) ? "AGENTS.md installed" : "AGENTS.md missing",
5848
5963
  "Run agent-kit init --stack next-supabase"
5849
5964
  )
5850
5965
  );
@@ -5853,8 +5968,8 @@ function buildSignals(cwd, maintainerProfile) {
5853
5968
  "l4-adapters-doc",
5854
5969
  4,
5855
5970
  "Assistant activation doc",
5856
- existsSync21(join23(cwd, "ASSISTANT_ADAPTERS.md")),
5857
- existsSync21(join23(cwd, "ASSISTANT_ADAPTERS.md")) ? "ASSISTANT_ADAPTERS.md installed" : "ASSISTANT_ADAPTERS.md missing",
5971
+ existsSync21(join24(cwd, "ASSISTANT_ADAPTERS.md")),
5972
+ existsSync21(join24(cwd, "ASSISTANT_ADAPTERS.md")) ? "ASSISTANT_ADAPTERS.md installed" : "ASSISTANT_ADAPTERS.md missing",
5858
5973
  "Run agent-kit init or agent-kit update"
5859
5974
  )
5860
5975
  );
@@ -5863,8 +5978,8 @@ function buildSignals(cwd, maintainerProfile) {
5863
5978
  "l4-roster",
5864
5979
  4,
5865
5980
  "Machine-readable council roster",
5866
- existsSync21(join23(cwd, ".agent-kit/agent-roster.json")),
5867
- existsSync21(join23(cwd, ".agent-kit/agent-roster.json")) ? ".agent-kit/agent-roster.json present" : "Roster missing",
5981
+ existsSync21(join24(cwd, ".agent-kit/agent-roster.json")),
5982
+ existsSync21(join24(cwd, ".agent-kit/agent-roster.json")) ? ".agent-kit/agent-roster.json present" : "Roster missing",
5868
5983
  "Run agent-kit init or agent-kit update"
5869
5984
  )
5870
5985
  );
@@ -5880,16 +5995,9 @@ function buildSignals(cwd, maintainerProfile) {
5880
5995
  );
5881
5996
  const tierB = detectTierBSubagents(cwd);
5882
5997
  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
- )
5998
+ signal("l5-subagents", 5, "Tier-B specialist activation", tierB.pass, tierB.evidence, "Run agent-kit init --activate cursor|codex|claude|copilot")
5891
5999
  );
5892
- const loopCoding = existsSync21(join23(cwd, "LOOP_CODING.md"));
6000
+ const loopCoding = existsSync21(join24(cwd, "LOOP_CODING.md"));
5893
6001
  signals.push(
5894
6002
  signal(
5895
6003
  "l6-loop-coding",
@@ -5920,12 +6028,12 @@ function buildSignals(cwd, maintainerProfile) {
5920
6028
  )
5921
6029
  );
5922
6030
  if (maintainerProfile) {
5923
- const pkgPath = join23(cwd, "package.json");
6031
+ const pkgPath = join24(cwd, "package.json");
5924
6032
  let releaseCheck = false;
5925
6033
  if (existsSync21(pkgPath)) {
5926
6034
  try {
5927
- const pkg = JSON.parse(readFileSync20(pkgPath, "utf8"));
5928
- releaseCheck = Boolean(pkg.scripts?.["release:check"]) && existsSync21(join23(cwd, "scripts/release-check.mjs"));
6035
+ const pkg = JSON.parse(readFileSync22(pkgPath, "utf8"));
6036
+ releaseCheck = Boolean(pkg.scripts?.["release:check"]) && existsSync21(join24(cwd, "scripts/release-check.mjs"));
5929
6037
  } catch {
5930
6038
  releaseCheck = false;
5931
6039
  }
@@ -5940,7 +6048,7 @@ function buildSignals(cwd, maintainerProfile) {
5940
6048
  "Use npm run release:check before merge; see MAINTAINER_RELEASE.md"
5941
6049
  )
5942
6050
  );
5943
- const maintainerDocs = existsSync21(join23(cwd, "MAINTAINER_RELEASE.md")) || readDocSnippet(cwd, "DOCS.md", ["maintainer dogfood", "dogfood:init"]);
6051
+ const maintainerDocs = existsSync21(join24(cwd, "MAINTAINER_RELEASE.md")) || readDocSnippet(cwd, "DOCS.md", ["maintainer dogfood", "dogfood:init"]);
5944
6052
  signals.push(
5945
6053
  signal(
5946
6054
  "l6-maintainer-docs",
@@ -5966,17 +6074,10 @@ function buildSignals(cwd, maintainerProfile) {
5966
6074
  adapterEvidence = `cursor (detected): ${report2.summary.pass} pass / ${report2.summary.fail} fail`;
5967
6075
  }
5968
6076
  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
- )
6077
+ signal("l6-adapter-validate", 6, "Adapter validate for active IDE", adapterPass, adapterEvidence, "Run agent-kit adapter validate cursor|codex|all")
5977
6078
  );
5978
- const ciWorkflow = existsSync21(join23(cwd, ".github/workflows/agent-kit-audit.yml"));
5979
- const testingEval = existsSync21(join23(cwd, "TESTING.md")) && readDocSnippet(cwd, "TESTING.md", ["agent-kit audit", "eval"]);
6079
+ const ciWorkflow = existsSync21(join24(cwd, ".github/workflows/agent-kit-audit.yml"));
6080
+ const testingEval = existsSync21(join24(cwd, "TESTING.md")) && readDocSnippet(cwd, "TESTING.md", ["agent-kit audit", "eval"]);
5980
6081
  const evalLoop = ciWorkflow || testingEval;
5981
6082
  signals.push(
5982
6083
  signal(
@@ -6108,16 +6209,11 @@ function buildStatePayload(cwd, options = {}) {
6108
6209
  const designDraft = loadDesignDraft(cwd);
6109
6210
  const messagingDraft = loadMessagingDraft(cwd);
6110
6211
  const draft = loadWizardDraft(cwd);
6111
- const agenticLevel = computeAgenticLevel(
6112
- cwd,
6113
- options.forceAgenticRefresh ? { forceRefresh: true } : {}
6114
- );
6212
+ const agenticLevel = computeAgenticLevel(cwd, options.forceAgenticRefresh ? { forceRefresh: true } : {});
6115
6213
  return {
6116
6214
  projectName: viewModel.projectName,
6117
6215
  form: buildWizardFormState(cwd),
6118
- hasExistingContext: Boolean(
6119
- viewModel.form.productSummary.trim() || viewModel.form.primaryAudience.trim() || viewModel.form.valueProposition.trim()
6120
- ),
6216
+ hasExistingContext: Boolean(viewModel.form.productSummary.trim() || viewModel.form.primaryAudience.trim() || viewModel.form.valueProposition.trim()),
6121
6217
  openQuestions: viewModel.openQuestions,
6122
6218
  hasSupabase: viewModel.hasSupabase,
6123
6219
  onboarding,
@@ -6380,7 +6476,7 @@ async function startSetupServer(options) {
6380
6476
  // src/studio/studio-server.ts
6381
6477
  import { watch } from "fs";
6382
6478
  import { createServer as createServer2 } from "http";
6383
- import { join as join24 } from "path";
6479
+ import { join as join25 } from "path";
6384
6480
  var DEFAULT_PORT2 = 9331;
6385
6481
  var DEFAULT_HOST2 = "127.0.0.1";
6386
6482
  var sseClients = /* @__PURE__ */ new Set();
@@ -6422,7 +6518,7 @@ function stopWatcher() {
6422
6518
  }
6423
6519
  }
6424
6520
  function watchSessionEvents(cwd, sessionId) {
6425
- const eventsPath2 = join24(cwd, COUNCIL_SESSIONS_DIR, sessionId, "events.jsonl");
6521
+ const eventsPath2 = join25(cwd, COUNCIL_SESSIONS_DIR, sessionId, "events.jsonl");
6426
6522
  if (watchedEventsPath === eventsPath2 && activeWatcher) return;
6427
6523
  stopWatcher();
6428
6524
  watchedEventsPath = eventsPath2;
@@ -6444,7 +6540,7 @@ function safeSessionId(raw) {
6444
6540
  if (!/^[a-z0-9-]+$/i.test(raw)) return null;
6445
6541
  return raw;
6446
6542
  }
6447
- async function handleRequest2(cwd, request, response) {
6543
+ function handleRequest2(cwd, request, response) {
6448
6544
  const url = new URL(request.url ?? "/", "http://127.0.0.1");
6449
6545
  if (request.method === "GET" && (url.pathname === "/" || url.pathname === "/office")) {
6450
6546
  sendHtml2(response, renderLiveStudioHtmlWithContext(cwd));
@@ -6539,9 +6635,11 @@ async function startStudioServer(options) {
6539
6635
  const requestedPort = options.port ?? DEFAULT_PORT2;
6540
6636
  ensureStudioDirs(options.cwd);
6541
6637
  const server = createServer2((request, response) => {
6542
- handleRequest2(options.cwd, request, response).catch((error) => {
6638
+ try {
6639
+ handleRequest2(options.cwd, request, response);
6640
+ } catch (error) {
6543
6641
  sendJson2(response, 500, { error: error instanceof Error ? error.message : String(error) });
6544
- });
6642
+ }
6545
6643
  });
6546
6644
  let port = requestedPort;
6547
6645
  let portFallback = false;
@@ -6578,33 +6676,33 @@ async function startStudioServer(options) {
6578
6676
  }
6579
6677
 
6580
6678
  // src/studio/session-checkpoint.ts
6581
- import { existsSync as existsSync22, readFileSync as readFileSync21 } from "fs";
6582
- import { extname, join as join25 } from "path";
6679
+ import { existsSync as existsSync22, readFileSync as readFileSync23 } from "fs";
6680
+ import { extname, join as join26 } from "path";
6583
6681
  function parseCheckpointMarkdown(content) {
6584
6682
  const payload = { notes: [], decisions: [], handoffs: [], outputs: [] };
6585
6683
  const sections = content.split(/^## /m).slice(1);
6586
6684
  for (const section of sections) {
6587
6685
  const [headingLine, ...bodyLines] = section.split("\n");
6588
6686
  if (!headingLine) continue;
6589
- const heading = headingLine.trim().toLowerCase();
6590
- const lines = bodyLines.map((line) => line.trim()).filter(Boolean);
6591
- if (heading === "notes") {
6592
- for (const line of lines) {
6593
- const match = line.match(/^-?\s*@(\S+):\s*(.+)$/);
6687
+ const heading2 = headingLine.trim().toLowerCase();
6688
+ const lines = bodyLines.map((line2) => line2.trim()).filter(Boolean);
6689
+ if (heading2 === "notes") {
6690
+ for (const line2 of lines) {
6691
+ const match = line2.match(/^-?\s*@(\S+):\s*(.+)$/);
6594
6692
  if (match?.[1] && match[2]) payload.notes?.push({ agent: match[1], text: match[2] });
6595
6693
  }
6596
6694
  }
6597
- if (heading === "decisions") {
6598
- for (const line of lines) {
6599
- const match = line.match(/^-?\s*@(\S+):\s*(.+?)(?:\s+\(risk:\s*(.+)\))?$/i);
6695
+ if (heading2 === "decisions") {
6696
+ for (const line2 of lines) {
6697
+ const match = line2.match(/^-?\s*@(\S+):\s*(.+?)(?:\s+\(risk:\s*(.+)\))?$/i);
6600
6698
  if (match?.[1] && match[2]) {
6601
6699
  payload.decisions?.push({ agent: match[1], text: match[2], ...match[3] ? { risk: match[3] } : {} });
6602
6700
  }
6603
6701
  }
6604
6702
  }
6605
- if (heading === "handoffs") {
6606
- for (const line of lines) {
6607
- const match = line.match(/^-?\s*(\S+)\s*->\s*(\S+):\s*(.+?)\s+\|\s*risk:\s*(.+)$/i);
6703
+ if (heading2 === "handoffs") {
6704
+ for (const line2 of lines) {
6705
+ const match = line2.match(/^-?\s*(\S+)\s*->\s*(\S+):\s*(.+?)\s+\|\s*risk:\s*(.+)$/i);
6608
6706
  if (match?.[1] && match?.[2] && match?.[3] && match?.[4]) {
6609
6707
  payload.handoffs?.push({
6610
6708
  fromAgentId: match[1],
@@ -6615,9 +6713,9 @@ function parseCheckpointMarkdown(content) {
6615
6713
  }
6616
6714
  }
6617
6715
  }
6618
- if (heading === "outputs") {
6619
- for (const line of lines) {
6620
- const match = line.match(/^-?\s*(.+?):\s*(missing|partial|complete|not-applicable)(?:\s+\|\s*(.+))?$/i);
6716
+ if (heading2 === "outputs") {
6717
+ for (const line2 of lines) {
6718
+ const match = line2.match(/^-?\s*(.+?):\s*(missing|partial|complete|not-applicable)(?:\s+\|\s*(.+))?$/i);
6621
6719
  if (match?.[1] && match?.[2]) {
6622
6720
  payload.outputs?.push({
6623
6721
  name: match[1].trim(),
@@ -6627,15 +6725,15 @@ function parseCheckpointMarkdown(content) {
6627
6725
  }
6628
6726
  }
6629
6727
  }
6630
- if (heading === "options") {
6631
- if (lines.some((line) => /render:\s*true/i.test(line))) payload.render = true;
6632
- if (lines.some((line) => /close:\s*true/i.test(line))) payload.close = true;
6728
+ if (heading2 === "options") {
6729
+ if (lines.some((line2) => /render:\s*true/i.test(line2))) payload.render = true;
6730
+ if (lines.some((line2) => /close:\s*true/i.test(line2))) payload.close = true;
6633
6731
  }
6634
6732
  }
6635
6733
  return payload;
6636
6734
  }
6637
6735
  function parseCheckpointFile(filePath) {
6638
- const content = readFileSync21(filePath, "utf8");
6736
+ const content = readFileSync23(filePath, "utf8");
6639
6737
  const ext = extname(filePath).toLowerCase();
6640
6738
  if (ext === ".json") {
6641
6739
  const parsed = JSON.parse(content);
@@ -6711,11 +6809,55 @@ function applySessionCheckpoint(cwd, payload) {
6711
6809
  };
6712
6810
  }
6713
6811
  function checkpointSessionFromFile(cwd, filePath) {
6714
- const absolute = join25(cwd, filePath);
6812
+ const absolute = join26(cwd, filePath);
6715
6813
  if (!existsSync22(absolute)) throw new Error(`Checkpoint file not found: ${filePath}`);
6716
6814
  return applySessionCheckpoint(cwd, parseCheckpointFile(absolute));
6717
6815
  }
6718
6816
 
6817
+ // src/cli/output.ts
6818
+ import pc from "picocolors";
6819
+ var colorEnabled = process.env.NO_COLOR === void 0 && process.stdout.isTTY === true;
6820
+ function paint(painter, text) {
6821
+ return colorEnabled ? painter(text) : text;
6822
+ }
6823
+ var style = {
6824
+ heading: (text) => paint(pc.cyan, text),
6825
+ pass: (text) => paint(pc.green, text),
6826
+ warn: (text) => paint(pc.yellow, text),
6827
+ fail: (text) => paint(pc.red, text),
6828
+ dim: (text) => paint(pc.dim, text),
6829
+ bold: (text) => paint(pc.bold, text)
6830
+ };
6831
+ function levelLabel(level) {
6832
+ const label = level.toUpperCase().padEnd(4);
6833
+ if (level === "pass") return style.pass(label);
6834
+ if (level === "warn") return style.warn(label);
6835
+ return style.fail(label);
6836
+ }
6837
+ function printJson(value) {
6838
+ console.log(JSON.stringify(value, null, 2));
6839
+ }
6840
+ function heading(text) {
6841
+ console.log(style.heading(text));
6842
+ }
6843
+ function line(text = "") {
6844
+ console.log(text);
6845
+ }
6846
+ function detail(text) {
6847
+ console.log(style.dim(` ${text}`));
6848
+ }
6849
+ function listItem(text) {
6850
+ console.log(`- ${text}`);
6851
+ }
6852
+ function fileGroup(label, files) {
6853
+ if (files.length === 0) return;
6854
+ console.log(`${style.bold(label)} (${files.length})`);
6855
+ for (const file of files) console.log(` ${file}`);
6856
+ }
6857
+ function fail(message) {
6858
+ console.error(style.fail(`error: ${message}`));
6859
+ }
6860
+
6719
6861
  // src/cli/index.ts
6720
6862
  var program = new Command();
6721
6863
  var requiredOutputStatuses = ["missing", "partial", "complete", "not-applicable"];
@@ -6723,6 +6865,37 @@ function isRequiredOutputStatus(value) {
6723
6865
  return requiredOutputStatuses.includes(value);
6724
6866
  }
6725
6867
  program.name("agent-kit").description("Next.js + Supabase agent, skill, docs, design, and research kit.").version(PACKAGE_VERSION);
6868
+ async function runGuidedContextPrompts(cwd) {
6869
+ if (!process.stdin.isTTY || !process.stdout.isTTY) return;
6870
+ const clack = await import("@clack/prompts");
6871
+ clack.intro("agent-kit guided setup");
6872
+ const questions = [
6873
+ { key: "productSummary", message: "What does this product do, in one concrete paragraph?" },
6874
+ { key: "primaryAudience", message: "Who is the primary user or buyer?" },
6875
+ { key: "authModel", message: "What authentication model should agents preserve?" },
6876
+ { key: "tenantModel", message: "Is this single-user, team, tenant, marketplace, admin, or public content?" }
6877
+ ];
6878
+ const answers = {};
6879
+ for (const question of questions) {
6880
+ const answer = await clack.text({ message: question.message, placeholder: "Leave empty to answer later" });
6881
+ if (clack.isCancel(answer)) {
6882
+ clack.cancel("Guided setup cancelled. Context files were still created; answer later with agent-kit context ask.");
6883
+ return;
6884
+ }
6885
+ if (typeof answer === "string" && answer.trim()) answers[question.key] = answer.trim();
6886
+ }
6887
+ if (Object.keys(answers).length > 0) {
6888
+ const contextPath = join27(cwd, ".agent-kit", "project-context.json");
6889
+ if (existsSync23(contextPath)) {
6890
+ const context2 = JSON.parse(readFileSync24(contextPath, "utf8"));
6891
+ Object.assign(context2, answers);
6892
+ writeFileSync2(contextPath, `${JSON.stringify(context2, null, 2)}
6893
+ `);
6894
+ renderProjectContext(cwd);
6895
+ }
6896
+ }
6897
+ clack.outro("Project context saved. Run agent-kit audit next.");
6898
+ }
6726
6899
  async function runSetupServer(options) {
6727
6900
  const handle = await startSetupServer({
6728
6901
  cwd: process.cwd(),
@@ -6730,35 +6903,73 @@ async function runSetupServer(options) {
6730
6903
  host: options.host
6731
6904
  });
6732
6905
  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
- );
6906
+ 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
6907
  console.warn(`Using fallback port ${handle.port} instead.`);
6737
6908
  }
6738
6909
  console.log(`Agent Kit v${PACKAGE_VERSION} \u2014 ${handle.defaultView} view at ${handle.url}/`);
6739
6910
  console.log(`Pixel office (default): ${handle.url}/ | Form fallback: ${handle.url}/wizard`);
6740
6911
  console.log("Pick Quick, Standard, or Complete on first visit. Press Ctrl+C to stop.");
6741
- if (options.open) openBrowser(`${handle.url}/`);
6912
+ if (options.open) void openBrowser(`${handle.url}/`);
6742
6913
  await new Promise((resolve3) => {
6743
6914
  const shutdown = () => {
6744
- handle.close().finally(resolve3);
6915
+ void handle.close().finally(resolve3);
6745
6916
  };
6746
6917
  process.once("SIGINT", shutdown);
6747
6918
  process.once("SIGTERM", shutdown);
6748
6919
  });
6749
6920
  }
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", "Deprecated alias for default project context scan (always runs on init).").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) => {
6921
+ 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
6922
  const cwd = process.cwd();
6923
+ if (options.dryRun) {
6924
+ const preview = diffProject(cwd, options.stack);
6925
+ if (options.json) {
6926
+ printJson({ dryRun: true, preview: preview.preview, missing: preview.missing, changed: preview.changed, unchanged: preview.unchanged });
6927
+ return;
6928
+ }
6929
+ heading("agent-kit init --dry-run");
6930
+ fileGroup("Would create", preview.preview.wouldCreate);
6931
+ fileGroup("Would write conflicts for", preview.preview.wouldWriteConflicts);
6932
+ fileGroup("Already up to date", preview.unchanged);
6933
+ line();
6934
+ line(`Run ${style.bold("agent-kit init")} to apply.`);
6935
+ return;
6936
+ }
6752
6937
  const result = initProject({
6753
6938
  cwd,
6754
6939
  stack: options.stack,
6755
6940
  force: Boolean(options.force),
6756
6941
  ...options.activate ? { activate: options.activate } : {}
6757
6942
  });
6943
+ const context2 = options.guided ? initProjectContext(cwd) : null;
6758
6944
  if (options.json) {
6759
- console.log(JSON.stringify(result, null, 2));
6945
+ printJson(context2 ? { install: result, context: context2 } : result);
6760
6946
  } else {
6761
- console.log(formatInitSummary(result));
6947
+ heading(`agent-kit ${PACKAGE_VERSION} installed (stack: ${options.stack})`);
6948
+ fileGroup("Created", result.copied);
6949
+ fileGroup("Unchanged", result.unchanged);
6950
+ fileGroup("Overwritten", result.overwritten);
6951
+ if (result.conflicts.length > 0) {
6952
+ fileGroup("Conflicts (local file kept, template saved for review)", result.conflicts);
6953
+ detail("Review .agent-kit/conflicts/ before adopting template changes.");
6954
+ }
6955
+ line();
6956
+ line(`Manifest: ${result.manifestPath}`);
6957
+ }
6958
+ if (options.guided && context2) {
6959
+ if (!options.json) {
6960
+ line();
6961
+ heading("Project context");
6962
+ line(`Context: ${context2.contextPath}`);
6963
+ if (context2.openQuestions.length > 0) {
6964
+ line("Open questions:");
6965
+ for (const question of context2.openQuestions) listItem(question);
6966
+ }
6967
+ }
6968
+ await runGuidedContextPrompts(cwd);
6969
+ }
6970
+ if (!options.json) {
6971
+ line();
6972
+ line(`Next: run ${style.bold("agent-kit audit")} to check readiness.`);
6762
6973
  }
6763
6974
  const shouldPrompt = !options.noSetup && !options.json;
6764
6975
  const startWizard = Boolean(options.setup) || shouldPrompt && await promptStartSetup(true);
@@ -6771,26 +6982,26 @@ program.command("audit").description("Audit an existing project for agent-kit co
6771
6982
  let minimumReadiness;
6772
6983
  if (options.minReadiness) {
6773
6984
  if (!isAuditReadinessLevel(options.minReadiness)) {
6774
- console.error(`Invalid --min-readiness value "${options.minReadiness}". Expected one of: ${READINESS_ORDER.join(", ")}.`);
6985
+ fail(`Invalid --min-readiness value "${options.minReadiness}". Expected one of: ${READINESS_ORDER.join(", ")}.`);
6775
6986
  process.exitCode = 1;
6776
6987
  return;
6777
6988
  }
6778
6989
  minimumReadiness = options.minReadiness;
6779
6990
  }
6780
6991
  if (options.json) {
6781
- console.log(JSON.stringify(report2, null, 2));
6992
+ printJson(report2);
6782
6993
  } else {
6783
- console.log(`READINESS ${report2.readiness.level}: ${report2.readiness.summary}`);
6784
- console.log(`SUMMARY pass=${report2.summary.pass} warn=${report2.summary.warn} fail=${report2.summary.fail}`);
6994
+ const readinessStyle = report2.summary.fail > 0 ? style.fail : report2.summary.warn > 0 ? style.warn : style.pass;
6995
+ line(`${style.bold("READINESS")} ${readinessStyle(report2.readiness.level)}: ${report2.readiness.summary}`);
6996
+ line(`${style.bold("SUMMARY")} pass=${report2.summary.pass} warn=${report2.summary.warn} fail=${report2.summary.fail}`);
6785
6997
  if (report2.readiness.nextActions.length > 0) {
6786
- console.log("NEXT ACTIONS");
6787
- for (const action of report2.readiness.nextActions) console.log(`- ${action}`);
6998
+ line(style.bold("NEXT ACTIONS"));
6999
+ for (const action of report2.readiness.nextActions) listItem(action);
6788
7000
  }
6789
- console.log("");
7001
+ line();
6790
7002
  for (const finding of report2.findings) {
6791
- const prefix = finding.level.toUpperCase().padEnd(4);
6792
- console.log(`${prefix} ${finding.area}: ${finding.message}`);
6793
- if (finding.remediation) console.log(` remediation: ${finding.remediation}`);
7003
+ line(`${levelLabel(finding.level)} ${finding.area}: ${finding.message}`);
7004
+ if (finding.remediation) detail(`remediation: ${finding.remediation}`);
6794
7005
  }
6795
7006
  }
6796
7007
  if (report2.summary.fail > 0) {
@@ -6801,32 +7012,88 @@ program.command("audit").description("Audit an existing project for agent-kit co
6801
7012
  process.exitCode = 1;
6802
7013
  }
6803
7014
  });
6804
- program.command("diff").description("Compare project docs against bundled templates.").action(() => {
6805
- console.log(JSON.stringify(diffProject(process.cwd()), null, 2));
7015
+ program.command("diff").description("Compare project docs against bundled templates.").option("--json", "Print machine-readable JSON output.").action((options) => {
7016
+ const result = diffProject(process.cwd());
7017
+ if (options.json) {
7018
+ printJson(result);
7019
+ return;
7020
+ }
7021
+ heading("agent-kit diff");
7022
+ fileGroup("Missing (update would create)", result.missing);
7023
+ fileGroup("Changed locally (update would write conflicts)", result.changed);
7024
+ fileGroup("Unchanged", result.unchanged);
7025
+ line();
7026
+ line(`Agent roster: ${result.agentRoster}`);
7027
+ line(`Model routing: ${result.modelRouting}`);
7028
+ if (result.libraryFolders.missing.length > 0) {
7029
+ line(`Missing library folders: ${result.libraryFolders.missing.join(", ")}`);
7030
+ }
7031
+ line();
7032
+ line(`Next: run ${style.bold("agent-kit update --dry-run")} to preview the exact per-file plan.`);
6806
7033
  });
6807
- program.command("update").description("Update installed templates, preserving local conflicts by default.").option("--force", "Overwrite local docs.").action((options) => {
6808
- const result = initProject({ cwd: process.cwd(), force: Boolean(options.force) });
6809
- console.log(JSON.stringify(result, null, 2));
7034
+ 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) => {
7035
+ const result = updateProject({ cwd: process.cwd(), force: Boolean(options.force), dryRun: Boolean(options.dryRun) });
7036
+ if (options.json) {
7037
+ printJson(result);
7038
+ return;
7039
+ }
7040
+ heading(result.dryRun ? "agent-kit update --dry-run" : "agent-kit update");
7041
+ const byAction = (action) => result.files.filter((file) => file.action === action).map((file) => file.target);
7042
+ fileGroup(result.dryRun ? "Would create" : "Created", byAction("created"));
7043
+ fileGroup(result.dryRun ? "Would update (pristine)" : "Updated (pristine)", byAction("updated"));
7044
+ fileGroup("Kept local customizations", byAction("kept-local"));
7045
+ fileGroup(result.dryRun ? "Would overwrite" : "Overwritten", byAction("overwritten"));
7046
+ const conflicts = result.files.filter((file) => file.action === "conflict");
7047
+ if (conflicts.length > 0) {
7048
+ line(`${style.bold("Conflicts")} (${conflicts.length})`);
7049
+ for (const file of conflicts) {
7050
+ line(` ${file.target}${file.conflictPath ? ` -> ${file.conflictPath}` : ""}`);
7051
+ }
7052
+ detail("Local files were kept. Review the conflict copies before adopting template changes.");
7053
+ }
7054
+ detail(`unchanged: ${result.summary.unchanged} file(s) already match the current templates`);
7055
+ if (!result.dryRun) {
7056
+ line();
7057
+ line(`Library folders refreshed: ${result.libraryFoldersRefreshed.length}`);
7058
+ line(`Manifest: ${result.manifestPath}`);
7059
+ }
6810
7060
  });
6811
7061
  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
- console.log(addSkill(process.cwd(), name, { force: Boolean(options.force) }));
7062
+ 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) => {
7063
+ const result = addSkill(process.cwd(), name, { force: Boolean(options.force), dryRun: Boolean(options.dryRun) });
7064
+ if (options.json) {
7065
+ printJson(result);
7066
+ return;
7067
+ }
7068
+ line(`${result.action}: ${result.target}${result.conflictPath ? ` -> ${result.conflictPath}` : ""}`);
7069
+ if (options.dryRun) detail("dry run: no files were written");
6814
7070
  });
6815
- program.command("doctor").description("Validate local CLI runtime prerequisites.").action(() => {
7071
+ program.command("doctor").description("Validate local CLI runtime prerequisites.").option("--json", "Print machine-readable JSON output.").action((options) => {
6816
7072
  const cwd = process.cwd();
6817
- console.log("agent-kit doctor");
6818
- console.log(`node: ${process.version}`);
6819
- console.log(`available skills: ${listSkills().length}`);
6820
- if (onboardingStateExists(cwd)) {
6821
- const progress = getSetupProgress(cwd);
6822
- console.log(`setup progress: ${progress.percent}% (depth: ${progress.depth})`);
6823
- if (!progress.quickComplete) {
6824
- console.log("tip: run agent-kit setup --open to finish project context onboarding.");
7073
+ const report2 = {
7074
+ version: PACKAGE_VERSION,
7075
+ node: process.version,
7076
+ availableSkills: listSkills().length,
7077
+ setupProgress: onboardingStateExists(cwd) ? getSetupProgress(cwd) : null,
7078
+ status: "ok"
7079
+ };
7080
+ if (options.json) {
7081
+ printJson(report2);
7082
+ return;
7083
+ }
7084
+ heading("agent-kit doctor");
7085
+ line(`version: ${report2.version}`);
7086
+ line(`node: ${report2.node}`);
7087
+ line(`available skills: ${report2.availableSkills}`);
7088
+ if (report2.setupProgress) {
7089
+ line(`setup progress: ${report2.setupProgress.percent}% (depth: ${report2.setupProgress.depth})`);
7090
+ if (!report2.setupProgress.quickComplete) {
7091
+ detail("run agent-kit setup --open to finish project context onboarding.");
6825
7092
  }
6826
7093
  } else {
6827
- console.log("tip: run agent-kit init then agent-kit setup to onboard this project.");
7094
+ detail("run agent-kit init then agent-kit setup to onboard this project.");
6828
7095
  }
6829
- console.log("status: ok");
7096
+ line(`status: ${style.pass(report2.status)}`);
6830
7097
  });
6831
7098
  function printValidationReport(report2, json) {
6832
7099
  if (json) {
@@ -6859,8 +7126,19 @@ packageCommand.command("validate").description("Validate package assets, runtime
6859
7126
  printValidationReport(report2, Boolean(options.json));
6860
7127
  if (report2.summary.fail > 0) process.exitCode = 1;
6861
7128
  });
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
- console.log(JSON.stringify(initProjectContext(process.cwd()), null, 2));
7129
+ 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) => {
7130
+ const result = initProjectContext(process.cwd());
7131
+ if (options.json) {
7132
+ printJson(result);
7133
+ return;
7134
+ }
7135
+ heading("agent-kit onboard");
7136
+ line(`Context: ${result.contextPath}`);
7137
+ line(`Markdown: ${result.markdownPath}`);
7138
+ if (result.openQuestions.length > 0) {
7139
+ line("Open questions:");
7140
+ for (const question of result.openQuestions) listItem(question);
7141
+ }
6864
7142
  });
6865
7143
  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
7144
  const cwd = process.cwd();
@@ -6873,140 +7151,194 @@ program.command("setup").description("Start the local Agent Office setup view fo
6873
7151
  await runSetupServer({ port: options.port, host: options.host, open: Boolean(options.open) });
6874
7152
  });
6875
7153
  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
- console.log(JSON.stringify(initProjectContext(process.cwd()), null, 2));
7154
+ context.command("init").description("Create project context from a local scan.").option("--json", "Print machine-readable JSON output.").action((options) => {
7155
+ const result = initProjectContext(process.cwd());
7156
+ if (options.json) {
7157
+ printJson(result);
7158
+ return;
7159
+ }
7160
+ line(`Context written: ${result.contextPath}`);
7161
+ if (result.openQuestions.length > 0) {
7162
+ line("Open questions:");
7163
+ for (const question of result.openQuestions) listItem(question);
7164
+ }
6878
7165
  });
6879
7166
  context.command("scan").description("Print inferred project context without writing it.").action(() => {
6880
- console.log(JSON.stringify(scanProjectContext(process.cwd()), null, 2));
7167
+ printJson(scanProjectContext(process.cwd()));
6881
7168
  });
6882
7169
  context.command("ask").description("Print unanswered high-value project context questions.").action(() => {
6883
7170
  const result = initProjectContext(process.cwd());
6884
7171
  if (result.openQuestions.length === 0) {
6885
- console.log("No open project-context questions.");
7172
+ line("No open project-context questions.");
6886
7173
  return;
6887
7174
  }
6888
- console.log("Answer these in the web setup wizard with: agent-kit setup --open");
6889
- console.log("Check progress with: agent-kit setup --status");
6890
- for (const question of result.openQuestions) console.log(`- ${question}`);
7175
+ line("Answer these in the web setup wizard with: agent-kit setup --open");
7176
+ detail("Check progress with: agent-kit setup --status");
7177
+ for (const question of result.openQuestions) listItem(question);
6891
7178
  });
6892
- context.command("render").description("Render .agent-kit/project-context.md from project-context.json.").action(() => {
6893
- console.log(JSON.stringify(renderProjectContext(process.cwd()), null, 2));
7179
+ context.command("render").description("Render .agent-kit/project-context.md from project-context.json.").option("--json", "Print machine-readable JSON output.").action((options) => {
7180
+ const result = renderProjectContext(process.cwd());
7181
+ if (options.json) {
7182
+ printJson(result);
7183
+ return;
7184
+ }
7185
+ line(`Rendered: ${result.markdownPath}`);
6894
7186
  });
6895
- context.command("validate").description("Validate .agent-kit/project-context.json.").action(() => {
6896
- console.log(JSON.stringify(validateProjectContext(process.cwd()), null, 2));
7187
+ context.command("validate").description("Validate .agent-kit/project-context.json.").option("--json", "Print machine-readable JSON output.").action((options) => {
7188
+ const result = validateProjectContext(process.cwd());
7189
+ if (options.json) {
7190
+ printJson(result);
7191
+ return;
7192
+ }
7193
+ line(`Valid: ${result.contextPath}`);
7194
+ if (result.openQuestions.length > 0) {
7195
+ line("Open questions:");
7196
+ for (const question of result.openQuestions) listItem(question);
7197
+ }
6897
7198
  });
6898
7199
  context.command("show").description("Print rendered project context markdown.").action(() => {
6899
7200
  console.log(readTextFile(process.cwd(), ".agent-kit/project-context.md") ?? "");
6900
7201
  });
6901
7202
  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) => {
7203
+ 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
7204
  const title = titleParts.join(" ");
6904
- console.log(
6905
- JSON.stringify(
6906
- startSession(process.cwd(), {
6907
- title,
6908
- workflowId: options.workflow,
6909
- ...options.request ? { request: options.request } : {}
6910
- }),
6911
- null,
6912
- 2
6913
- )
6914
- );
7205
+ const result = startSession(process.cwd(), {
7206
+ title,
7207
+ workflowId: options.workflow,
7208
+ ...options.request ? { request: options.request } : {}
7209
+ });
7210
+ if (options.json) {
7211
+ printJson(result);
7212
+ return;
7213
+ }
7214
+ line(`Session started: ${result.sessionId}`);
7215
+ line(`Path: ${result.sessionPath}`);
6915
7216
  });
6916
- session.command("list").description("List local council sessions.").action(() => {
6917
- console.log(JSON.stringify(listSessions(process.cwd()), null, 2));
7217
+ session.command("list").description("List local council sessions.").option("--json", "Print machine-readable JSON output.").action((options) => {
7218
+ const sessions = listSessions(process.cwd());
7219
+ if (options.json) {
7220
+ printJson(sessions);
7221
+ return;
7222
+ }
7223
+ if (sessions.length === 0) {
7224
+ line("No sessions yet. Start one with agent-kit session start <title>.");
7225
+ return;
7226
+ }
7227
+ for (const item of sessions) {
7228
+ line(`${item.sessionId} [${item.status}] ${item.title}`);
7229
+ }
6918
7230
  });
6919
7231
  session.command("active").description("Print the active council session id.").action(() => {
6920
7232
  console.log(getActiveSessionId(process.cwd()));
6921
7233
  });
6922
- session.command("note <text...>").description("Record a visible agent message.").requiredOption("--agent <agent>", "Agent id.").action((textParts, options) => {
6923
- console.log(JSON.stringify(recordNote(process.cwd(), options.agent, textParts.join(" ")), null, 2));
7234
+ 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) => {
7235
+ const result = recordNote(process.cwd(), options.agent, textParts.join(" "));
7236
+ if (options.json) printJson(result);
7237
+ else line(`Recorded note from ${options.agent}.`);
6924
7238
  });
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
- console.log(JSON.stringify(recordDecision(process.cwd(), options.agent, textParts.join(" "), options.risk), null, 2));
7239
+ 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) => {
7240
+ const result = recordDecision(process.cwd(), options.agent, textParts.join(" "), options.risk);
7241
+ if (options.json) printJson(result);
7242
+ else line(`Recorded decision from ${options.agent}.`);
6927
7243
  });
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
- console.log(
6930
- JSON.stringify(
6931
- recordHandoff(process.cwd(), {
6932
- fromAgentId: options.from,
6933
- toAgentId: options.to,
6934
- decision: options.decision,
6935
- risk: options.risk,
6936
- ...options.evidence ? { evidence: options.evidence } : {}
6937
- }),
6938
- null,
6939
- 2
6940
- )
6941
- );
7244
+ 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) => {
7245
+ const result = recordHandoff(process.cwd(), {
7246
+ fromAgentId: options.from,
7247
+ toAgentId: options.to,
7248
+ decision: options.decision,
7249
+ risk: options.risk,
7250
+ ...options.evidence ? { evidence: options.evidence } : {}
7251
+ });
7252
+ if (options.json) printJson(result);
7253
+ else line(`Recorded handoff ${options.from} -> ${options.to}.`);
6942
7254
  });
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
- console.log(
6945
- JSON.stringify(
6946
- recordCorrection(process.cwd(), {
6947
- ...options.agent ? { agentId: options.agent } : {},
6948
- scope: options.scope,
6949
- text: textParts.join(" ")
6950
- }),
6951
- null,
6952
- 2
6953
- )
6954
- );
7255
+ 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) => {
7256
+ const result = recordCorrection(process.cwd(), {
7257
+ ...options.agent ? { agentId: options.agent } : {},
7258
+ scope: options.scope,
7259
+ text: textParts.join(" ")
7260
+ });
7261
+ if (options.json) printJson(result);
7262
+ else line(`Recorded ${options.scope}-scoped correction.`);
6955
7263
  });
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
- console.log(JSON.stringify(recordArtifact(process.cwd(), options.file, options.note), null, 2));
7264
+ 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) => {
7265
+ const result = recordArtifact(process.cwd(), options.file, options.note);
7266
+ if (options.json) printJson(result);
7267
+ else line(`Recorded artifact ${options.file}.`);
6958
7268
  });
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
- console.log(JSON.stringify(recordVerification(process.cwd(), options.command, options.result, options.notes), null, 2));
7269
+ 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) => {
7270
+ const result = recordVerification(process.cwd(), options.command, options.result, options.notes);
7271
+ if (options.json) printJson(result);
7272
+ else line(`Recorded verification (${options.result}): ${options.command}`);
6961
7273
  });
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) => {
7274
+ 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
7275
  if (!isRequiredOutputStatus(options.status)) {
6964
- console.error(`Invalid --status value "${options.status}". Expected one of: ${requiredOutputStatuses.join(", ")}.`);
7276
+ fail(`Invalid --status value "${options.status}". Expected one of: ${requiredOutputStatuses.join(", ")}.`);
6965
7277
  process.exitCode = 1;
6966
7278
  return;
6967
7279
  }
6968
- console.log(JSON.stringify(recordRequiredOutput(process.cwd(), nameParts.join(" "), options.status, options.evidence), null, 2));
7280
+ const result = recordRequiredOutput(process.cwd(), nameParts.join(" "), options.status, options.evidence);
7281
+ if (options.json) printJson(result);
7282
+ else line(`Marked "${nameParts.join(" ")}" as ${options.status}.`);
6969
7283
  });
6970
- session.command("render").description("Render active session Markdown files.").action(() => {
6971
- console.log(JSON.stringify(renderActiveSession(process.cwd()), null, 2));
7284
+ session.command("render").description("Render active session Markdown files.").option("--json", "Print machine-readable JSON output.").action((options) => {
7285
+ const result = renderActiveSession(process.cwd());
7286
+ if (options.json) printJson(result);
7287
+ else line(`Rendered session ${result.sessionId} at ${result.sessionPath}.`);
6972
7288
  });
6973
7289
  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
7290
  console.log(JSON.stringify(checkpointSessionFromFile(process.cwd(), options.file), null, 2));
6975
7291
  });
6976
- session.command("close").description("Close the active session.").option("--status <status>", "planned, in-progress, blocked, or complete.", "complete").action((options) => {
6977
- console.log(JSON.stringify(closeSession(process.cwd(), options.status), null, 2));
7292
+ 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) => {
7293
+ const result = closeSession(process.cwd(), options.status);
7294
+ if (options.json) printJson(result);
7295
+ else line(`Closed session ${result.sessionId} with status ${options.status}.`);
6978
7296
  });
6979
7297
  var correction = program.command("correction").description("Manage durable Agent Studio correction rules.");
6980
- correction.command("list").description("List correction rules.").action(() => {
6981
- console.log(JSON.stringify(listCorrections(process.cwd()), null, 2));
7298
+ correction.command("list").description("List correction rules.").option("--json", "Print machine-readable JSON output.").action((options) => {
7299
+ const corrections = listCorrections(process.cwd());
7300
+ if (options.json) {
7301
+ printJson(corrections);
7302
+ return;
7303
+ }
7304
+ const rules = [...corrections.project, ...corrections.agent, ...corrections.upstream];
7305
+ if (rules.length === 0) {
7306
+ line("No correction rules yet. Add one with agent-kit correction add <text>.");
7307
+ return;
7308
+ }
7309
+ for (const rule of rules) {
7310
+ line(`${rule.id} [${rule.status}] (${rule.scope}) ${rule.text}`);
7311
+ }
6982
7312
  });
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
- console.log(
6985
- JSON.stringify(
6986
- addCorrection(process.cwd(), {
6987
- scope: options.scope,
6988
- ...options.agent ? { agentId: options.agent } : {},
6989
- text: textParts.join(" ")
6990
- }),
6991
- null,
6992
- 2
6993
- )
6994
- );
7313
+ 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) => {
7314
+ const result = addCorrection(process.cwd(), {
7315
+ scope: options.scope,
7316
+ ...options.agent ? { agentId: options.agent } : {},
7317
+ text: textParts.join(" ")
7318
+ });
7319
+ if (options.json) printJson(result);
7320
+ else line(`Added ${options.scope}-scoped correction ${result.id}.`);
6995
7321
  });
6996
- correction.command("apply [id]").description("Mark a correction rule active and reviewed.").option("--id <id>", "Correction id.").action((idArgument, options) => {
7322
+ 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
7323
  const id = idArgument ?? options.id;
6998
7324
  if (!id) {
6999
- console.error("Missing correction id. Use agent-kit correction apply <id> or --id <id>.");
7325
+ fail("Missing correction id. Use agent-kit correction apply <id> or --id <id>.");
7000
7326
  process.exitCode = 1;
7001
7327
  return;
7002
7328
  }
7003
- console.log(JSON.stringify(applyCorrection(process.cwd(), id), null, 2));
7329
+ const result = applyCorrection(process.cwd(), id);
7330
+ if (options.json) printJson(result);
7331
+ else line(`Applied correction ${id}.`);
7004
7332
  });
7005
- correction.command("retire <id>").description("Retire a correction rule.").requiredOption("--reason <reason>", "Reason for retirement.").action((id, options) => {
7006
- console.log(JSON.stringify(retireCorrection(process.cwd(), id, options.reason), null, 2));
7333
+ 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) => {
7334
+ const result = retireCorrection(process.cwd(), id, options.reason);
7335
+ if (options.json) printJson(result);
7336
+ else line(`Retired correction ${id}: ${options.reason}`);
7007
7337
  });
7008
- correction.command("propose-upstream <id>").description("Create an upstream proposal from a project or agent correction.").action((id) => {
7009
- console.log(JSON.stringify(proposeCorrectionUpstream(process.cwd(), id), null, 2));
7338
+ 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) => {
7339
+ const result = proposeCorrectionUpstream(process.cwd(), id);
7340
+ if (options.json) printJson(result);
7341
+ else line(`Created upstream proposal from correction ${id}.`);
7010
7342
  });
7011
7343
  var studio = program.command("studio").description("Export and serve local Agent Studio views.");
7012
7344
  async function runStudioServer(options) {
@@ -7016,16 +7348,14 @@ async function runStudioServer(options) {
7016
7348
  host: options.host
7017
7349
  });
7018
7350
  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
- );
7351
+ console.warn(`Port ${handle.requestedPort} is in use \u2014 using fallback port ${handle.port}. Kill the old process to avoid confusion.`);
7022
7352
  }
7023
7353
  console.log(`Agent Kit v${PACKAGE_VERSION} \u2014 live studio at ${handle.url}/`);
7024
7354
  console.log("SSE: GET /api/events/stream | Press Ctrl+C to stop.");
7025
- if (options.open) openBrowser(`${handle.url}/`);
7355
+ if (options.open) void openBrowser(`${handle.url}/`);
7026
7356
  await new Promise((resolve3) => {
7027
7357
  const shutdown = () => {
7028
- handle.close().finally(resolve3);
7358
+ void handle.close().finally(resolve3);
7029
7359
  };
7030
7360
  process.once("SIGINT", shutdown);
7031
7361
  process.once("SIGTERM", shutdown);
@@ -7034,8 +7364,13 @@ async function runStudioServer(options) {
7034
7364
  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
7365
  await runStudioServer(options);
7036
7366
  });
7037
- studio.command("export").description("Generate a self-contained static Agent Studio HTML file.").action(() => {
7038
- console.log(JSON.stringify(exportStaticStudio(process.cwd()), null, 2));
7367
+ studio.command("export").description("Generate a self-contained static Agent Studio HTML file.").option("--json", "Print machine-readable JSON output.").action((options) => {
7368
+ const result = exportStaticStudio(process.cwd());
7369
+ if (options.json) {
7370
+ printJson(result);
7371
+ return;
7372
+ }
7373
+ line(`Exported ${result.sessionCount} session(s) to ${result.studioPath}.`);
7039
7374
  });
7040
7375
  var research = program.command("research").description("Research high-quality open-source repositories.");
7041
7376
  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 +7392,7 @@ research.command("propose-updates").description("Create a research-to-template u
7057
7392
  console.log(proposeUpdates(process.cwd()));
7058
7393
  });
7059
7394
  program.parseAsync(process.argv).catch((error) => {
7060
- console.error(error instanceof Error ? error.message : String(error));
7395
+ fail(error instanceof Error ? error.message : String(error));
7061
7396
  process.exitCode = 1;
7062
7397
  });
7063
7398
  //# sourceMappingURL=index.js.map