@alecsibilia/luca 13.0.0-alpha.1 → 13.0.0-alpha.3

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 (45) hide show
  1. package/dist/chunks/branch.mjs +6 -6
  2. package/dist/chunks/checks.mjs +6 -6
  3. package/dist/chunks/claim-verify.mjs +1 -1
  4. package/dist/chunks/classify.mjs +1 -1
  5. package/dist/chunks/confidence.mjs +6 -6
  6. package/dist/chunks/doctor.mjs +6 -0
  7. package/dist/chunks/hook.mjs +27 -9
  8. package/dist/chunks/init.mjs +4 -5
  9. package/dist/chunks/legacy-package.mjs +47 -0
  10. package/dist/chunks/muninn-mcp.mjs +104 -0
  11. package/dist/chunks/muninndb-health.mjs +1 -1
  12. package/dist/chunks/phase.mjs +28 -8
  13. package/dist/chunks/pr-review.mjs +6 -6
  14. package/dist/chunks/preferences.mjs +6 -6
  15. package/dist/chunks/repair.mjs +1 -1
  16. package/dist/chunks/repo.mjs +6 -6
  17. package/dist/chunks/retro.mjs +5 -5
  18. package/dist/chunks/roadmap.mjs +6 -6
  19. package/dist/chunks/rules.mjs +5 -5
  20. package/dist/chunks/stale-global-symlinks.mjs +78 -0
  21. package/dist/chunks/state.mjs +6 -6
  22. package/dist/chunks/stray-local-install.mjs +15 -7
  23. package/dist/chunks/telemetry.mjs +1 -1
  24. package/dist/chunks/todo.mjs +6 -6
  25. package/dist/chunks/vault-init.mjs +6 -4
  26. package/dist/chunks/verification.mjs +4 -4
  27. package/dist/chunks/workflow.mjs +6 -6
  28. package/dist/claude/.claude/hooks/context-refresher.ts +14047 -252
  29. package/dist/claude/.claude/hooks/continuation-messages.ts +14024 -190
  30. package/dist/claude/.claude/hooks/pipeline-guard.ts +14016 -162
  31. package/dist/claude/skills/caveman/SKILL.md +58 -0
  32. package/dist/claude/skills/lu/SKILL.md +1 -1
  33. package/dist/claude/skills/milestone-complete/SKILL.md +8 -1
  34. package/dist/index.mjs +1 -1
  35. package/dist/shared/{luca.CrXzXueR.mjs → luca.BH2GZl5z.mjs} +1 -1
  36. package/dist/shared/{luca.B3saVjJm.mjs → luca.BHov6l1O.mjs} +25 -5
  37. package/dist/shared/{luca.BmhNkYe2.mjs → luca.BQXFn5yo.mjs} +2 -2
  38. package/dist/shared/{luca.BYdjkfnz.mjs → luca.BfjhRHhj.mjs} +1 -1
  39. package/dist/shared/{luca.C4gMUoBd.mjs → luca.BhM9TDAo.mjs} +3 -3
  40. package/dist/shared/{luca.HZxBTBgD.mjs → luca.CuvqWf4b.mjs} +2 -2
  41. package/dist/shared/{luca.CRmaAfXR.mjs → luca.DXUcpbIe.mjs} +5 -4
  42. package/dist/shared/{luca.B3Mimc0P.mjs → luca.Djs7oPPj.mjs} +5 -0
  43. package/dist/shared/{luca.DjDTeDCi.mjs → luca.DykMxS_D.mjs} +125 -16
  44. package/dist/shared/{luca.TSMg1t7I.mjs → luca.pqZahLS5.mjs} +1 -1
  45. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { defineCommand } from 'citty';
2
2
  import 'zod';
3
- import '../shared/luca.CRmaAfXR.mjs';
3
+ import '../shared/luca.DXUcpbIe.mjs';
4
4
  import 'node:fs';
5
5
  import 'node:fs/promises';
6
6
  import 'node:path';
@@ -8,13 +8,13 @@ import 'node:crypto';
8
8
  import 'node:module';
9
9
  import 'node:url';
10
10
  import 'node:child_process';
11
- import { r as runWriteHandler, q as lucaBranchGuardTool } from '../shared/luca.DjDTeDCi.mjs';
11
+ import { r as runWriteHandler, t as lucaBranchGuardTool } from '../shared/luca.DykMxS_D.mjs';
12
12
  import 'node:os';
13
- import '../shared/luca.CrXzXueR.mjs';
14
- import '../shared/luca.HZxBTBgD.mjs';
15
- import '../shared/luca.TSMg1t7I.mjs';
13
+ import '../shared/luca.BH2GZl5z.mjs';
14
+ import '../shared/luca.CuvqWf4b.mjs';
15
+ import '../shared/luca.pqZahLS5.mjs';
16
16
  import '../shared/luca.CQ3g1xrD.mjs';
17
- import '../shared/luca.B3Mimc0P.mjs';
17
+ import '../shared/luca.Djs7oPPj.mjs';
18
18
 
