@alecsibilia/luca 13.0.0-alpha.1

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 (128) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +47 -0
  3. package/bin/luca.js +3 -0
  4. package/dist/chunks/branch.mjs +47 -0
  5. package/dist/chunks/bun-runtime.mjs +46 -0
  6. package/dist/chunks/checks.mjs +53 -0
  7. package/dist/chunks/claim-verify.mjs +465 -0
  8. package/dist/chunks/classify.mjs +105 -0
  9. package/dist/chunks/confidence.mjs +199 -0
  10. package/dist/chunks/doctor.mjs +158 -0
  11. package/dist/chunks/hook.mjs +696 -0
  12. package/dist/chunks/init.mjs +715 -0
  13. package/dist/chunks/muninndb-health.mjs +66 -0
  14. package/dist/chunks/phase.mjs +38 -0
  15. package/dist/chunks/pr-review.mjs +122 -0
  16. package/dist/chunks/preferences.mjs +61 -0
  17. package/dist/chunks/repair.mjs +111 -0
  18. package/dist/chunks/repo.mjs +58 -0
  19. package/dist/chunks/retro.mjs +86 -0
  20. package/dist/chunks/roadmap.mjs +58 -0
  21. package/dist/chunks/rules.mjs +527 -0
  22. package/dist/chunks/stale-mcp-server.mjs +90 -0
  23. package/dist/chunks/state.mjs +57 -0
  24. package/dist/chunks/stray-local-install.mjs +200 -0
  25. package/dist/chunks/telemetry.mjs +165 -0
  26. package/dist/chunks/todo.mjs +151 -0
  27. package/dist/chunks/vault-init.mjs +300 -0
  28. package/dist/chunks/verification.mjs +95 -0
  29. package/dist/chunks/version.mjs +70 -0
  30. package/dist/chunks/workflow.mjs +47 -0
  31. package/dist/claude/.claude/agents/architect.md +410 -0
  32. package/dist/claude/.claude/agents/build.md +111 -0
  33. package/dist/claude/.claude/agents/discuss.md +93 -0
  34. package/dist/claude/.claude/agents/discussion.md +149 -0
  35. package/dist/claude/.claude/agents/execute.md +416 -0
  36. package/dist/claude/.claude/agents/executor.md +161 -0
  37. package/dist/claude/.claude/agents/fast.md +84 -0
  38. package/dist/claude/.claude/agents/finalize.md +484 -0
  39. package/dist/claude/.claude/agents/learner.md +160 -0
  40. package/dist/claude/.claude/agents/plan-reviewer.md +129 -0
  41. package/dist/claude/.claude/agents/plan.md +96 -0
  42. package/dist/claude/.claude/agents/research.md +327 -0
  43. package/dist/claude/.claude/agents/researcher.md +78 -0
  44. package/dist/claude/.claude/agents/review.md +283 -0
  45. package/dist/claude/.claude/agents/reviewer.md +163 -0
  46. package/dist/claude/.claude/agents/shadow-scanner.md +257 -0
  47. package/dist/claude/.claude/agents/triage.md +230 -0
  48. package/dist/claude/.claude/agents/verifier.md +131 -0
  49. package/dist/claude/.claude/commands/bug-diagnose.md +12 -0
  50. package/dist/claude/.claude/commands/gh-issue-triage.md +14 -0
  51. package/dist/claude/.claude/commands/gh-pr-address.md +235 -0
  52. package/dist/claude/.claude/commands/gh-prepare.md +12 -0
  53. package/dist/claude/.claude/commands/grill-me.md +12 -0
  54. package/dist/claude/.claude/commands/lu-review.md +51 -0
  55. package/dist/claude/.claude/commands/lu.md +75 -0
  56. package/dist/claude/.claude/commands/luca-init.md +14 -0
  57. package/dist/claude/.claude/commands/luca-telemetry-report.md +12 -0
  58. package/dist/claude/.claude/commands/memory-audit.md +12 -0
  59. package/dist/claude/.claude/commands/milestone-new.md +122 -0
  60. package/dist/claude/.claude/commands/phase-discuss.md +45 -0
  61. package/dist/claude/.claude/commands/phase-execute.md +39 -0
  62. package/dist/claude/.claude/commands/phase-plan.md +53 -0
  63. package/dist/claude/.claude/commands/repo-cleanup.md +80 -0
  64. package/dist/claude/.claude/commands/todo-add.md +28 -0
  65. package/dist/claude/.claude/commands/todo-check.md +36 -0
  66. package/dist/claude/.claude/hooks/context-refresher.ts +285 -0
  67. package/dist/claude/.claude/hooks/continuation-messages.ts +215 -0
  68. package/dist/claude/.claude/hooks/pipeline-guard.ts +182 -0
  69. package/dist/claude/.claude/settings.json +41 -0
  70. package/dist/claude/skills/arch-audit/SKILL.md +161 -0
  71. package/dist/claude/skills/autopilot/SKILL.md +1299 -0
  72. package/dist/claude/skills/bug-diagnose/SKILL.md +102 -0
  73. package/dist/claude/skills/choose/SKILL.md +124 -0
  74. package/dist/claude/skills/gh-issue-triage/SKILL.md +97 -0
  75. package/dist/claude/skills/gh-pr-address/SKILL.md +235 -0
  76. package/dist/claude/skills/gh-prepare/SKILL.md +209 -0
  77. package/dist/claude/skills/grill-me/SKILL.md +46 -0
  78. package/dist/claude/skills/lu/SKILL.md +112 -0
  79. package/dist/claude/skills/lu-review/SKILL.md +51 -0
  80. package/dist/claude/skills/luca-init/SKILL.md +91 -0
  81. package/dist/claude/skills/luca-telemetry-report/SKILL.md +145 -0
  82. package/dist/claude/skills/luca-write-surface/SKILL.md +213 -0
  83. package/dist/claude/skills/memory-audit/SKILL.md +217 -0
  84. package/dist/claude/skills/milestone-audit/SKILL.md +545 -0
  85. package/dist/claude/skills/milestone-complete/SKILL.md +168 -0
  86. package/dist/claude/skills/milestone-gaps/SKILL.md +60 -0
  87. package/dist/claude/skills/milestone-new/SKILL.md +125 -0
  88. package/dist/claude/skills/note/SKILL.md +162 -0
  89. package/dist/claude/skills/phase-add/SKILL.md +91 -0
  90. package/dist/claude/skills/phase-assumptions/SKILL.md +92 -0
  91. package/dist/claude/skills/phase-discuss/SKILL.md +165 -0
  92. package/dist/claude/skills/phase-execute/SKILL.md +1786 -0
  93. package/dist/claude/skills/phase-insert/SKILL.md +100 -0
  94. package/dist/claude/skills/phase-plan/SKILL.md +461 -0
  95. package/dist/claude/skills/phase-remove/SKILL.md +113 -0
  96. package/dist/claude/skills/phase-research/SKILL.md +80 -0
  97. package/dist/claude/skills/post-init-tour/SKILL.md +58 -0
  98. package/dist/claude/skills/progress/SKILL.md +271 -0
  99. package/dist/claude/skills/project-new/SKILL.md +609 -0
  100. package/dist/claude/skills/quick/SKILL.md +256 -0
  101. package/dist/claude/skills/rename-audit/SKILL.md +52 -0
  102. package/dist/claude/skills/repo-audit/SKILL.md +88 -0
  103. package/dist/claude/skills/repo-cleanup/SKILL.md +80 -0
  104. package/dist/claude/skills/seed-memory/SKILL.md +235 -0
  105. package/dist/claude/skills/session-pause/SKILL.md +126 -0
  106. package/dist/claude/skills/session-plan/SKILL.md +112 -0
  107. package/dist/claude/skills/session-resume/SKILL.md +75 -0
  108. package/dist/claude/skills/todo-add/SKILL.md +85 -0
  109. package/dist/claude/skills/todo-check/SKILL.md +77 -0
  110. package/dist/claude/skills/workflow-save/SKILL.md +277 -0
  111. package/dist/index.d.mts +33 -0
  112. package/dist/index.d.ts +33 -0
  113. package/dist/index.mjs +69 -0
  114. package/dist/shared/luca.B3Mimc0P.mjs +52 -0
  115. package/dist/shared/luca.B3saVjJm.mjs +163 -0
  116. package/dist/shared/luca.BYdjkfnz.mjs +217 -0
  117. package/dist/shared/luca.BmhNkYe2.mjs +56 -0
  118. package/dist/shared/luca.C4gMUoBd.mjs +358 -0
  119. package/dist/shared/luca.CQ3g1xrD.mjs +19 -0
  120. package/dist/shared/luca.CRmaAfXR.mjs +713 -0
  121. package/dist/shared/luca.CrXzXueR.mjs +57 -0
  122. package/dist/shared/luca.DTomPq7I.mjs +91 -0
  123. package/dist/shared/luca.DjDTeDCi.mjs +1904 -0
  124. package/dist/shared/luca.HZxBTBgD.mjs +201 -0
  125. package/dist/shared/luca.TSMg1t7I.mjs +10 -0
  126. package/dist/shared/luca.dM-MKlNE.mjs +25 -0
  127. package/dist/shared/luca.naWEcQ4B.mjs +7 -0
  128. package/package.json +76 -0
