kairn-cli 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -338,7 +338,7 @@ var initCommand = new Command("init").description("Set up Kairn with your API ke
338
338
 
339
339
  // src/commands/describe.ts
340
340
  import { Command as Command2 } from "commander";
341
- import { input, confirm } from "@inquirer/prompts";
341
+ import { input, confirm, select as select2 } from "@inquirer/prompts";
342
342
  import chalk5 from "chalk";
343
343
  import ora from "ora";
344
344
 
@@ -614,6 +614,19 @@ When generating for Hermes runtime, the same EnvironmentSpec JSON is produced. T
614
614
 
615
615
  The LLM output format does not change. Adapter-level conversion happens post-compilation.
616
616
 
617
+ ## Autonomy Levels
618
+
619
+ The user may specify an autonomy level (1-4). This affects CLAUDE.md content:
620
+
621
+ - **Level 1 (Guided):** Add a "Workflow" section showing recommended command flow (e.g., spec \u2192 sprint \u2192 plan \u2192 code \u2192 prove \u2192 grill \u2192 commit) and a "When to Use What" reference table.
622
+ - **Level 2 (Assisted):** Level 1 content + mention /project:loop in the workflow section and @pm in the agents section of CLAUDE.md.
623
+ - **Level 3 (Autonomous):** Level 2 content + mention /project:auto and worktree-based PR delivery workflow.
624
+ - **Level 4 (Full Auto):** Level 3 content + add a prominent warning section about autonomous operation.
625
+
626
+ The autonomy-specific commands, agents, and hooks are injected post-compilation. Focus on tailoring the CLAUDE.md content and workflow guidance for the selected level.
627
+
628
+ If no autonomy level is specified, assume Level 1 (Guided).
629
+
617
630
  ## Output Schema
618
631
 
619
632
  Return ONLY valid JSON matching this structure:
@@ -884,7 +897,8 @@ async function compile(intent, onProgress) {
884
897
  id: `env_${crypto.randomUUID()}`,
885
898
  intent,
886
899
  created_at: (/* @__PURE__ */ new Date()).toISOString(),
887
- ...parsed
900
+ ...parsed,
901
+ autonomy_level: parsed.autonomy_level ?? 1
888
902
  };
889
903
  validateSpec(spec, onProgress);
890
904
  await ensureDirs();
@@ -919,6 +933,290 @@ async function generateClarifications(intent, onProgress) {
919
933
  // src/adapter/claude-code.ts
920
934
  import fs5 from "fs/promises";
921
935
  import path5 from "path";
936
+
937
+ // src/autonomy.ts
938
+ var AUTONOMY_LABELS = {
939
+ 1: "Guided",
940
+ 2: "Assisted",
941
+ 3: "Autonomous",
942
+ 4: "Full Auto"
943
+ };
944
+ var WELCOME_HOOK = {
945
+ matcher: "",
946
+ hooks: [{
947
+ type: "command",
948
+ command: "if [ ! -f .claude/.toured ]; then echo '\\n Welcome to your Kairn environment!\\n Type /project:tour for a walkthrough, or /project:help for a quick reference.\\n'; fi"
949
+ }]
950
+ };
951
+ var TOUR_COMMAND = `# Environment Tour
952
+
953
+ Welcome! Let me show you around this Kairn environment.
954
+
955
+ ## Your Commands
956
+ Read .claude/commands/ and list each one with a one-line description.
957
+ Group them by workflow phase:
958
+
959
+ PLAN: /project:spec, /project:sprint, /project:plan
960
+ BUILD: (just start coding \u2014 Claude reads CLAUDE.md automatically)
961
+ VERIFY: /project:prove, /project:grill, /project:test
962
+ SHIP: /project:commit, /project:review
963
+ MANAGE: /project:status, /project:tasks, /project:reset
964
+
965
+ ## Your Agents
966
+ Read .claude/agents/ and explain each one with how to invoke it.
967
+
968
+ ## Your MCP Tools
969
+ !claude mcp list 2>/dev/null || echo "Run /mcp in Claude Code to see active tools"
970
+
971
+ ## Workflow
972
+ For this project, the recommended flow is:
973
+ spec \u2192 sprint \u2192 plan \u2192 code \u2192 prove \u2192 grill \u2192 commit
974
+
975
+ ## Tips
976
+ - Type / to see all commands
977
+ - Type @ to invoke an agent
978
+ - Paste raw errors \u2014 don't summarize them
979
+ - Use subagents for deep investigation
980
+ - Say "update CLAUDE.md" after any correction
981
+
982
+ After showing the tour, create .claude/.toured to suppress the welcome message:
983
+ !touch .claude/.toured
984
+
985
+ Ready to start? Try /project:spec to define your first feature.`;
986
+ function buildQuickstart(spec) {
987
+ const commands = Object.keys(spec.harness.commands || {});
988
+ const agents = Object.keys(spec.harness.agents || {});
989
+ const commandList = commands.map((c) => `- \`/project:${c}\``).join("\n");
990
+ const agentList = agents.length > 0 ? agents.map((a) => `- \`@${a}\``).join("\n") : "- (none configured)";
991
+ return `# Quick Start Guide
992
+
993
+ This environment was generated by Kairn. Here's how to use it.
994
+
995
+ ## First Time
996
+ 1. Open terminal in this directory
997
+ 2. Run \`claude\`
998
+ 3. Type \`/project:tour\` for a guided walkthrough
999
+
1000
+ ## Daily Workflow
1001
+ 1. \`/project:status\` \u2014 see where things stand
1002
+ 2. \`/project:spec\` \u2014 define what to build (Claude will interview you)
1003
+ 3. Start coding \u2014 Claude follows CLAUDE.md automatically
1004
+ 4. \`/project:prove\` \u2014 verify your work
1005
+ 5. \`/project:commit\` \u2014 ship it
1006
+
1007
+ ## Commands
1008
+ ${commandList}
1009
+
1010
+ ## Agents
1011
+ ${agentList}
1012
+
1013
+ ## Need Help?
1014
+ Type \`/project:help\` in Claude Code for a quick reference.
1015
+ `;
1016
+ }
1017
+ var LOOP_COMMAND_CODE = `# Development Loop
1018
+
1019
+ Run an assisted development cycle for the next feature.
1020
+
1021
+ ## Phase 1: SPEC
1022
+ Review docs/TODO.md and docs/SPRINT.md.
1023
+ If no sprint is defined, run /project:spec to interview the user.
1024
+ Wait for user approval of the spec.
1025
+
1026
+ ## Phase 2: PLAN
1027
+ Read the approved spec in docs/SPRINT.md.
1028
+ Plan the implementation: files to change, tests to write, approach.
1029
+ Write plan to docs/DECISIONS.md.
1030
+ Wait for user approval of the plan.
1031
+
1032
+ ## Phase 3: IMPLEMENT
1033
+ Follow the plan. Implement the feature.
1034
+ Run tests after each change.
1035
+ Commit each logical unit: "feat: description"
1036
+
1037
+ ## Phase 4: VERIFY
1038
+ Run /project:prove to verify the implementation.
1039
+ If confidence is LOW or MEDIUM, fix issues and re-verify.
1040
+
1041
+ ## Phase 5: REVIEW
1042
+ Run /project:grill for adversarial review.
1043
+ Fix any BLOCKERs.
1044
+
1045
+ ## Phase 6: SHIP
1046
+ Run /project:commit.
1047
+ Report what was built and what's next from docs/TODO.md.
1048
+
1049
+ Then ask: "Continue to next feature?"
1050
+ If yes, return to Phase 1.`;
1051
+ var LOOP_COMMAND_RESEARCH = `# Research Loop
1052
+
1053
+ Run an assisted research cycle.
1054
+
1055
+ ## Phase 1: QUESTION
1056
+ Review docs/TODO.md for the next research question.
1057
+ If none, ask the user what to investigate.
1058
+
1059
+ ## Phase 2: RESEARCH
1060
+ Search, extract, and analyze sources.
1061
+ Log findings to docs/SOURCES.md and docs/LEARNINGS.md.
1062
+
1063
+ ## Phase 3: SYNTHESIZE
1064
+ Review all findings. Write structured summary to docs/SUMMARY.md.
1065
+ Cite all sources.
1066
+
1067
+ ## Phase 4: REVIEW
1068
+ Present the summary. Ask the user for feedback.
1069
+ Revise based on feedback.
1070
+
1071
+ ## Phase 5: NEXT
1072
+ Update docs/TODO.md \u2014 mark question as done, identify follow-ups.
1073
+ Ask: "Continue to next question?"`;
1074
+ var PM_AGENT = `---
1075
+ name: pm
1076
+ description: Project manager agent. Maintains roadmap, specs features, prioritizes work.
1077
+ model: opus
1078
+ ---
1079
+
1080
+ You are a project manager for this codebase.
1081
+
1082
+ Your responsibilities:
1083
+ 1. Maintain docs/TODO.md \u2014 keep it prioritized and current
1084
+ 2. Write specs to docs/SPRINT.md when asked
1085
+ 3. Review completed work and suggest what's next
1086
+ 4. Track decisions in docs/DECISIONS.md
1087
+ 5. Track learnings in docs/LEARNINGS.md
1088
+
1089
+ When invoked:
1090
+ - Read all docs/ files to understand current state
1091
+ - Read recent git log for what changed
1092
+ - Suggest the highest-priority next task
1093
+ - If asked to spec something, interview the user (5-8 questions)
1094
+
1095
+ You do NOT write code. You plan, spec, and prioritize.`;
1096
+ var AUTO_COMMAND = `# Autonomous Development
1097
+
1098
+ PM-driven development loop with PR delivery.
1099
+
1100
+ ## Phase 1: PLAN (@pm)
1101
+ Use @pm to:
1102
+ - Read docs/TODO.md and docs/SPRINT.md
1103
+ - Select the highest-priority unfinished task
1104
+ - Write a spec to docs/SPRINT.md
1105
+ - Present the spec for approval
1106
+
1107
+ Wait for user approval. If approved, proceed.
1108
+
1109
+ ## Phase 2: BRANCH
1110
+ Create an isolated worktree:
1111
+ git worktree add ../project-feat-{name} -b feat/{name}
1112
+ All implementation happens in the worktree.
1113
+
1114
+ ## Phase 3: IMPLEMENT
1115
+ In the worktree directory:
1116
+ - Follow the spec in docs/SPRINT.md
1117
+ - Build, test, commit after each change
1118
+
1119
+ ## Phase 4: VERIFY
1120
+ Run verification:
1121
+ - Static analysis (linting, type checks)
1122
+ - Run functional tests
1123
+ - If NEEDS FIXES: fix and re-verify
1124
+
1125
+ ## Phase 5: PR
1126
+ Create a pull request:
1127
+ gh pr create --title "feat: {name}" --body "{spec + QA report}"
1128
+
1129
+ ## Phase 6: NEXT
1130
+ Report:
1131
+ "PR #{N} ready for review: {link}
1132
+ Next priority from TODO.md: {next task}
1133
+ Continue? (y/n)"
1134
+
1135
+ If yes, return to Phase 1 with next task.`;
1136
+ var AUTOPILOT_COMMAND = `# Autopilot Mode
1137
+
1138
+ Continuous autonomous development. The PM plans, the loop executes,
1139
+ PRs are opened automatically. You review when ready.
1140
+
1141
+ ## Configuration
1142
+ - Max features per session: 5 (prevent runaway)
1143
+ - Stop on: test failure, build error, or blocked dependency
1144
+ - All work in isolated worktrees
1145
+ - Every feature = one PR
1146
+
1147
+ ## The Loop
1148
+ Repeat until max features reached or stopped:
1149
+ 1. @pm selects next priority from docs/TODO.md
1150
+ 2. Create worktree + branch
1151
+ 3. Implement the feature
1152
+ 4. Run verification (build, test, lint)
1153
+ 5. Open PR via gh
1154
+ 6. Report status
1155
+ 7. Move to next feature
1156
+
1157
+ ## Stop Conditions
1158
+ - Max 5 features per autopilot session
1159
+ - Any BLOCKER from verification
1160
+ - Build failure that can't be resolved in 3 attempts
1161
+ - User presses Escape`;
1162
+ var AUTOPILOT_WARNING = `
1163
+ ## Autopilot Mode Active
1164
+ This environment is configured for autonomous operation.
1165
+ The @pm agent plans features and /project:autopilot executes them.
1166
+ All changes are delivered as PRs \u2014 review before merging.
1167
+ Stop conditions: max 5 features, test failure, or Escape.`;
1168
+ function isResearchProject(spec) {
1169
+ const commands = spec.harness.commands ?? {};
1170
+ return "research" in commands || "summarize" in commands;
1171
+ }
1172
+ function applyAutonomyLevel(spec) {
1173
+ const level = spec.autonomy_level ?? 1;
1174
+ const commands = spec.harness.commands ?? {};
1175
+ const agents = spec.harness.agents ?? {};
1176
+ const docs = spec.harness.docs ?? {};
1177
+ const settings = spec.harness.settings ?? {};
1178
+ if (level >= 1) {
1179
+ if (!("tour" in commands)) {
1180
+ commands.tour = TOUR_COMMAND;
1181
+ }
1182
+ docs.QUICKSTART = buildQuickstart(spec);
1183
+ const hooks = settings.hooks ?? {};
1184
+ const sessionStart = hooks.SessionStart ?? [];
1185
+ sessionStart.push(WELCOME_HOOK);
1186
+ hooks.SessionStart = sessionStart;
1187
+ settings.hooks = hooks;
1188
+ }
1189
+ if (level >= 2) {
1190
+ if (!("loop" in commands)) {
1191
+ commands.loop = isResearchProject(spec) ? LOOP_COMMAND_RESEARCH : LOOP_COMMAND_CODE;
1192
+ }
1193
+ if (!("pm" in agents)) {
1194
+ agents.pm = PM_AGENT;
1195
+ }
1196
+ }
1197
+ if (level >= 3) {
1198
+ if (!("auto" in commands)) {
1199
+ commands.auto = AUTO_COMMAND;
1200
+ }
1201
+ }
1202
+ if (level >= 4) {
1203
+ if (!("autopilot" in commands)) {
1204
+ commands.autopilot = AUTOPILOT_COMMAND;
1205
+ }
1206
+ if (spec.harness.claude_md && !spec.harness.claude_md.includes("Autopilot Mode")) {
1207
+ spec.harness.claude_md += "\n" + AUTOPILOT_WARNING;
1208
+ }
1209
+ }
1210
+ spec.harness.commands = commands;
1211
+ spec.harness.agents = agents;
1212
+ spec.harness.docs = docs;
1213
+ spec.harness.settings = settings;
1214
+ }
1215
+ function autonomyLabel(level) {
1216
+ return AUTONOMY_LABELS[level];
1217
+ }
1218
+
1219
+ // src/adapter/claude-code.ts
922
1220
  var STATUS_LINE = {
923
1221
  command: `printf '%s | %s tasks' "$(git branch --show-current 2>/dev/null || echo 'no-git')" "$(grep -c '\\- \\[ \\]' docs/TODO.md 2>/dev/null || echo 0)"`
924
1222
  };
@@ -954,6 +1252,7 @@ async function writeFile(filePath, content) {
954
1252
  await fs5.writeFile(filePath, content, "utf-8");
955
1253
  }
956
1254
  function buildFileMap(spec, options) {
1255
+ applyAutonomyLevel(spec);
957
1256
  const files = /* @__PURE__ */ new Map();
958
1257
  if (spec.harness.claude_md) {
959
1258
  files.set(".claude/CLAUDE.md", spec.harness.claude_md);
@@ -996,6 +1295,7 @@ function buildFileMap(spec, options) {
996
1295
  return files;
997
1296
  }
998
1297
  async function writeEnvironment(spec, targetDir, options) {
1298
+ applyAutonomyLevel(spec);
999
1299
  const claudeDir = path5.join(targetDir, ".claude");
1000
1300
  const written = [];
1001
1301
  if (spec.harness.claude_md) {
@@ -1360,6 +1660,23 @@ Clarifications:
1360
1660
  ${clarificationLines}`;
1361
1661
  }
1362
1662
  }
1663
+ let autonomyLevel = 1;
1664
+ if (!options.quick) {
1665
+ console.log(ui.section("Autonomy"));
1666
+ autonomyLevel = await select2({
1667
+ message: "Autonomy level",
1668
+ choices: [
1669
+ { name: "1. Guided \u2014 orientation + commands, you drive", value: 1 },
1670
+ { name: "2. Assisted \u2014 workflow loop, you approve phases", value: 2 },
1671
+ { name: "3. Autonomous \u2014 PM plans, loop executes, you review PRs", value: 3 },
1672
+ { name: "4. Full Auto \u2014 continuous execution (\u26A0 advanced)", value: 4 }
1673
+ ],
1674
+ default: 1
1675
+ });
1676
+ finalIntent += `
1677
+
1678
+ Autonomy level: ${autonomyLevel} (${autonomyLabel(autonomyLevel)})`;
1679
+ }
1363
1680
  console.log(ui.section("Compilation"));
1364
1681
  const spinner = ora({ text: "Loading tool registry...", indent: 2 }).start();
1365
1682
  let spec;
@@ -1367,6 +1684,7 @@ ${clarificationLines}`;
1367
1684
  spec = await compile(finalIntent, (msg) => {
1368
1685
  spinner.text = msg;
1369
1686
  });
1687
+ spec.autonomy_level = autonomyLevel;
1370
1688
  spinner.succeed("Environment compiled");
1371
1689
  } catch (err) {
1372
1690
  spinner.fail("Compilation failed");
@@ -1381,6 +1699,7 @@ ${clarificationLines}`;
1381
1699
  console.log("");
1382
1700
  console.log(ui.kv("Name:", spec.name));
1383
1701
  console.log(ui.kv("Description:", spec.description));
1702
+ console.log(ui.kv("Autonomy:", `Level ${spec.autonomy_level} (${autonomyLabel(spec.autonomy_level)})`));
1384
1703
  console.log(ui.kv("Tools:", String(summary.toolCount)));
1385
1704
  console.log(ui.kv("Commands:", String(summary.commandCount)));
1386
1705
  console.log(ui.kv("Rules:", String(summary.ruleCount)));
@@ -2274,7 +2593,7 @@ var doctorCommand = new Command7("doctor").description(
2274
2593
  // src/commands/registry.ts
2275
2594
  import { Command as Command8 } from "commander";
2276
2595
  import chalk11 from "chalk";
2277
- import { input as input2, select as select2 } from "@inquirer/prompts";
2596
+ import { input as input2, select as select3 } from "@inquirer/prompts";
2278
2597
  var listCommand2 = new Command8("list").description("List tools in the registry").option("--category <cat>", "Filter by category").option("--user-only", "Show only user-defined tools").action(async (options) => {
2279
2598
  printCompactBanner();
2280
2599
  let all;
@@ -2344,7 +2663,7 @@ var addCommand = new Command8("add").description("Add a tool to the user registr
2344
2663
  });
2345
2664
  const name = await input2({ message: "Display name" });
2346
2665
  const description = await input2({ message: "Description" });
2347
- const category = await select2({
2666
+ const category = await select3({
2348
2667
  message: "Category",
2349
2668
  choices: [
2350
2669
  { value: "universal" },
@@ -2358,7 +2677,7 @@ var addCommand = new Command8("add").description("Add a tool to the user registr
2358
2677
  { value: "sandbox" }
2359
2678
  ]
2360
2679
  });
2361
- const tier = await select2({
2680
+ const tier = await select3({
2362
2681
  message: "Tier",
2363
2682
  choices: [
2364
2683
  { name: "1 \u2014 Universal", value: 1 },
@@ -2366,7 +2685,7 @@ var addCommand = new Command8("add").description("Add a tool to the user registr
2366
2685
  { name: "3 \u2014 Specialized", value: 3 }
2367
2686
  ]
2368
2687
  });
2369
- const type = await select2({
2688
+ const type = await select3({
2370
2689
  message: "Type",
2371
2690
  choices: [
2372
2691
  { value: "mcp_server" },
@@ -2374,7 +2693,7 @@ var addCommand = new Command8("add").description("Add a tool to the user registr
2374
2693
  { value: "hook" }
2375
2694
  ]
2376
2695
  });
2377
- const auth = await select2({
2696
+ const auth = await select3({
2378
2697
  message: "Auth",
2379
2698
  choices: [
2380
2699
  { value: "none" },
@@ -2390,7 +2709,7 @@ var addCommand = new Command8("add").description("Add a tool to the user registr
2390
2709
  const varName = await input2({ message: "Env var name" });
2391
2710
  const varDesc = await input2({ message: "Env var description" });
2392
2711
  env_vars.push({ name: varName, description: varDesc });
2393
- const another = await select2({
2712
+ const another = await select3({
2394
2713
  message: "Add another env var?",
2395
2714
  choices: [
2396
2715
  { name: "No", value: false },
@@ -2654,7 +2973,7 @@ var keysCommand = new Command10("keys").description("Add or update API keys for
2654
2973
  var program = new Command11();
2655
2974
  program.name("kairn").description(
2656
2975
  "Compile natural language intent into optimized Claude Code environments"
2657
- ).version("1.8.0").option("--no-color", "Disable colored output");
2976
+ ).version("1.9.0").option("--no-color", "Disable colored output");
2658
2977
  program.addCommand(initCommand);
2659
2978
  program.addCommand(describeCommand);
2660
2979
  program.addCommand(optimizeCommand);