19
19
  const guardCommand = defineCommand({
20
20
  meta: {
@@ -1,6 +1,6 @@
1
1
  import { defineCommand } from 'citty';
2
2
  import 'zod';
3
- import '../shared/luca.CRmaAfXR.mjs';
3
+ import '../shared/luca.DXUcpbIe.mjs';
4
4
  import 'node:fs';
5
5
  import 'node:fs/promises';
6
6
  import 'node:path';
@@ -8,13 +8,13 @@ import 'node:crypto';
8
8
  import 'node:module';
9
9
  import 'node:url';
10
10
  import 'node:child_process';
11
- import { c as readJsonPayload, r as runWriteHandler, p as lucaChecksRunTool } from '../shared/luca.DjDTeDCi.mjs';
11
+ import { e as readJsonPayload, r as runWriteHandler, s as lucaChecksRunTool } from '../shared/luca.DykMxS_D.mjs';
12
12
  import 'node:os';
13
- import '../shared/luca.CrXzXueR.mjs';
14
- import '../shared/luca.HZxBTBgD.mjs';
15
- import '../shared/luca.TSMg1t7I.mjs';
13
+ import '../shared/luca.BH2GZl5z.mjs';
14
+ import '../shared/luca.CuvqWf4b.mjs';
15
+ import '../shared/luca.pqZahLS5.mjs';
16
16
  import '../shared/luca.CQ3g1xrD.mjs';
17
- import '../shared/luca.B3Mimc0P.mjs';
17
+ import '../shared/luca.Djs7oPPj.mjs';
18
18
 
19
19
  const runCommand = defineCommand({
20
20
  meta: {
@@ -1,6 +1,6 @@
1
1
  import { defineCommand } from 'citty';
2
2
  import { resolve } from 'pathe';
3
- import '../shared/luca.CRmaAfXR.mjs';
3
+ import '../shared/luca.DXUcpbIe.mjs';
4
4
  import { readFileSync, existsSync, readdirSync, statSync } from 'node:fs';
5
5
  import 'node:fs/promises';
6
6
  import { join } from 'node:path';
@@ -1,5 +1,5 @@
1
1
  import { defineCommand } from 'citty';
2
- import { C as ClassifyComplexityInputSchema } from '../shared/luca.CRmaAfXR.mjs';
2
+ import { C as ClassifyComplexityInputSchema } from '../shared/luca.DXUcpbIe.mjs';
3
3
  import 'node:fs';
4
4
  import 'node:fs/promises';
5
5
  import 'node:path';
@@ -1,6 +1,6 @@
1
1
  import { defineCommand } from 'citty';
2
- import '../shared/luca.CRmaAfXR.mjs';
3
- import { l as loadCurrentState, r as resolveActiveSlug } from '../shared/luca.CrXzXueR.mjs';
2
+ import '../shared/luca.DXUcpbIe.mjs';
3
+ import { l as loadCurrentState, r as resolveActiveSlug } from '../shared/luca.BH2GZl5z.mjs';
4
4
  import 'node:fs';
5
5
  import 'node:fs/promises';
6
6
  import 'node:path';
@@ -8,15 +8,15 @@ import 'node:crypto';
8
8
  import 'node:module';
9
9
  import 'node:url';
10
10
  import 'node:child_process';
11
- import { b as renderConfidenceJournalMarkdown, r as readConfidenceJournal, g as getConfidenceSummary } from '../shared/luca.HZxBTBgD.mjs';
11
+ import { b as renderConfidenceJournalMarkdown, r as readConfidenceJournal, g as getConfidenceSummary } from '../shared/luca.CuvqWf4b.mjs';
12
12
  import { l as logger } from '../shared/luca.dM-MKlNE.mjs';
13
13
  import 'zod';
14
- import { c as readJsonPayload, r as runWriteHandler, t as lucaConfidenceLogTool } from '../shared/luca.DjDTeDCi.mjs';
14
+ import { e as readJsonPayload, r as runWriteHandler, v as lucaConfidenceLogTool } from '../shared/luca.DykMxS_D.mjs';
15
15
  import 'node:os';
16
- import '../shared/luca.TSMg1t7I.mjs';
16
+ import '../shared/luca.pqZahLS5.mjs';
17
17
  import 'consola';
18
18
  import '../shared/luca.CQ3g1xrD.mjs';
19
- import '../shared/luca.B3Mimc0P.mjs';
19
+ import '../shared/luca.Djs7oPPj.mjs';
20
20
 
21
21
  async function resolveSlug(opts) {
22
22
  if (opts.explicit) return opts.explicit;
@@ -7,7 +7,10 @@ async function executeDoctor(options = {}) {
7
7
  logger.info("Running environment diagnostics...\n");
8
8
  const { bunRuntimeCheck } = await import('./bun-runtime.mjs');
9
9
  const { muninndbHealthCheck } = await import('./muninndb-health.mjs');
10
+ const { muninnMcpCheck } = await import('./muninn-mcp.mjs');
10
11
  const { staleMcpServerCheck } = await import('./stale-mcp-server.mjs');
12
+ const { staleGlobalSymlinksCheck } = await import('./stale-global-symlinks.mjs');
13
+ const { legacyPackageCheck } = await import('./legacy-package.mjs');
11
14
  const { strayLocalInstallCheck } = await import('./stray-local-install.mjs');
12
15
  const allChecks = [
13
16
  // Prerequisites
@@ -15,6 +18,9 @@ async function executeDoctor(options = {}) {
15
18
  staleMcpServerCheck,
16
19
  // Global
17
20
  muninndbHealthCheck,
21
+ muninnMcpCheck,
22
+ staleGlobalSymlinksCheck,
23
+ legacyPackageCheck,
18
24
  // Project (cwd-dependent)
19
25
  strayLocalInstallCheck
20
26
  ];
@@ -1,11 +1,11 @@
1
1
  import { defineCommand } from 'citty';
2
- import { c as coarsePhaseOf, a as classifyWritePath, A as AUDIT_PATH_PATTERN, W as WAVE_FILE_RE } from '../shared/luca.CRmaAfXR.mjs';
3
- import { l as loadCurrentState, r as resolveActiveSlug } from '../shared/luca.CrXzXueR.mjs';
2
+ import { c as coarsePhaseOf, a as classifyWritePath, A as AUDIT_PATH_PATTERN, W as WAVE_FILE_RE } from '../shared/luca.DXUcpbIe.mjs';
3
+ import { l as loadCurrentState, r as resolveActiveSlug } from '../shared/luca.BH2GZl5z.mjs';
4
4
  import 'node:fs';
5
5
  import 'node:fs/promises';
6
- import 'node:path';
7
- import { S as STEP_ARTIFACTS } from '../shared/luca.B3Mimc0P.mjs';
8
- import { p as phasePathFor } from '../shared/luca.TSMg1t7I.mjs';
6
+ import { isAbsolute, relative } from 'node:path';
7
+ import { S as STEP_ARTIFACTS } from '../shared/luca.Djs7oPPj.mjs';
8
+ import { p as phasePathFor } from '../shared/luca.pqZahLS5.mjs';
9
9
  import 'node:crypto';
10
10
  import 'node:module';
11
11
  import 'node:url';
@@ -72,6 +72,13 @@ function isToolAllowed({
72
72
  }
73
73
 
74
74
  const READONLY_COMMANDS = /* @__PURE__ */ new Set([
75
+ // Shell navigation/no-ops: mutate shell state, not files — benign for
76
+ // the file/repo-mutation policy this classifier enforces. `cd` is the
77
+ // big one: agents prefix nearly every command with `cd <dir> && …`, so
78
+ // omitting it made every compound command classify as a mutate.
79
+ "cd",
80
+ "pushd",
81
+ "popd",
75
82
  "ls",
76
83
  "cat",
77
84
  "grep",
@@ -195,7 +202,7 @@ const LUCA_READ_VERBS = /* @__PURE__ */ new Set([
195
202
  ]);
196
203
  const LUCA_NOUN_VERBS = {
197
204
  state: /* @__PURE__ */ new Set(["read", "advance"]),
198
- phase: /* @__PURE__ */ new Set(["current"]),
205
+ phase: /* @__PURE__ */ new Set(["current", "advance", "archive"]),
199
206
  roadmap: /* @__PURE__ */ new Set(["read", "create"]),
200
207
  preferences: /* @__PURE__ */ new Set(["read", "write"]),
201
208
  todo: /* @__PURE__ */ new Set(["add", "list", "update"]),
@@ -212,7 +219,7 @@ const LUCA_NOUN_VERBS = {
212
219
  };
213
220
  function classifyLucaCommand(rest) {
214
221
  const noun = rest.find((t) => !t.startsWith("-"));
215
- if (!noun) return void 0;
222
+ if (!noun) return "bash-readonly";
216
223
  const verbs = LUCA_NOUN_VERBS[noun];
217
224
  if (!verbs) return void 0;
218
225
  const afterNoun = rest.slice(rest.indexOf(noun) + 1);
@@ -358,6 +365,16 @@ function classifySubcommand(sub) {
358
365
  };
359
366
  }
360
367
  }
368
+ if (cmd === "sed" || cmd === "awk") {
369
+ const sedInPlace = cmd === "sed" && rest.some((a) => a === "--in-place" || a.startsWith("-i"));
370
+ const awkInPlace = cmd === "awk" && rest.some((a, i) => a === "-i" && rest[i + 1] === "inplace");
371
+ if (!sedInPlace && !awkInPlace) {
372
+ return {
373
+ category: sub.redirect ? "bash-mutate" : "bash-readonly",
374
+ targetPaths: targetsFromRedirect
375
+ };
376
+ }
377
+ }
361
378
  if (MUTATE_COMMANDS.has(cmd)) {
362
379
  const lastArg = cmd === "cp" || cmd === "mv" || cmd === "ln" ? lastNonFlag(rest) : void 0;
363
380
  const sedTarget = cmd === "sed" && rest.includes("-i") ? rest[rest.length - 1] : void 0;
@@ -494,11 +511,12 @@ async function handleStageGateHook(opts) {
494
511
  log(`stage-gate: ${toolName} without file_path \u2014 allowing`);
495
512
  return { exitCode: 0, toolName, toolInput, decision: "allow" };
496
513
  }
497
- const pc = classifyWritePath(targetPath, { homedir });
514
+ const relTarget = isAbsolute(targetPath) ? relative(cwd, targetPath) : targetPath;
515
+ const pc = classifyWritePath(targetPath, { homedir, cwd });
498
516
  if (pc.class === "denied") {
499
517
  pathBlockReason = `${toolName} to '${targetPath}' is always denied: ${pc.reason ?? "forbidden path"}`;
500
518
  } else if (pc.class === "planning-general" || pc.class === "planning-audit") {
501
- const gate = artifactPathGate(targetPath, state.pipelineStep, state);
519
+ const gate = artifactPathGate(relTarget, state.pipelineStep, state);
502
520
  if (gate.kind === "block") {
503
521
  const msg = `stage-gate BLOCK: ${toolName} ${gate.reason} (pipelineStep=${state.pipelineStep})`;
504
522
  log(msg);
@@ -3,16 +3,16 @@ import { defineCommand, runMain } from 'citty';
3
3
  import { existsSync, chmodSync } from 'node:fs';
4
4
  import { mkdir, writeFile, readFile, readdir, copyFile } from 'node:fs/promises';
5
5
  import { join, dirname, delimiter } from 'node:path';
6
- import { l as lucaStateSchema } from '../shared/luca.CRmaAfXR.mjs';
6
+ import { l as lucaStateSchema } from '../shared/luca.DXUcpbIe.mjs';
7
7
  import 'node:crypto';
8
8
  import 'node:module';
9
9
  import 'node:url';
10
10
  import 'node:child_process';
11
11
  import { g as generateRunId } from '../shared/luca.naWEcQ4B.mjs';
12
12
  import { LUCA_VERSION } from '../index.mjs';
13
- import { d as defaultClaudeHome, r as resolveBundledArtifactsForHooks, i as installSkills } from '../shared/luca.B3saVjJm.mjs';
13
+ import { d as defaultClaudeHome, r as resolveBundledArtifactsForHooks, i as installSkills } from '../shared/luca.BHov6l1O.mjs';
14
14
  import { l as logger } from '../shared/luca.dM-MKlNE.mjs';
15
- import { M as MuninndbInstallResultSchema, r as resolvePlatformTarget, g as getLucaHomePaths, a as MUNINNDB_BINARY_NAME, b as getCommonBinaryPaths, c as resolveMuninndbPort, d as checkMuninndbService, e as MuninndbServiceStatusSchema, w as waitForMuninndbHealthy, f as ensureLucaHome, h as checkMuninndbBinary, i as MUNINNDB_DEFAULT_PORT } from '../shared/luca.BYdjkfnz.mjs';
15
+ import { M as MuninndbInstallResultSchema, r as resolvePlatformTarget, g as getLucaHomePaths, a as MUNINNDB_BINARY_NAME, b as getCommonBinaryPaths, c as resolveMuninndbPort, d as checkMuninndbService, e as MuninndbServiceStatusSchema, w as waitForMuninndbHealthy, f as ensureLucaHome, h as checkMuninndbBinary } from '../shared/luca.BfjhRHhj.mjs';
16
16
  import { join as join$1 } from 'pathe';
17
17
  import { c as checkPrerequisites, p as promptBunInstall } from '../shared/luca.DTomPq7I.mjs';
18
18
  import 'zod';
@@ -689,12 +689,11 @@ const initCommand = defineCommand({
689
689
  readout.push(
690
690
  " stores them in MuninnDB; downstream pipeline modes consult them)"
691
691
  );
692
- const mcpPort = muninndbPort ?? MUNINNDB_DEFAULT_PORT;
693
692
  readout.push(
694
693
  " To expose MuninnDB to Claude Code: register it as an MCP server,"
695
694
  );
696
695
  readout.push(
697
- ` e.g. claude mcp add --transport http muninn http://localhost:${mcpPort}/mcp \\`
696
+ ` e.g. claude mcp add --transport sse muninn http://localhost:8750/mcp \\`
698
697
  );
699
698
  readout.push(
700
699
  ' --header "Authorization: Bearer <your-muninn-api-key>"'
@@ -0,0 +1,47 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+
5
+ const CHECK_NAME = "Legacy global package";
6
+ const LEGACY = "@alecsibilia/luca-framework";
7
+ const UMBRELLA = "@alecsibilia/luca";
8
+ function bunGlobalNodeModules() {
9
+ const bunInstall = process.env.BUN_INSTALL ?? join(homedir(), ".bun");
10
+ return join(bunInstall, "install", "global", "node_modules");
11
+ }
12
+ function isInstalled(nodeModules, pkg) {
13
+ return existsSync(join(nodeModules, pkg, "package.json"));
14
+ }
15
+ const legacyPackageCheck = {
16
+ name: CHECK_NAME,
17
+ scope: "global",
18
+ async run() {
19
+ const nm = bunGlobalNodeModules();
20
+ const legacyInstalled = isInstalled(nm, LEGACY);
21
+ if (!legacyInstalled) {
22
+ return {
23
+ name: CHECK_NAME,
24
+ status: "pass",
25
+ message: `no legacy ${LEGACY} global install`,
26
+ fixCommand: null,
27
+ details: null
28
+ };
29
+ }
30
+ const umbrellaInstalled = isInstalled(nm, UMBRELLA);
31
+ const conflict = umbrellaInstalled ? `Both ${UMBRELLA} and ${LEGACY} are installed globally \u2014 they provide the same \`luca\` binary, so the active one is whichever was installed last.` : `The pre-v13 ${LEGACY} is still installed globally; install ${UMBRELLA} for the v13 CLI.`;
32
+ const message = umbrellaInstalled ? `legacy ${LEGACY} installed globally (conflicts with ${UMBRELLA})` : `legacy ${LEGACY} still installed globally (pre-v13)`;
33
+ return {
34
+ name: CHECK_NAME,
35
+ status: "warning",
36
+ message,
37
+ fixCommand: `bun rm -g ${LEGACY}`,
38
+ details: [
39
+ conflict,
40
+ `Remove the legacy package: bun rm -g ${LEGACY}`,
41
+ `(reversible \u2014 \`bun add -g ${LEGACY}\` reinstalls it).`
42
+ ].join("\n ")
43
+ };
44
+ }
45
+ };
46
+
47
+ export { legacyPackageCheck };
@@ -0,0 +1,104 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+
4
+ const CHECK_NAME = "MuninnDB MCP wiring";
5
+ const MCP_URL = "http://127.0.0.1:8750/mcp";
6
+ const ADD_COMMAND = 'claude mcp add --transport sse muninn http://localhost:8750/mcp --header "Authorization: Bearer <your-muninn-api-key>"';
7
+ async function readJsonObject(path) {
8
+ try {
9
+ const file = Bun.file(path);
10
+ if (!await file.exists()) return null;
11
+ const parsed = JSON.parse(await file.text());
12
+ return parsed !== null && typeof parsed === "object" ? parsed : null;
13
+ } catch {
14
+ return null;
15
+ }
16
+ }
17
+ function hasMuninnEntry(mcpServers) {
18
+ return mcpServers !== null && typeof mcpServers === "object" && "muninn" in mcpServers;
19
+ }
20
+ async function isMuninnRegistered(cwd) {
21
+ const projectMcp = await readJsonObject(join(cwd, ".mcp.json"));
22
+ if (hasMuninnEntry(projectMcp?.mcpServers)) return true;
23
+ const userConfig = await readJsonObject(join(homedir(), ".claude.json"));
24
+ if (hasMuninnEntry(userConfig?.mcpServers)) return true;
25
+ const projects = userConfig?.projects;
26
+ if (projects !== null && typeof projects === "object") {
27
+ const project = projects[cwd];
28
+ if (project !== null && typeof project === "object" && hasMuninnEntry(project.mcpServers)) {
29
+ return true;
30
+ }
31
+ }
32
+ return false;
33
+ }
34
+ async function isMcpReachable() {
35
+ try {
36
+ const res = await fetch(MCP_URL, {
37
+ method: "GET",
38
+ signal: AbortSignal.timeout(2500)
39
+ });
40
+ return res.status >= 200 && res.status < 300 || res.status === 401 || res.status === 403;
41
+ } catch {
42
+ return false;
43
+ }
44
+ }
45
+ const muninnMcpCheck = {
46
+ name: CHECK_NAME,
47
+ scope: "global",
48
+ async run() {
49
+ const [reachable, registered] = await Promise.all([
50
+ isMcpReachable(),
51
+ isMuninnRegistered(process.cwd())
52
+ ]);
53
+ if (reachable && registered) {
54
+ return {
55
+ name: CHECK_NAME,
56
+ status: "pass",
57
+ message: "muninn MCP registered and reachable on :8750",
58
+ fixCommand: null,
59
+ details: null
60
+ };
61
+ }
62
+ if (reachable && !registered) {
63
+ return {
64
+ name: CHECK_NAME,
65
+ status: "warning",
66
+ message: "MuninnDB MCP is up but not registered with Claude Code",
67
+ fixCommand: ADD_COMMAND,
68
+ details: [
69
+ "The MCP endpoint on :8750 is reachable, but no `muninn`",
70
+ "server is registered, so the pipeline cannot use memory.",
71
+ "Register it (use the key from `luca vault:init` / .env):",
72
+ ` ${ADD_COMMAND}`
73
+ ].join("\n ")
74
+ };
75
+ }
76
+ if (!reachable && registered) {
77
+ return {
78
+ name: CHECK_NAME,
79
+ status: "warning",
80
+ message: "muninn MCP registered but endpoint unreachable on :8750",
81
+ fixCommand: "luca init",
82
+ details: [
83
+ "A `muninn` server is registered, but nothing is answering",
84
+ "on :8750. Is MuninnDB running? Start it with `luca init`",
85
+ "or `muninn start`, then restart Claude Code."
86
+ ].join("\n ")
87
+ };
88
+ }
89
+ return {
90
+ name: CHECK_NAME,
91
+ status: "warning",
92
+ message: "MuninnDB MCP not running and not registered (optional)",
93
+ fixCommand: ADD_COMMAND,
94
+ details: [
95
+ "MuninnDB provides cross-session memory for the pipeline. It is",
96
+ "optional, but recommended. Start it (`luca init`) and register",
97
+ "the MCP server:",
98
+ ` ${ADD_COMMAND}`
99
+ ].join("\n ")
100
+ };
101
+ }
102
+ };
103
+
104
+ export { muninnMcpCheck };
@@ -1,4 +1,4 @@
1
- import { h as checkMuninndbBinary, d as checkMuninndbService } from '../shared/luca.BYdjkfnz.mjs';
1
+ import { h as checkMuninndbBinary, d as checkMuninndbService } from '../shared/luca.BfjhRHhj.mjs';
2
2
  import 'pathe';
3
3
  import 'node:fs';
4
4
  import 'node:fs/promises';
@@ -1,6 +1,6 @@
1
1
  import { defineCommand } from 'citty';
2
2
  import 'zod';
3
- import '../shared/luca.CRmaAfXR.mjs';
3
+ import '../shared/luca.DXUcpbIe.mjs';
4
4
  import 'node:fs';
5
5
  import 'node:fs/promises';
6
6
  import 'node:path';
@@ -8,13 +8,13 @@ import 'node:crypto';
8
8
  import 'node:module';
9
9
  import 'node:url';
10
10
  import 'node:child_process';
11
- import { r as runWriteHandler, b as lucaPhaseCurrentTool } from '../shared/luca.DjDTeDCi.mjs';
11
+ import { r as runWriteHandler, b as lucaPhaseCurrentTool, c as lucaPhaseAdvanceTool, d as lucaPhaseArchiveTool } from '../shared/luca.DykMxS_D.mjs';
12
12
  import 'node:os';
13
- import '../shared/luca.CrXzXueR.mjs';
14
- import '../shared/luca.HZxBTBgD.mjs';
15
- import '../shared/luca.TSMg1t7I.mjs';
13
+ import '../shared/luca.BH2GZl5z.mjs';
14
+ import '../shared/luca.CuvqWf4b.mjs';
15
+ import '../shared/luca.pqZahLS5.mjs';
16
16
  import '../shared/luca.CQ3g1xrD.mjs';
17
- import '../shared/luca.B3Mimc0P.mjs';
17
+ import '../shared/luca.Djs7oPPj.mjs';
18
18
 
19
19
  const currentCommand = defineCommand({
20
20
  meta: {
@@ -25,13 +25,33 @@ const currentCommand = defineCommand({
25
25
  await runWriteHandler("phase current", lucaPhaseCurrentTool, {});
26
26
  }
27
27
  });
28
+ const advanceCommand = defineCommand({
29
+ meta: {
30
+ name: "advance",
31
+ description: "Advance the active roadmap phase by one (currentPhase \u2192 currentPhase+1), marking the completed phase done and the next in-progress. Call at the phase boundary (learn step) when more phases remain; the final phase routes to the milestone step."
32
+ },
33
+ async run() {
34
+ await runWriteHandler("phase advance", lucaPhaseAdvanceTool, {});
35
+ }
36
+ });
37
+ const archiveCommand = defineCommand({
38
+ meta: {
39
+ name: "archive",
40
+ description: "Archive all active phase directories (.luca/phases/<slug>/ \u2192 .luca/archive/<slug>/) at milestone close, so the next milestone starts from an empty phases/ dir. Idempotent; skips slugs already archived. Allowed only in the milestone/complete steps."
41
+ },
42
+ async run() {
43
+ await runWriteHandler("phase archive", lucaPhaseArchiveTool, {});
44
+ }
45
+ });
28
46
  const phaseCommand = defineCommand({
29
47
  meta: {
30
48
  name: "phase",
31
- description: "Inspect the active Luca workflow phase"
49
+ description: "Inspect, advance, and archive Luca workflow phases"
32
50
  },
33
51
  subCommands: {
34
- current: currentCommand
52
+ current: currentCommand,
53
+ advance: advanceCommand,
54
+ archive: archiveCommand
35
55
  }
36
56
  });
37
57
 
@@ -1,6 +1,6 @@
1
1
  import { defineCommand } from 'citty';
2
2
  import 'zod';
3
- import '../shared/luca.CRmaAfXR.mjs';
3
+ import '../shared/luca.DXUcpbIe.mjs';
4
4
  import 'node:fs';
5
5
  import 'node:fs/promises';
6
6
  import 'node:path';
@@ -8,13 +8,13 @@ import 'node:crypto';
8
8
  import 'node:module';
9
9
  import 'node:url';
10
10
  import 'node:child_process';
11
- import { c as readJsonPayload, r as runWriteHandler, k as lucaPrReviewDetectConvergenceTool, m as lucaPrReviewFilterStaleTool, n as lucaPrReviewRegressionCheckTool } from '../shared/luca.DjDTeDCi.mjs';
11
+ import { e as readJsonPayload, r as runWriteHandler, n as lucaPrReviewDetectConvergenceTool, o as lucaPrReviewFilterStaleTool, p as lucaPrReviewRegressionCheckTool } from '../shared/luca.DykMxS_D.mjs';
12
12
  import 'node:os';
13
- import '../shared/luca.CrXzXueR.mjs';
14
- import '../shared/luca.HZxBTBgD.mjs';
15
- import '../shared/luca.TSMg1t7I.mjs';
13
+ import '../shared/luca.BH2GZl5z.mjs';
14
+ import '../shared/luca.CuvqWf4b.mjs';
15
+ import '../shared/luca.pqZahLS5.mjs';
16
16
  import '../shared/luca.CQ3g1xrD.mjs';
17
- import '../shared/luca.B3Mimc0P.mjs';
17
+ import '../shared/luca.Djs7oPPj.mjs';
18
18
 
19
19
  const filterStaleCommand = defineCommand({
20
20
  meta: {
@@ -1,6 +1,6 @@
1
1
  import { defineCommand } from 'citty';
2
2
  import 'zod';
3
- import '../shared/luca.CRmaAfXR.mjs';
3
+ import '../shared/luca.DXUcpbIe.mjs';
4
4
  import 'node:fs';
5
5
  import 'node:fs/promises';
6
6
  import 'node:path';
@@ -8,13 +8,13 @@ import 'node:crypto';
8
8
  import 'node:module';
9
9
  import 'node:url';
10
10
  import 'node:child_process';
11
- import { c as readJsonPayload, r as runWriteHandler, f as lucaPreferencesReadTool, g as lucaPreferencesWriteTool } from '../shared/luca.DjDTeDCi.mjs';
11
+ import { e as readJsonPayload, r as runWriteHandler, h as lucaPreferencesReadTool, i as lucaPreferencesWriteTool } from '../shared/luca.DykMxS_D.mjs';
12
12
  import 'node:os';
13
- import '../shared/luca.CrXzXueR.mjs';
14
- import '../shared/luca.HZxBTBgD.mjs';
15
- import '../shared/luca.TSMg1t7I.mjs';
13
+ import '../shared/luca.BH2GZl5z.mjs';
14
+ import '../shared/luca.CuvqWf4b.mjs';
15
+ import '../shared/luca.pqZahLS5.mjs';
16
16
  import '../shared/luca.CQ3g1xrD.mjs';
17
- import '../shared/luca.B3Mimc0P.mjs';
17
+ import '../shared/luca.Djs7oPPj.mjs';
18
18
 
19
19
  const readCommand = defineCommand({
20
20
  meta: {
@@ -2,7 +2,7 @@ import { defineCommand } from 'citty';
2
2
  import { existsSync } from 'node:fs';
3
3
  import { readFile, rm } from 'node:fs/promises';
4
4
  import { join } from 'node:path';
5
- import { l as lucaStateSchema } from '../shared/luca.CRmaAfXR.mjs';
5
+ import { l as lucaStateSchema } from '../shared/luca.DXUcpbIe.mjs';
6
6
  import 'node:crypto';
7
7
  import 'node:module';
8
8
  import 'node:url';
@@ -1,6 +1,6 @@
1
1
  import { defineCommand } from 'citty';
2
2
  import 'zod';
3
- import '../shared/luca.CRmaAfXR.mjs';
3
+ import '../shared/luca.DXUcpbIe.mjs';
4
4
  import 'node:fs';
5
5
  import 'node:fs/promises';
6
6
  import 'node:path';
@@ -8,13 +8,13 @@ import 'node:crypto';
8
8
  import 'node:module';
9
9
  import 'node:url';
10
10
  import 'node:child_process';
11
- import { c as readJsonPayload, r as runWriteHandler, o as lucaRepoCleanupApplyTool } from '../shared/luca.DjDTeDCi.mjs';
11
+ import { e as readJsonPayload, r as runWriteHandler, q as lucaRepoCleanupApplyTool } from '../shared/luca.DykMxS_D.mjs';
12
12
  import 'node:os';
13
- import '../shared/luca.CrXzXueR.mjs';
14
- import '../shared/luca.HZxBTBgD.mjs';
15
- import '../shared/luca.TSMg1t7I.mjs';
13
+ import '../shared/luca.BH2GZl5z.mjs';
14
+ import '../shared/luca.CuvqWf4b.mjs';
15
+ import '../shared/luca.pqZahLS5.mjs';
16
16
  import '../shared/luca.CQ3g1xrD.mjs';
17
- import '../shared/luca.B3Mimc0P.mjs';
17
+ import '../shared/luca.Djs7oPPj.mjs';
18
18
 
19
19
  const cleanupApplyCommand = defineCommand({
20
20
  meta: {
@@ -1,5 +1,5 @@
1
1
  import { defineCommand } from 'citty';
2
- import '../shared/luca.CRmaAfXR.mjs';
2
+ import '../shared/luca.DXUcpbIe.mjs';
3
3
  import 'node:fs';
4
4
  import 'node:fs/promises';
5
5
  import 'node:path';
@@ -7,13 +7,13 @@ import 'node:crypto';
7
7
  import 'node:module';
8
8
  import 'node:url';
9
9
  import 'node:child_process';
10
- import { a as analyzeRun, g as gatherRunArtifacts, r as renderPostmortemMarkdown, c as computePostmortemExitCode } from '../shared/luca.C4gMUoBd.mjs';
11
- import { l as listRuns } from '../shared/luca.HZxBTBgD.mjs';
10
+ import { a as analyzeRun, g as gatherRunArtifacts, r as renderPostmortemMarkdown, c as computePostmortemExitCode } from '../shared/luca.BhM9TDAo.mjs';
11
+ import { l as listRuns } from '../shared/luca.CuvqWf4b.mjs';
12
12
  import { l as logger } from '../shared/luca.dM-MKlNE.mjs';
13
13
  import 'zod';
14
14
  import 'node:os';
15
- import '../shared/luca.BmhNkYe2.mjs';
16
- import '../shared/luca.TSMg1t7I.mjs';
15
+ import '../shared/luca.BQXFn5yo.mjs';
16
+ import '../shared/luca.pqZahLS5.mjs';
17
17
  import 'pathe';
18
18
  import 'consola';
19
19
 
@@ -1,6 +1,6 @@
1
1
  import { defineCommand } from 'citty';
2
2
  import 'zod';
3
- import '../shared/luca.CRmaAfXR.mjs';
3
+ import '../shared/luca.DXUcpbIe.mjs';
4
4
  import 'node:fs';
5
5
  import 'node:fs/promises';
6
6
  import 'node:path';
@@ -8,13 +8,13 @@ import 'node:crypto';
8
8
  import 'node:module';
9
9
  import 'node:url';
10
10
  import 'node:child_process';
11
- import { c as readJsonPayload, r as runWriteHandler, d as lucaRoadmapReadTool, e as lucaRoadmapCreateTool } from '../shared/luca.DjDTeDCi.mjs';
11
+ import { e as readJsonPayload, r as runWriteHandler, f as lucaRoadmapReadTool, g as lucaRoadmapCreateTool } from '../shared/luca.DykMxS_D.mjs';
12
12
  import 'node:os';
13
- import '../shared/luca.CrXzXueR.mjs';
14
- import '../shared/luca.HZxBTBgD.mjs';
15
- import '../shared/luca.TSMg1t7I.mjs';
13
+ import '../shared/luca.BH2GZl5z.mjs';
14
+ import '../shared/luca.CuvqWf4b.mjs';
15
+ import '../shared/luca.pqZahLS5.mjs';
16
16
  import '../shared/luca.CQ3g1xrD.mjs';
17
- import '../shared/luca.B3Mimc0P.mjs';
17
+ import '../shared/luca.Djs7oPPj.mjs';
18
18
 
19
19
  const readCommand = defineCommand({
20
20
  meta: {
@@ -1,6 +1,6 @@
1
1
  import { defineCommand } from 'citty';
2
2
  import { join as join$1 } from 'pathe';
3
- import '../shared/luca.CRmaAfXR.mjs';
3
+ import '../shared/luca.DXUcpbIe.mjs';
4
4
  import { existsSync, readdirSync, statSync, readFileSync } from 'node:fs';
5
5
  import 'node:fs/promises';
6
6
  import { isAbsolute, resolve, join, extname } from 'node:path';
@@ -8,13 +8,13 @@ import 'node:crypto';
8
8
  import { createRequire } from 'node:module';
9
9
  import { pathToFileURL } from 'node:url';
10
10
  import 'node:child_process';
11
- import { a as analyzeRun, g as gatherRunArtifacts } from '../shared/luca.C4gMUoBd.mjs';
12
- import { l as listRuns } from '../shared/luca.HZxBTBgD.mjs';
11
+ import { a as analyzeRun, g as gatherRunArtifacts } from '../shared/luca.BhM9TDAo.mjs';
12
+ import { l as listRuns } from '../shared/luca.CuvqWf4b.mjs';
13
13
  import { l as logger } from '../shared/luca.dM-MKlNE.mjs';
14
14
  import 'zod';
15
15
  import 'node:os';
16
- import '../shared/luca.BmhNkYe2.mjs';
17
- import '../shared/luca.TSMg1t7I.mjs';
16
+ import '../shared/luca.BQXFn5yo.mjs';
17
+ import '../shared/luca.pqZahLS5.mjs';
18
18
  import 'consola';
19
19
 
20
20
  let tsModuleCache = void 0;