@@ -0,0 +1,163 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { mkdir, readdir, copyFile } from 'node:fs/promises';
3
+ import { homedir } from 'node:os';
4
+ import { join, dirname } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ function defaultClaudeHome() {
8
+ return join(homedir(), ".claude");
9
+ }
10
+ async function installSkills(opts) {
11
+ const log = opts.log ?? (() => {
12
+ });
13
+ const claudeHome = opts.claudeHome ?? defaultClaudeHome();
14
+ const resolved = resolveBundledArtifacts({
15
+ claudeArtifactsRoot: opts.claudeArtifactsRoot,
16
+ skillsRoot: opts.skillsRoot
17
+ });
18
+ if (resolved === null) {
19
+ log(
20
+ " skip: bundled artifacts not found \u2014 could not locate the @alecsibilia/luca package root (running from a non-bundled dev tree?)"
21
+ );
22
+ return;
23
+ }
24
+ const { claudeArtifactsRoot, skillsRoot } = resolved;
25
+ if (!existsSync(claudeArtifactsRoot)) {
26
+ log(
27
+ ` skip: bundled artifacts not found at ${claudeArtifactsRoot} (running from a non-bundled dev tree? did the umbrella build run?)`
28
+ );
29
+ return;
30
+ }
31
+ await copyDir({
32
+ from: join(claudeArtifactsRoot, "commands"),
33
+ to: join(claudeHome, "commands"),
34
+ log,
35
+ label: "command"
36
+ });
37
+ await copyDir({
38
+ from: join(claudeArtifactsRoot, "agents"),
39
+ to: join(claudeHome, "agents"),
40
+ log,
41
+ label: "agent"
42
+ });
43
+ await copySkillTree({
44
+ from: skillsRoot,
45
+ to: join(claudeHome, "skills"),
46
+ log
47
+ });
48
+ }
49
+ async function listBundledArtifacts(opts = {}) {
50
+ const resolved = resolveBundledArtifacts({
51
+ claudeArtifactsRoot: opts.claudeArtifactsRoot,
52
+ skillsRoot: opts.skillsRoot
53
+ });
54
+ if (resolved === null) return null;
55
+ const { claudeArtifactsRoot, skillsRoot } = resolved;
56
+ if (!existsSync(claudeArtifactsRoot)) return null;
57
+ return {
58
+ commands: await listEntries(
59
+ join(claudeArtifactsRoot, "commands"),
60
+ "file",
61
+ ".md"
62
+ ),
63
+ agents: await listEntries(
64
+ join(claudeArtifactsRoot, "agents"),
65
+ "file",
66
+ ".md"
67
+ ),
68
+ skills: await listEntries(skillsRoot, "dir")
69
+ };
70
+ }
71
+ function resolveBundledArtifacts(overrides) {
72
+ if (overrides.claudeArtifactsRoot !== void 0 && overrides.skillsRoot !== void 0) {
73
+ return {
74
+ claudeArtifactsRoot: overrides.claudeArtifactsRoot,
75
+ skillsRoot: overrides.skillsRoot
76
+ };
77
+ }
78
+ const distClaude = findUmbrellaDistClaude();
79
+ if (distClaude === null) return null;
80
+ return {
81
+ claudeArtifactsRoot: overrides.claudeArtifactsRoot ?? join(distClaude, ".claude"),
82
+ skillsRoot: overrides.skillsRoot ?? join(distClaude, "skills")
83
+ };
84
+ }
85
+ function findUmbrellaDistClaude() {
86
+ let dir = dirname(fileURLToPath(import.meta.url));
87
+ for (let i = 0; i < 20; i += 1) {
88
+ const pkgPath = join(dir, "package.json");
89
+ if (existsSync(pkgPath)) {
90
+ try {
91
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
92
+ if (pkg.name === "@alecsibilia/luca") {
93
+ return join(dir, "dist", "claude");
94
+ }
95
+ } catch {
96
+ }
97
+ }
98
+ const parent = dirname(dir);
99
+ if (parent === dir) break;
100
+ dir = parent;
101
+ }
102
+ dir = dirname(fileURLToPath(import.meta.url));
103
+ for (let i = 0; i < 20; i += 1) {
104
+ const candidate = join(dir, "packages", "luca", "package.json");
105
+ if (existsSync(candidate)) {
106
+ try {
107
+ const pkg = JSON.parse(readFileSync(candidate, "utf-8"));
108
+ if (pkg.name === "@alecsibilia/luca") {
109
+ return join(dir, "packages", "luca", "dist", "claude");
110
+ }
111
+ } catch {
112
+ }
113
+ }
114
+ const parent = dirname(dir);
115
+ if (parent === dir) break;
116
+ dir = parent;
117
+ }
118
+ return null;
119
+ }
120
+ function resolveBundledArtifactsForHooks() {
121
+ const distClaude = findUmbrellaDistClaude();
122
+ if (distClaude === null) return null;
123
+ return join(distClaude, ".claude");
124
+ }
125
+ async function listEntries(dir, kind, ext) {
126
+ if (!existsSync(dir)) return [];
127
+ const entries = await readdir(dir, { withFileTypes: true });
128
+ return entries.filter((e) => kind === "file" ? e.isFile() : e.isDirectory()).filter((e) => ext ? e.name.endsWith(ext) : true).map((e) => e.name);
129
+ }
130
+ async function copySkillTree(args) {
131
+ if (!existsSync(args.from)) {
132
+ args.log(` skip: skills source missing (${args.from})`);
133
+ return;
134
+ }
135
+ const entries = await readdir(args.from, { withFileTypes: true });
136
+ for (const entry of entries) {
137
+ if (!entry.isDirectory()) continue;
138
+ const skillFrom = join(args.from, entry.name);
139
+ const skillTo = join(args.to, entry.name);
140
+ await mkdir(skillTo, { recursive: true });
141
+ const files = await readdir(skillFrom, { withFileTypes: true });
142
+ for (const file of files) {
143
+ if (!file.isFile()) continue;
144
+ await copyFile(join(skillFrom, file.name), join(skillTo, file.name));
145
+ args.log(` write: ${join(skillTo, file.name)}`);
146
+ }
147
+ }
148
+ }
149
+ async function copyDir(args) {
150
+ if (!existsSync(args.from)) {
151
+ args.log(` skip: ${args.label}s source missing (${args.from})`);
152
+ return;
153
+ }
154
+ await mkdir(args.to, { recursive: true });
155
+ const entries = await readdir(args.from, { withFileTypes: true });
156
+ for (const entry of entries) {
157
+ if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
158
+ await copyFile(join(args.from, entry.name), join(args.to, entry.name));
159
+ args.log(` write: ${join(args.to, entry.name)}`);
160
+ }
161
+ }
162
+
163
+ export { defaultClaudeHome as d, installSkills as i, listBundledArtifacts as l, resolveBundledArtifactsForHooks as r };
@@ -0,0 +1,217 @@
1
+ import { join } from 'pathe';
2
+ import { existsSync } from 'node:fs';
3
+ import { mkdir } from 'node:fs/promises';
4
+ import { homedir } from 'node:os';
5
+ import { z } from 'zod';
6
+ import { a as checkPlatform } from './luca.DTomPq7I.mjs';
7
+
8
+ const LucaHomePathsSchema = z.object({
9
+ /** Absolute path to the root ~/.luca/ directory. */
10
+ root: z.string(),
11
+ /** Absolute path to the ~/.luca/bin/ directory for executables. */
12
+ bin: z.string()
13
+ });
14
+ function getLucaHomePaths() {
15
+ const home = homedir();
16
+ const root = join(home, ".luca");
17
+ const paths = {
18
+ root,
19
+ bin: join(root, "bin")
20
+ };
21
+ return LucaHomePathsSchema.parse(paths);
22
+ }
23
+ async function ensureLucaHome() {
24
+ const paths = getLucaHomePaths();
25
+ const dirs = [paths.root, paths.bin];
26
+ for (const dir of dirs) {
27
+ if (!existsSync(dir)) {
28
+ await mkdir(dir, { recursive: true });
29
+ }
30
+ }
31
+ return paths;
32
+ }
33
+
34
+ const SUPPORTED_PLATFORM_TARGETS = [
35
+ "darwin-arm64",
36
+ "darwin-x64",
37
+ "linux-x64",
38
+ "linux-arm64"
39
+ ];
40
+ z.enum(SUPPORTED_PLATFORM_TARGETS);
41
+ const MuninndbBinaryStatusSchema = z.object({
42
+ /** Whether the MuninnDB binary file exists on disk. */
43
+ installed: z.boolean(),
44
+ /** Absolute path to the binary, or null if not found. */
45
+ path: z.string().nullable(),
46
+ /** Version string reported by the binary, or null if unknown. */
47
+ version: z.string().nullable(),
48
+ /** Whether the binary has executable permissions. */
49
+ executable: z.boolean()
50
+ });
51
+ const MuninndbServiceStatusSchema = z.object({
52
+ /** Whether the MuninnDB process appears to be running. */
53
+ running: z.boolean(),
54
+ /** Port number the service listens on. */
55
+ port: z.number(),
56
+ /** Process ID from the pidfile, or null if unavailable. */
57
+ pid: z.number().nullable(),
58
+ /** Whether the service responds to HTTP health checks. */
59
+ healthy: z.boolean()
60
+ });
61
+ const MuninndbInstallResultSchema = z.object({
62
+ /** Whether the download and installation succeeded. */
63
+ success: z.boolean(),
64
+ /** Absolute path to the installed binary, or null on failure. */
65
+ binaryPath: z.string().nullable(),
66
+ /** Error message describing the failure, or null on success. */
67
+ error: z.string().nullable()
68
+ });
69
+ const PLATFORM_TARGET_MAP = {
70
+ "darwin-arm64": "darwin-arm64",
71
+ "darwin-x64": "darwin-x64",
72
+ "linux-x64": "linux-x64",
73
+ "linux-arm64": "linux-arm64"
74
+ };
75
+ function resolvePlatformTarget() {
76
+ const platform = checkPlatform();
77
+ const key = `${platform.os}-${platform.arch}`;
78
+ const target = PLATFORM_TARGET_MAP[key];
79
+ if (!target) {
80
+ return {
81
+ success: false,
82
+ error: `Unsupported platform: ${platform.os}/${platform.arch}. MuninnDB supports: ${SUPPORTED_PLATFORM_TARGETS.join(", ")}`
83
+ };
84
+ }
85
+ return { success: true, target };
86
+ }
87
+ const MUNINNDB_DEFAULT_PORT = 8476;
88
+ const MUNINNDB_BINARY_NAME = "muninn";
89
+ function getCommonBinaryPaths() {
90
+ const home = process.env.HOME;
91
+ return [
92
+ ...home ? [
93
+ join(home, ".local", "bin", MUNINNDB_BINARY_NAME),
94
+ join(home, "bin", MUNINNDB_BINARY_NAME),
95
+ join(home, ".muninndb", "bin", MUNINNDB_BINARY_NAME),
96
+ join(home, ".muninndb", MUNINNDB_BINARY_NAME),
97
+ join(home, ".muninn", "bin", MUNINNDB_BINARY_NAME),
98
+ join(home, ".cargo", "bin", MUNINNDB_BINARY_NAME)
99
+ ] : [],
100
+ join("/usr", "local", "bin", MUNINNDB_BINARY_NAME)
101
+ ];
102
+ }
103
+ function resolveMuninndbPort(port) {
104
+ if (port !== void 0) return port;
105
+ if (process.env.MUNINNDB_PORT) {
106
+ const parsed = parseInt(process.env.MUNINNDB_PORT, 10);
107
+ if (!isNaN(parsed)) return parsed;
108
+ }
109
+ return MUNINNDB_DEFAULT_PORT;
110
+ }
111
+
112
+ async function checkMuninndbBinary(binaryPath) {
113
+ const preferredPath = join(getLucaHomePaths().bin, MUNINNDB_BINARY_NAME);
114
+ let resolvedPath = preferredPath;
115
+ const exists = await Bun.file(resolvedPath).exists();
116
+ if (!exists) {
117
+ const candidates = getCommonBinaryPaths();
118
+ let found = false;
119
+ for (const candidate of candidates) {
120
+ if (await Bun.file(candidate).exists()) {
121
+ resolvedPath = candidate;
122
+ found = true;
123
+ break;
124
+ }
125
+ }
126
+ if (!found) {
127
+ const whichResult = Bun.which(MUNINNDB_BINARY_NAME);
128
+ if (whichResult && await Bun.file(whichResult).exists()) {
129
+ resolvedPath = whichResult;
130
+ found = true;
131
+ }
132
+ }
133
+ if (!found) {
134
+ return MuninndbBinaryStatusSchema.parse({
135
+ installed: false,
136
+ path: null,
137
+ version: null,
138
+ executable: false
139
+ });
140
+ }
141
+ }
142
+ let executable = false;
143
+ try {
144
+ const result = await Bun.$`test -x ${resolvedPath}`.quiet().nothrow();
145
+ executable = result.exitCode === 0;
146
+ } catch {
147
+ executable = false;
148
+ }
149
+ let version = null;
150
+ try {
151
+ const result = await Bun.$`${resolvedPath} --version`.quiet().nothrow();
152
+ if (result.exitCode === 0) {
153
+ version = result.stdout.toString().trim() || null;
154
+ }
155
+ } catch {
156
+ }
157
+ return MuninndbBinaryStatusSchema.parse({
158
+ installed: true,
159
+ path: resolvedPath,
160
+ version,
161
+ executable
162
+ });
163
+ }
164
+ async function checkMuninndbService(port) {
165
+ const resolvedPort = resolveMuninndbPort(port);
166
+ let pid = null;
167
+ try {
168
+ const pidfilePath = join(getLucaHomePaths().root, "muninndb.pid");
169
+ const pidfileExists = await Bun.file(pidfilePath).exists();
170
+ if (pidfileExists) {
171
+ const pidStr = await Bun.file(pidfilePath).text();
172
+ const parsed = parseInt(pidStr.trim(), 10);
173
+ if (!isNaN(parsed) && parsed > 0) {
174
+ pid = parsed;
175
+ }
176
+ }
177
+ } catch {
178
+ }
179
+ let healthy = false;
180
+ let running = false;
181
+ try {
182
+ const controller = new AbortController();
183
+ const timeout = setTimeout(() => controller.abort(), 3e3);
184
+ const response = await fetch(
185
+ `http://localhost:${resolvedPort}/health`,
186
+ {
187
+ signal: controller.signal
188
+ }
189
+ );
190
+ clearTimeout(timeout);
191
+ healthy = response.ok;
192
+ running = true;
193
+ } catch {
194
+ healthy = false;
195
+ running = false;
196
+ }
197
+ return MuninndbServiceStatusSchema.parse({
198
+ running,
199
+ port: resolvedPort,
200
+ pid,
201
+ healthy
202
+ });
203
+ }
204
+ async function waitForMuninndbHealthy(options = {}) {
205
+ const { port, timeoutMs = 1e4, intervalMs = 500 } = options;
206
+ const deadline = Date.now() + timeoutMs;
207
+ while (Date.now() < deadline) {
208
+ const status = await checkMuninndbService(port);
209
+ if (status.healthy) {
210
+ return status;
211
+ }
212
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
213
+ }
214
+ return checkMuninndbService(port);
215
+ }
216
+
217
+ export { MuninndbInstallResultSchema as M, MUNINNDB_BINARY_NAME as a, getCommonBinaryPaths as b, resolveMuninndbPort as c, checkMuninndbService as d, MuninndbServiceStatusSchema as e, ensureLucaHome as f, getLucaHomePaths as g, checkMuninndbBinary as h, MUNINNDB_DEFAULT_PORT as i, resolvePlatformTarget as r, waitForMuninndbHealthy as w };
@@ -0,0 +1,56 @@
1
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { u as VerificationResultSchema, v as PHASE_SLUG_RE } from './luca.CRmaAfXR.mjs';
4
+ import { p as phasePathFor } from './luca.TSMg1t7I.mjs';
5
+ import { join as join$1 } from 'pathe';
6
+ import 'node:fs/promises';
7
+ import 'node:crypto';
8
+ import 'node:module';
9
+ import 'node:url';
10
+ import 'node:child_process';
11
+
12
+ function readVerificationResult(opts) {
13
+ const p = join(opts.cwd, phasePathFor(opts.slug, "verify"));
14
+ if (!existsSync(p)) return null;
15
+ try {
16
+ const parsed = VerificationResultSchema.safeParse(
17
+ JSON.parse(readFileSync(p, "utf-8"))
18
+ );
19
+ if (!parsed.success) return null;
20
+ const result = parsed.data;
21
+ if (opts.currentRunId && typeof result.runId === "string" && result.runId.length > 0 && result.runId !== opts.currentRunId) {
22
+ return null;
23
+ }
24
+ return result;
25
+ } catch {
26
+ return null;
27
+ }
28
+ }
29
+ function aggregateVerificationResults(results) {
30
+ const latest = results[results.length - 1];
31
+ const blockingGaps = latest ? latest.criteria.filter((c) => !c.met && c.blocking).map((c) => ({
32
+ criterionId: c.criterionId,
33
+ gap: c.gap ?? "Unknown",
34
+ wave: latest.wave
35
+ })) : [];
36
+ return {
37
+ totalWaves: results.length,
38
+ passCount: results.filter((r) => r.status === "PASS").length,
39
+ failCount: results.filter((r) => r.status === "FAIL").length,
40
+ stalledCount: results.filter((r) => r.status === "STALLED").length,
41
+ allCriteriaMet: latest ? latest.criteria.filter((c) => c.blocking).every((c) => c.met) : false,
42
+ blockingGaps
43
+ };
44
+ }
45
+
46
+ function listPhaseSlugs(cwd) {
47
+ const phasesDir = join$1(cwd, ".luca", "phases");
48
+ if (!existsSync(phasesDir)) return [];
49
+ try {
50
+ return readdirSync(phasesDir, { withFileTypes: true }).filter((e) => e.isDirectory() && PHASE_SLUG_RE.test(e.name)).map((e) => e.name);
51
+ } catch {
52
+ return [];
53
+ }
54
+ }
55
+
56
+ export { aggregateVerificationResults as a, listPhaseSlugs as l, readVerificationResult as r };