@alecsibilia/luca 13.0.0-alpha.2 → 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.
- package/dist/chunks/branch.mjs +6 -6
- package/dist/chunks/checks.mjs +6 -6
- package/dist/chunks/claim-verify.mjs +1 -1
- package/dist/chunks/classify.mjs +1 -1
- package/dist/chunks/confidence.mjs +6 -6
- package/dist/chunks/hook.mjs +27 -9
- package/dist/chunks/init.mjs +1 -1
- package/dist/chunks/phase.mjs +28 -8
- package/dist/chunks/pr-review.mjs +6 -6
- package/dist/chunks/preferences.mjs +6 -6
- package/dist/chunks/repair.mjs +1 -1
- package/dist/chunks/repo.mjs +6 -6
- package/dist/chunks/retro.mjs +5 -5
- package/dist/chunks/roadmap.mjs +6 -6
- package/dist/chunks/rules.mjs +5 -5
- package/dist/chunks/state.mjs +6 -6
- package/dist/chunks/stray-local-install.mjs +1 -1
- package/dist/chunks/telemetry.mjs +1 -1
- package/dist/chunks/todo.mjs +6 -6
- package/dist/chunks/vault-init.mjs +1 -1
- package/dist/chunks/verification.mjs +4 -4
- package/dist/chunks/workflow.mjs +6 -6
- package/dist/claude/skills/caveman/SKILL.md +58 -0
- package/dist/claude/skills/lu/SKILL.md +1 -1
- package/dist/claude/skills/milestone-complete/SKILL.md +8 -1
- package/dist/index.mjs +1 -1
- package/dist/shared/{luca.CrXzXueR.mjs → luca.BH2GZl5z.mjs} +1 -1
- package/dist/shared/{luca.BmhNkYe2.mjs → luca.BQXFn5yo.mjs} +2 -2
- package/dist/shared/{luca.C4gMUoBd.mjs → luca.BhM9TDAo.mjs} +3 -3
- package/dist/shared/{luca.HZxBTBgD.mjs → luca.CuvqWf4b.mjs} +2 -2
- package/dist/shared/{luca.CRmaAfXR.mjs → luca.DXUcpbIe.mjs} +5 -4
- package/dist/shared/{luca.B3Mimc0P.mjs → luca.Djs7oPPj.mjs} +5 -0
- package/dist/shared/{luca.DjDTeDCi.mjs → luca.DykMxS_D.mjs} +125 -16
- package/dist/shared/{luca.TSMg1t7I.mjs → luca.pqZahLS5.mjs} +1 -1
- package/package.json +1 -1
package/dist/chunks/branch.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineCommand } from 'citty';
|
|
2
2
|
import 'zod';
|
|
3
|
-
import '../shared/luca.
|
|
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,
|
|
11
|
+
import { r as runWriteHandler, t as lucaBranchGuardTool } from '../shared/luca.DykMxS_D.mjs';
|
|
12
12
|
import 'node:os';
|
|
13
|
-
import '../shared/luca.
|
|
14
|
-
import '../shared/luca.
|
|
15
|
-
import '../shared/luca.
|
|
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.
|
|
17
|
+
import '../shared/luca.Djs7oPPj.mjs';
|
|
18
18
|
|
|
19
19
|
const guardCommand = defineCommand({
|
|
20
20
|
meta: {
|
package/dist/chunks/checks.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineCommand } from 'citty';
|
|
2
2
|
import 'zod';
|
|
3
|
-
import '../shared/luca.
|
|
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 {
|
|
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.
|
|
14
|
-
import '../shared/luca.
|
|
15
|
-
import '../shared/luca.
|
|
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.
|
|
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.
|
|
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';
|
package/dist/chunks/classify.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineCommand } from 'citty';
|
|
2
|
-
import { C as ClassifyComplexityInputSchema } from '../shared/luca.
|
|
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.
|
|
3
|
-
import { l as loadCurrentState, r as resolveActiveSlug } from '../shared/luca.
|
|
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.
|
|
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 {
|
|
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.
|
|
16
|
+
import '../shared/luca.pqZahLS5.mjs';
|
|
17
17
|
import 'consola';
|
|
18
18
|
import '../shared/luca.CQ3g1xrD.mjs';
|
|
19
|
-
import '../shared/luca.
|
|
19
|
+
import '../shared/luca.Djs7oPPj.mjs';
|
|
20
20
|
|
|
21
21
|
async function resolveSlug(opts) {
|
|
22
22
|
if (opts.explicit) return opts.explicit;
|
package/dist/chunks/hook.mjs
CHANGED
|
@@ -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.
|
|
3
|
-
import { l as loadCurrentState, r as resolveActiveSlug } from '../shared/luca.
|
|
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.
|
|
8
|
-
import { p as phasePathFor } from '../shared/luca.
|
|
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
|
|
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
|
|
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(
|
|
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);
|
package/dist/chunks/init.mjs
CHANGED
|
@@ -3,7 +3,7 @@ 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.
|
|
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';
|
package/dist/chunks/phase.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineCommand } from 'citty';
|
|
2
2
|
import 'zod';
|
|
3
|
-
import '../shared/luca.
|
|
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.
|
|
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.
|
|
14
|
-
import '../shared/luca.
|
|
15
|
-
import '../shared/luca.
|
|
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.
|
|
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
|
|
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.
|
|
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 {
|
|
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.
|
|
14
|
-
import '../shared/luca.
|
|
15
|
-
import '../shared/luca.
|
|
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.
|
|
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.
|
|
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 {
|
|
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.
|
|
14
|
-
import '../shared/luca.
|
|
15
|
-
import '../shared/luca.
|
|
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.
|
|
17
|
+
import '../shared/luca.Djs7oPPj.mjs';
|
|
18
18
|
|
|
19
19
|
const readCommand = defineCommand({
|
|
20
20
|
meta: {
|
package/dist/chunks/repair.mjs
CHANGED
|
@@ -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.
|
|
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';
|
package/dist/chunks/repo.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineCommand } from 'citty';
|
|
2
2
|
import 'zod';
|
|
3
|
-
import '../shared/luca.
|
|
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 {
|
|
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.
|
|
14
|
-
import '../shared/luca.
|
|
15
|
-
import '../shared/luca.
|
|
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.
|
|
17
|
+
import '../shared/luca.Djs7oPPj.mjs';
|
|
18
18
|
|
|
19
19
|
const cleanupApplyCommand = defineCommand({
|
|
20
20
|
meta: {
|
package/dist/chunks/retro.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineCommand } from 'citty';
|
|
2
|
-
import '../shared/luca.
|
|
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.
|
|
11
|
-
import { l as listRuns } from '../shared/luca.
|
|
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.
|
|
16
|
-
import '../shared/luca.
|
|
15
|
+
import '../shared/luca.BQXFn5yo.mjs';
|
|
16
|
+
import '../shared/luca.pqZahLS5.mjs';
|
|
17
17
|
import 'pathe';
|
|
18
18
|
import 'consola';
|
|
19
19
|
|
package/dist/chunks/roadmap.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineCommand } from 'citty';
|
|
2
2
|
import 'zod';
|
|
3
|
-
import '../shared/luca.
|
|
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 {
|
|
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.
|
|
14
|
-
import '../shared/luca.
|
|
15
|
-
import '../shared/luca.
|
|
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.
|
|
17
|
+
import '../shared/luca.Djs7oPPj.mjs';
|
|
18
18
|
|
|
19
19
|
const readCommand = defineCommand({
|
|
20
20
|
meta: {
|
package/dist/chunks/rules.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineCommand } from 'citty';
|
|
2
2
|
import { join as join$1 } from 'pathe';
|
|
3
|
-
import '../shared/luca.
|
|
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.
|
|
12
|
-
import { l as listRuns } from '../shared/luca.
|
|
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.
|
|
17
|
-
import '../shared/luca.
|
|
16
|
+
import '../shared/luca.BQXFn5yo.mjs';
|
|
17
|
+
import '../shared/luca.pqZahLS5.mjs';
|
|
18
18
|
import 'consola';
|
|
19
19
|
|
|
20
20
|
let tsModuleCache = void 0;
|
package/dist/chunks/state.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineCommand } from 'citty';
|
|
2
2
|
import 'zod';
|
|
3
|
-
import '../shared/luca.
|
|
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, l as lucaStateAdvanceTool, a as lucaStateReadTool } from '../shared/luca.
|
|
11
|
+
import { r as runWriteHandler, l as lucaStateAdvanceTool, a as lucaStateReadTool } from '../shared/luca.DykMxS_D.mjs';
|
|
12
12
|
import 'node:os';
|
|
13
|
-
import '../shared/luca.
|
|
14
|
-
import '../shared/luca.
|
|
15
|
-
import '../shared/luca.
|
|
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.
|
|
17
|
+
import '../shared/luca.Djs7oPPj.mjs';
|
|
18
18
|
|
|
19
19
|
const readCommand = defineCommand({
|
|
20
20
|
meta: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, lstatSync } from 'node:fs';
|
|
2
2
|
import { rm, writeFile, readdir, rmdir } from 'node:fs/promises';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
-
import '../shared/luca.
|
|
4
|
+
import '../shared/luca.DXUcpbIe.mjs';
|
|
5
5
|
import 'node:crypto';
|
|
6
6
|
import 'node:module';
|
|
7
7
|
import 'node:url';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineCommand } from 'citty';
|
|
2
|
-
import { R as RunIdSchema, L as LUCA_DIR_ROOT, T as TelemetryRecordSchema } from '../shared/luca.
|
|
2
|
+
import { R as RunIdSchema, L as LUCA_DIR_ROOT, T as TelemetryRecordSchema } from '../shared/luca.DXUcpbIe.mjs';
|
|
3
3
|
import { mkdirSync, appendFileSync } from 'node:fs';
|
|
4
4
|
import 'node:fs/promises';
|
|
5
5
|
import { join, dirname } from 'node:path';
|
package/dist/chunks/todo.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineCommand } from 'citty';
|
|
2
2
|
import 'zod';
|
|
3
|
-
import '../shared/luca.
|
|
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 {
|
|
11
|
+
import { e as readJsonPayload, r as runWriteHandler, j as lucaTodoUpdateTool, k as lucaTodoListTool, m as lucaTodoAddTool } from '../shared/luca.DykMxS_D.mjs';
|
|
12
12
|
import 'node:os';
|
|
13
|
-
import '../shared/luca.
|
|
14
|
-
import '../shared/luca.
|
|
15
|
-
import '../shared/luca.
|
|
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.
|
|
17
|
+
import '../shared/luca.Djs7oPPj.mjs';
|
|
18
18
|
|
|
19
19
|
const addCommand = defineCommand({
|
|
20
20
|
meta: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineCommand } from 'citty';
|
|
2
|
-
import '../shared/luca.
|
|
3
|
-
import { l as loadCurrentState, r as resolveActiveSlug } from '../shared/luca.
|
|
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,11 +8,11 @@ import 'node:crypto';
|
|
|
8
8
|
import 'node:module';
|
|
9
9
|
import 'node:url';
|
|
10
10
|
import 'node:child_process';
|
|
11
|
-
import { l as listPhaseSlugs, r as readVerificationResult, a as aggregateVerificationResults } from '../shared/luca.
|
|
11
|
+
import { l as listPhaseSlugs, r as readVerificationResult, a as aggregateVerificationResults } from '../shared/luca.BQXFn5yo.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.
|
|
15
|
+
import '../shared/luca.pqZahLS5.mjs';
|
|
16
16
|
import 'pathe';
|
|
17
17
|
import 'consola';
|
|
18
18
|
|
package/dist/chunks/workflow.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineCommand } from 'citty';
|
|
2
2
|
import 'zod';
|
|
3
|
-
import '../shared/luca.
|
|
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,
|
|
11
|
+
import { r as runWriteHandler, u as lucaWorkflowResetTool } from '../shared/luca.DykMxS_D.mjs';
|
|
12
12
|
import 'node:os';
|
|
13
|
-
import '../shared/luca.
|
|
14
|
-
import '../shared/luca.
|
|
15
|
-
import '../shared/luca.
|
|
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.
|
|
17
|
+
import '../shared/luca.Djs7oPPj.mjs';
|
|
18
18
|
|
|
19
19
|
const resetCommand = defineCommand({
|
|
20
20
|
meta: {
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: caveman
|
|
3
|
+
description: "Ultra-compressed communication mode. Cuts token usage ~75% by speaking like caveman while keeping full technical accuracy. Supports intensity levels: lite, full (default), ultra. Use when user says \"caveman mode\", \"talk like caveman\", \"use caveman\", \"less tokens\", \"be brief\", or invokes /caveman. Also auto-triggers when token efficiency is requested."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<main>
|
|
7
|
+
# Caveman
|
|
8
|
+
|
|
9
|
+
Respond terse like smart caveman. All technical substance stay. Only fluff die.
|
|
10
|
+
|
|
11
|
+
## Persistence
|
|
12
|
+
|
|
13
|
+
ACTIVE EVERY RESPONSE. No revert after many turns. No filler drift. Still active if unsure. Off only: "stop caveman" / "normal mode".
|
|
14
|
+
|
|
15
|
+
Default: **full**. Switch: `/caveman lite|full|ultra`.
|
|
16
|
+
|
|
17
|
+
## Rules
|
|
18
|
+
|
|
19
|
+
Drop: articles (a/an/the), filler (just/really/basically/actually/simply), pleasantries (sure/certainly/of course/happy to), hedging. Fragments OK. Short synonyms (big not extensive, fix not "implement a solution for"). Technical terms exact. Code blocks unchanged. Errors quoted exact.
|
|
20
|
+
|
|
21
|
+
Pattern: `[thing] [action] [reason]. [next step].`
|
|
22
|
+
|
|
23
|
+
Not: "Sure! I'd be happy to help you with that. The issue you're experiencing is likely caused by..."
|
|
24
|
+
Yes: "Bug in auth middleware. Token expiry check use `<` not `<=`. Fix:"
|
|
25
|
+
|
|
26
|
+
## Intensity
|
|
27
|
+
|
|
28
|
+
| Level | What change |
|
|
29
|
+
|-------|------------|
|
|
30
|
+
| **lite** | No filler/hedging. Keep articles + full sentences. Professional but tight |
|
|
31
|
+
| **full** | Drop articles, fragments OK, short synonyms. Classic caveman |
|
|
32
|
+
| **ultra** | Abbreviate (DB/auth/config/req/res/fn/impl), strip conjunctions, arrows for causality (X → Y), one word when one word enough |
|
|
33
|
+
|
|
34
|
+
Example — "Why React component re-render?"
|
|
35
|
+
- lite: "Your component re-renders because you create a new object reference each render. Wrap it in `useMemo`."
|
|
36
|
+
- full: "New object ref each render. Inline object prop = new ref = re-render. Wrap in `useMemo`."
|
|
37
|
+
- ultra: "Inline obj prop → new ref → re-render. `useMemo`."
|
|
38
|
+
|
|
39
|
+
Example — "Explain database connection pooling."
|
|
40
|
+
- lite: "Connection pooling reuses open connections instead of creating new ones per request. Avoids repeated handshake overhead."
|
|
41
|
+
- full: "Pool reuse open DB connections. No new connection per request. Skip handshake overhead."
|
|
42
|
+
- ultra: "Pool = reuse DB conn. Skip handshake → fast under load."
|
|
43
|
+
|
|
44
|
+
## Auto-Clarity
|
|
45
|
+
|
|
46
|
+
Drop caveman for: security warnings, irreversible action confirmations, multi-step sequences where fragment order risks misread, user asks to clarify or repeats question. Resume caveman after clear part done.
|
|
47
|
+
|
|
48
|
+
Example — destructive op:
|
|
49
|
+
> **Warning:** This will permanently delete all rows in the `users` table and cannot be undone.
|
|
50
|
+
> ```sql
|
|
51
|
+
> DROP TABLE users;
|
|
52
|
+
> ```
|
|
53
|
+
> Caveman resume. Verify backup exist first.
|
|
54
|
+
|
|
55
|
+
## Boundaries
|
|
56
|
+
|
|
57
|
+
Code/commits/PRs: write normal. "stop caveman" or "normal mode": revert. Level persist until changed or session end.
|
|
58
|
+
</main>
|
|
@@ -80,7 +80,7 @@ Repeat until `pipelineStep` is `complete`:
|
|
|
80
80
|
| `checks` | Run `luca checks run --file <commands.json>` with the project's typecheck (and tests, if present). On failure, loop back to `execute`. |
|
|
81
81
|
| `verify` | Spawn `luca-verifier` (Agent tool). On `recommendation: fix`, loop back to `checks`; on `escalate`, stop and surface to the user. |
|
|
82
82
|
| `review` | Spawn `luca-reviewer` (Agent tool) — one per perspective, in parallel. |
|
|
83
|
-
| `learn` | Spawn `luca-learner` (Agent tool). Then
|
|
83
|
+
| `learn` | Spawn `luca-learner` (Agent tool). Then, if more phases remain: run `luca phase advance` (bumps `currentPhase` to the next phase and marks the finished one complete) **before** advancing the step to `plan` — the next phase's artifacts resolve against the new `currentPhase`, so skipping this writes them into the wrong (or no) phase dir. On the last phase, do NOT run `luca phase advance`; advance the step to `milestone`. |
|
|
84
84
|
| `milestone` | Invoke `Skill(skill: "milestone-new")` to close out, or advance to `complete` if no milestone bookkeeping is needed. |
|
|
85
85
|
|
|
86
86
|
### Oversight
|
|
@@ -71,9 +71,16 @@ When updating state during milestone completion, use the `luca` CLI write surfac
|
|
|
71
71
|
STATE_JSON=$(luca state read 2>/dev/null || echo '{"initialized":false}')
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
After archiving the milestone,
|
|
74
|
+
After archiving the milestone, freeze the closing milestone's phase
|
|
75
|
+
directories and reset workflow state for the next milestone:
|
|
75
76
|
|
|
76
77
|
```bash
|
|
78
|
+
# Move .luca/phases/<slug>/ → .luca/archive/<slug>/ so the next milestone's
|
|
79
|
+
# roadmap starts from an empty phases/ dir (per LUCA_DIR_CONTRACT). Idempotent;
|
|
80
|
+
# skips any slug already present under archive/. Do this BEFORE the next
|
|
81
|
+
# roadmap is created, or stale phase dirs collide on phase number with it.
|
|
82
|
+
luca phase archive 2>/dev/null || true
|
|
83
|
+
|
|
77
84
|
luca workflow reset 2>/dev/null || true
|
|
78
85
|
```
|
|
79
86
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
-
import {
|
|
4
|
+
import { x as lucaStateSchemaTolerant, P as PhaseSlugSchema } from './luca.DXUcpbIe.mjs';
|
|
5
5
|
|
|
6
6
|
async function loadCurrentState(opts) {
|
|
7
7
|
const statePath = join(opts.cwd, ".luca", "state.json");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
import { p as phasePathFor } from './luca.
|
|
3
|
+
import { v as VerificationResultSchema, w as PHASE_SLUG_RE } from './luca.DXUcpbIe.mjs';
|
|
4
|
+
import { p as phasePathFor } from './luca.pqZahLS5.mjs';
|
|
5
5
|
import { join as join$1 } from 'pathe';
|
|
6
6
|
import 'node:fs/promises';
|
|
7
7
|
import 'node:crypto';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import './luca.
|
|
1
|
+
import './luca.DXUcpbIe.mjs';
|
|
2
2
|
import 'node:fs';
|
|
3
3
|
import 'node:fs/promises';
|
|
4
4
|
import 'node:path';
|
|
@@ -6,8 +6,8 @@ import 'node:crypto';
|
|
|
6
6
|
import 'node:module';
|
|
7
7
|
import 'node:url';
|
|
8
8
|
import 'node:child_process';
|
|
9
|
-
import { r as readConfidenceJournal, a as readLedgerForRun } from './luca.
|
|
10
|
-
import { l as listPhaseSlugs, r as readVerificationResult } from './luca.
|
|
9
|
+
import { r as readConfidenceJournal, a as readLedgerForRun } from './luca.CuvqWf4b.mjs';
|
|
10
|
+
import { l as listPhaseSlugs, r as readVerificationResult } from './luca.BQXFn5yo.mjs';
|
|
11
11
|
|
|
12
12
|
function fingerprint(input) {
|
|
13
13
|
let hash = 0;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync, mkdirSync, appendFileSync } from 'node:fs';
|
|
2
2
|
import { join, dirname } from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
import { p as phasePathFor } from './luca.
|
|
3
|
+
import { f as lucaRootPaths, r as LedgerEntrySchema, u as ConfidenceEntrySchema } from './luca.DXUcpbIe.mjs';
|
|
4
|
+
import { p as phasePathFor } from './luca.pqZahLS5.mjs';
|
|
5
5
|
|
|
6
6
|
function appendLedger(opts) {
|
|
7
7
|
const entry = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import 'node:fs';
|
|
3
3
|
import 'node:fs/promises';
|
|
4
|
-
import 'node:path';
|
|
4
|
+
import { isAbsolute, relative } from 'node:path';
|
|
5
5
|
import 'node:os';
|
|
6
6
|
|
|
7
7
|
const PipelineStepValues = [
|
|
@@ -266,8 +266,9 @@ function classifyWritePath(path, opts = {}) {
|
|
|
266
266
|
}
|
|
267
267
|
}
|
|
268
268
|
}
|
|
269
|
-
|
|
270
|
-
|
|
269
|
+
const rel = opts.cwd && isAbsolute(path) ? relative(opts.cwd, path) : path;
|
|
270
|
+
if (rel.startsWith(".luca/") || rel === ".luca") {
|
|
271
|
+
if (AUDIT_PATH_PATTERN.test(rel)) {
|
|
271
272
|
return { class: "planning-audit" };
|
|
272
273
|
}
|
|
273
274
|
return { class: "planning-general" };
|
|
@@ -710,4 +711,4 @@ for (const step of Object.keys(STEP_REMINDERS)) {
|
|
|
710
711
|
}
|
|
711
712
|
}
|
|
712
713
|
|
|
713
|
-
export { AUDIT_PATH_PATTERN as A, ClassifyComplexityInputSchema as C, LUCA_DIR_ROOT as L,
|
|
714
|
+
export { AUDIT_PATH_PATTERN as A, ClassifyComplexityInputSchema as C, LUCA_DIR_ROOT as L, PhaseSlugSchema as P, RunIdSchema as R, ShadowScanFindingSchema as S, TelemetryRecordSchema as T, VerificationRefSchema as V, WAVE_FILE_RE as W, classifyWritePath as a, ProjectPreferencesSchema as b, coarsePhaseOf as c, ConfidenceCategorySchema as d, ConfidenceLevelSchema as e, lucaRootPaths as f, RoadmapPhaseSchema as g, PipelineStep as h, isLegalTransition as i, PIPELINE_TRANSITIONS as j, PIPELINE_STEP_TO_COARSE_PHASE as k, lucaStateSchema as l, PipelineStepValues as m, TodoIdSchema as n, TodoSchema as o, TodoStatus as p, TODO_CONCEPT_PREFIX as q, LedgerEntrySchema as r, slugFromTitle as s, todoConceptFor as t, ConfidenceEntrySchema as u, VerificationResultSchema as v, PHASE_SLUG_RE as w, lucaStateSchemaTolerant as x, PHASE_FILE_PATHS as y };
|
|
@@ -37,6 +37,11 @@ const WRITE_COMMAND_PHASES = {
|
|
|
37
37
|
// Phase-restricted structured mutations
|
|
38
38
|
"roadmap create": ["idle", "triage"],
|
|
39
39
|
"checks run": ["execute", "checks"],
|
|
40
|
+
// Phase lifecycle: advance at the phase boundary (learn); archive only
|
|
41
|
+
// at milestone close. (The tool descriptors carry matching allowedPhases,
|
|
42
|
+
// but the CLI self-check consults THIS table — runWriteHandler.)
|
|
43
|
+
"phase advance": ["learn"],
|
|
44
|
+
"phase archive": ["milestone", "complete"],
|
|
40
45
|
// Phase-restricted freeform artifact writes
|
|
41
46
|
"phase write-research": ["research"],
|
|
42
47
|
"phase write-context": ["discuss"],
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { P as
|
|
3
|
-
import { l as loadCurrentState, r as resolveActiveSlug } from './luca.
|
|
2
|
+
import { P as PhaseSlugSchema, L as LUCA_DIR_ROOT, b as ProjectPreferencesSchema, d as ConfidenceCategorySchema, e as ConfidenceLevelSchema, f as lucaRootPaths, S as ShadowScanFindingSchema, g as RoadmapPhaseSchema, h as PipelineStep, i as isLegalTransition, j as PIPELINE_TRANSITIONS, k as PIPELINE_STEP_TO_COARSE_PHASE, m as PipelineStepValues, n as TodoIdSchema, s as slugFromTitle, o as TodoSchema, t as todoConceptFor, p as TodoStatus, q as TODO_CONCEPT_PREFIX, V as VerificationRefSchema, l as lucaStateSchema } from './luca.DXUcpbIe.mjs';
|
|
3
|
+
import { l as loadCurrentState, r as resolveActiveSlug } from './luca.BH2GZl5z.mjs';
|
|
4
4
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
5
|
-
import { mkdir, writeFile, rename, rm, readFile, appendFile, unlink } from 'node:fs/promises';
|
|
5
|
+
import { mkdir, writeFile, rename, rm, readFile, readdir, appendFile, unlink } from 'node:fs/promises';
|
|
6
6
|
import { join, dirname, resolve, relative, sep } from 'node:path';
|
|
7
7
|
import 'node:crypto';
|
|
8
8
|
import 'node:module';
|
|
9
9
|
import 'node:url';
|
|
10
10
|
import { spawnSync } from 'node:child_process';
|
|
11
|
-
import { c as appendConfidenceEntry, d as appendLedger } from './luca.
|
|
12
|
-
import { p as phasePathFor } from './luca.
|
|
11
|
+
import { c as appendConfidenceEntry, d as appendLedger } from './luca.CuvqWf4b.mjs';
|
|
12
|
+
import { p as phasePathFor } from './luca.pqZahLS5.mjs';
|
|
13
13
|
import { l as loadCurrentConfig } from './luca.CQ3g1xrD.mjs';
|
|
14
|
-
import { S as STEP_ARTIFACTS, W as WRITE_COMMAND_PHASES } from './luca.
|
|
14
|
+
import { S as STEP_ARTIFACTS, W as WRITE_COMMAND_PHASES } from './luca.Djs7oPPj.mjs';
|
|
15
|
+
|
|
16
|
+
function archivedPhasePathFor(slug) {
|
|
17
|
+
PhaseSlugSchema.parse(slug);
|
|
18
|
+
return `${LUCA_DIR_ROOT}/archive/${slug}`;
|
|
19
|
+
}
|
|
15
20
|
|
|
16
21
|
const PREFERENCE_SECTIONS = [
|
|
17
22
|
"schemaVersion",
|
|
@@ -578,7 +583,7 @@ async function validateVerificationRef(opts) {
|
|
|
578
583
|
return null;
|
|
579
584
|
}
|
|
580
585
|
|
|
581
|
-
const inputSchema$
|
|
586
|
+
const inputSchema$j = z.object({
|
|
582
587
|
default_branch: z.string().min(1).default("main").describe(
|
|
583
588
|
"Branch name that must NOT equal the current branch (typically the repository default branch)."
|
|
584
589
|
)
|
|
@@ -597,7 +602,7 @@ async function readCurrentBranch(cwd) {
|
|
|
597
602
|
const lucaBranchGuardTool = {
|
|
598
603
|
name: "luca_branch_guard",
|
|
599
604
|
description: "Assert that the current git branch is NOT the repository default branch. Returns isError when on the default branch, otherwise ok=true. Use before committing to prevent accidental main writes.",
|
|
600
|
-
inputSchema: inputSchema$
|
|
605
|
+
inputSchema: inputSchema$j,
|
|
601
606
|
async handler(args, ctx) {
|
|
602
607
|
const current = await readCurrentBranch(ctx.cwd);
|
|
603
608
|
if (current === null) {
|
|
@@ -634,7 +639,7 @@ const commandSchema = z.object({
|
|
|
634
639
|
"Optional human-friendly label for this command in the summary output. Defaults to the argv joined by spaces."
|
|
635
640
|
)
|
|
636
641
|
});
|
|
637
|
-
const inputSchema$
|
|
642
|
+
const inputSchema$i = z.object({
|
|
638
643
|
commands: z.array(commandSchema).min(1).describe(
|
|
639
644
|
"Ordered list of commands to run sequentially. Each command runs only if the previous one is still within budget; failures do NOT stop the sequence."
|
|
640
645
|
),
|
|
@@ -714,7 +719,7 @@ async function runOne(argv, label, cwd, timeoutMs) {
|
|
|
714
719
|
const lucaChecksRunTool = {
|
|
715
720
|
name: "luca_checks_run",
|
|
716
721
|
description: "Run verification commands (typecheck/tests/lint) sequentially with per-command timeout and SIGTERM/SIGKILL cleanup. Returns structured summary per command. Only callable in execute/checks phases.",
|
|
717
|
-
inputSchema: inputSchema$
|
|
722
|
+
inputSchema: inputSchema$i,
|
|
718
723
|
allowedPhases: ["execute", "checks"],
|
|
719
724
|
async handler(args, ctx) {
|
|
720
725
|
const results = [];
|
|
@@ -732,7 +737,7 @@ const lucaChecksRunTool = {
|
|
|
732
737
|
}
|
|
733
738
|
};
|
|
734
739
|
|
|
735
|
-
const inputSchema$
|
|
740
|
+
const inputSchema$h = z.object({
|
|
736
741
|
phase: z.string().min(1).describe("Phase name from the plan / roadmap."),
|
|
737
742
|
wave: z.number().describe("Wave number within the phase."),
|
|
738
743
|
task: z.string().min(1).describe("Task ID or description from the plan."),
|
|
@@ -752,7 +757,7 @@ const inputSchema$f = z.object({
|
|
|
752
757
|
const lucaConfidenceLogTool = {
|
|
753
758
|
name: "luca_confidence_log",
|
|
754
759
|
description: "Append a confidence entry to the active phase's confidence.jsonl. One JSONL line per call. Payload matches the canonical ConfidenceEntrySchema (phase, wave, task, confidence, category, decision, alternatives, reasoning, risk, files, reviewHint?).",
|
|
755
|
-
inputSchema: inputSchema$
|
|
760
|
+
inputSchema: inputSchema$h,
|
|
756
761
|
async handler(args, ctx) {
|
|
757
762
|
const state = await loadCurrentState({ cwd: ctx.cwd });
|
|
758
763
|
const slug = resolveActiveSlug(state);
|
|
@@ -790,6 +795,109 @@ const lucaConfidenceLogTool = {
|
|
|
790
795
|
}
|
|
791
796
|
};
|
|
792
797
|
|
|
798
|
+
const inputSchema$g = z.object({});
|
|
799
|
+
const lucaPhaseAdvanceTool = {
|
|
800
|
+
name: "luca_phase_advance",
|
|
801
|
+
description: "Advance the active roadmap phase by one (currentPhase \u2192 currentPhase+1), marking the completed phase `complete` and the next `in-progress`. Call at the phase boundary (learn step) when more phases remain; the final phase routes to the milestone step instead. Errors if no phase is active (currentPhase=0) or already at the final phase.",
|
|
802
|
+
inputSchema: inputSchema$g,
|
|
803
|
+
allowedPhases: ["learn"],
|
|
804
|
+
async handler(_args, ctx) {
|
|
805
|
+
const state = await loadCurrentState({ cwd: ctx.cwd });
|
|
806
|
+
const { currentPhase, totalPhases } = state;
|
|
807
|
+
if (currentPhase === 0) {
|
|
808
|
+
return errorResult(
|
|
809
|
+
"no active phase to advance (currentPhase=0). Create a roadmap first (`luca roadmap create`)."
|
|
810
|
+
);
|
|
811
|
+
}
|
|
812
|
+
if (currentPhase >= totalPhases) {
|
|
813
|
+
return errorResult(
|
|
814
|
+
`already at the final phase (${currentPhase}/${totalPhases}); there is no next phase. Advance to the milestone step instead.`
|
|
815
|
+
);
|
|
816
|
+
}
|
|
817
|
+
const roadmap = state.roadmap.map((phase, index) => {
|
|
818
|
+
if (index === currentPhase - 1) {
|
|
819
|
+
return { ...phase, status: "complete" };
|
|
820
|
+
}
|
|
821
|
+
if (index === currentPhase) {
|
|
822
|
+
return { ...phase, status: "in-progress" };
|
|
823
|
+
}
|
|
824
|
+
return phase;
|
|
825
|
+
});
|
|
826
|
+
const next = { ...state, roadmap, currentPhase: currentPhase + 1 };
|
|
827
|
+
const absPath = join(ctx.cwd, lucaRootPaths.state);
|
|
828
|
+
await writeAtomicFile(absPath, JSON.stringify(next, null, 2) + "\n");
|
|
829
|
+
return {
|
|
830
|
+
content: [
|
|
831
|
+
{
|
|
832
|
+
type: "text",
|
|
833
|
+
text: `phase advanced: ${currentPhase} \u2192 ${currentPhase + 1} of ${totalPhases} (phase ${currentPhase} marked complete, phase ${currentPhase + 1} in-progress)`
|
|
834
|
+
}
|
|
835
|
+
]
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
};
|
|
839
|
+
function errorResult(message) {
|
|
840
|
+
return {
|
|
841
|
+
content: [{ type: "text", text: message }],
|
|
842
|
+
isError: true
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
const inputSchema$f = z.object({});
|
|
847
|
+
const lucaPhaseArchiveTool = {
|
|
848
|
+
name: "luca_phase_archive",
|
|
849
|
+
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: a slug already present under archive/ is skipped, not overwritten. Allowed only in the milestone/complete steps.",
|
|
850
|
+
inputSchema: inputSchema$f,
|
|
851
|
+
allowedPhases: ["milestone", "complete"],
|
|
852
|
+
async handler(_args, ctx) {
|
|
853
|
+
const phasesDir = join(ctx.cwd, ".luca", "phases");
|
|
854
|
+
if (!existsSync(phasesDir)) {
|
|
855
|
+
return ok("no .luca/phases/ directory \u2014 nothing to archive.");
|
|
856
|
+
}
|
|
857
|
+
const entries = await readdir(phasesDir, { withFileTypes: true });
|
|
858
|
+
const archived = [];
|
|
859
|
+
const skipped = [];
|
|
860
|
+
const invalid = [];
|
|
861
|
+
for (const entry of entries) {
|
|
862
|
+
if (!entry.isDirectory()) continue;
|
|
863
|
+
const slug = entry.name;
|
|
864
|
+
let to;
|
|
865
|
+
try {
|
|
866
|
+
to = join(ctx.cwd, archivedPhasePathFor(slug));
|
|
867
|
+
} catch {
|
|
868
|
+
invalid.push(slug);
|
|
869
|
+
continue;
|
|
870
|
+
}
|
|
871
|
+
const from = join(phasesDir, slug);
|
|
872
|
+
if (existsSync(to)) {
|
|
873
|
+
skipped.push(slug);
|
|
874
|
+
continue;
|
|
875
|
+
}
|
|
876
|
+
await mkdir(join(ctx.cwd, ".luca", "archive"), {
|
|
877
|
+
recursive: true
|
|
878
|
+
});
|
|
879
|
+
await rename(from, to);
|
|
880
|
+
archived.push(slug);
|
|
881
|
+
}
|
|
882
|
+
const parts = [`archived ${archived.length} phase(s) \u2192 .luca/archive/`];
|
|
883
|
+
if (archived.length > 0) parts.push(`moved: ${archived.join(", ")}`);
|
|
884
|
+
if (skipped.length > 0) {
|
|
885
|
+
parts.push(
|
|
886
|
+
`skipped (archive entry already exists): ${skipped.join(", ")}`
|
|
887
|
+
);
|
|
888
|
+
}
|
|
889
|
+
if (invalid.length > 0) {
|
|
890
|
+
parts.push(
|
|
891
|
+
`skipped (not a valid phase slug): ${invalid.join(", ")}`
|
|
892
|
+
);
|
|
893
|
+
}
|
|
894
|
+
return ok(parts.join(". "));
|
|
895
|
+
}
|
|
896
|
+
};
|
|
897
|
+
function ok(text) {
|
|
898
|
+
return { content: [{ type: "text", text }] };
|
|
899
|
+
}
|
|
900
|
+
|
|
793
901
|
const inputSchema$e = z.object({});
|
|
794
902
|
const lucaPhaseCurrentTool = {
|
|
795
903
|
name: "luca_phase_current",
|
|
@@ -1283,7 +1391,7 @@ const inputSchema$7 = z.object({
|
|
|
1283
1391
|
});
|
|
1284
1392
|
const lucaRoadmapCreateTool = {
|
|
1285
1393
|
name: "luca_roadmap_create",
|
|
1286
|
-
description: "Replace the roadmap in .luca/state.json with a new ordered list of phases.
|
|
1394
|
+
description: "Replace the roadmap in .luca/state.json with a new ordered list of phases. Activates phase 1 (currentPhase=1) when non-empty; updates totalPhases. Only callable in idle or triage pipelineSteps so an active roadmap cannot be clobbered mid-execution.",
|
|
1287
1395
|
inputSchema: inputSchema$7,
|
|
1288
1396
|
allowedPhases: ["idle", "triage"],
|
|
1289
1397
|
async handler(args, ctx) {
|
|
@@ -1293,11 +1401,12 @@ const lucaRoadmapCreateTool = {
|
|
|
1293
1401
|
deps: p.deps ?? [],
|
|
1294
1402
|
status: p.status ?? "pending"
|
|
1295
1403
|
}));
|
|
1404
|
+
const currentPhase = phases.length > 0 ? 1 : 0;
|
|
1296
1405
|
const next = {
|
|
1297
1406
|
...state,
|
|
1298
1407
|
roadmap: phases,
|
|
1299
1408
|
totalPhases: phases.length,
|
|
1300
|
-
currentPhase
|
|
1409
|
+
currentPhase
|
|
1301
1410
|
};
|
|
1302
1411
|
const absPath = join(ctx.cwd, lucaRootPaths.state);
|
|
1303
1412
|
await writeAtomicFile(absPath, JSON.stringify(next, null, 2) + "\n");
|
|
@@ -1305,7 +1414,7 @@ const lucaRoadmapCreateTool = {
|
|
|
1305
1414
|
content: [
|
|
1306
1415
|
{
|
|
1307
1416
|
type: "text",
|
|
1308
|
-
text: `wrote .luca/state.json (roadmap replaced with ${phases.length} phase(s); currentPhase
|
|
1417
|
+
text: `wrote .luca/state.json (roadmap replaced with ${phases.length} phase(s); currentPhase=${currentPhase})`
|
|
1309
1418
|
}
|
|
1310
1419
|
]
|
|
1311
1420
|
};
|
|
@@ -1901,4 +2010,4 @@ async function readJsonPayload(command, filePath) {
|
|
|
1901
2010
|
}
|
|
1902
2011
|
}
|
|
1903
2012
|
|
|
1904
|
-
export { lucaStateReadTool as a, lucaPhaseCurrentTool as b,
|
|
2013
|
+
export { lucaStateReadTool as a, lucaPhaseCurrentTool as b, lucaPhaseAdvanceTool as c, lucaPhaseArchiveTool as d, readJsonPayload as e, lucaRoadmapReadTool as f, lucaRoadmapCreateTool as g, lucaPreferencesReadTool as h, lucaPreferencesWriteTool as i, lucaTodoUpdateTool as j, lucaTodoListTool as k, lucaStateAdvanceTool as l, lucaTodoAddTool as m, lucaPrReviewDetectConvergenceTool as n, lucaPrReviewFilterStaleTool as o, lucaPrReviewRegressionCheckTool as p, lucaRepoCleanupApplyTool as q, runWriteHandler as r, lucaChecksRunTool as s, lucaBranchGuardTool as t, lucaWorkflowResetTool as u, lucaConfidenceLogTool as v };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { P as PhaseSlugSchema, L as LUCA_DIR_ROOT, y as PHASE_FILE_PATHS } from './luca.DXUcpbIe.mjs';
|
|
2
2
|
|
|
3
3
|
function phasePathFor(slug, file) {
|
|
4
4
|
PhaseSlugSchema.parse(slug);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alecsibilia/luca",
|
|
3
3
|
"description": "Luca — spec-driven agentic development workflow for Claude Code (umbrella; bundles luca-cli, luca-core, luca-tools)",
|
|
4
|
-
"version": "13.0.0-alpha.
|
|
4
|
+
"version": "13.0.0-alpha.3",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Alec Sibilia <sibilia.alec@gmail.com>",
|
|
7
7
|
"homepage": "https://github.com/asibilia/luca-framework#readme",
|