@alecsibilia/luca 13.0.0-alpha.4 → 13.0.0-alpha.5
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/config-version-skew.mjs +97 -0
- package/dist/chunks/doctor.mjs +3 -1
- package/dist/chunks/hook.mjs +79 -9
- package/dist/chunks/init.mjs +28 -12
- package/dist/chunks/phase.mjs +6 -6
- 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 +47 -7
- 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/.claude/hooks/context-refresher.ts +1 -0
- package/dist/claude/.claude/hooks/continuation-messages.ts +1 -0
- package/dist/claude/.claude/hooks/pipeline-guard.ts +1 -0
- package/dist/claude/skills/luca-write-surface/SKILL.md +8 -3
- package/dist/index.mjs +1 -1
- package/dist/shared/{luca.BKNzBAX6.mjs → luca.0ssL9rcP.mjs} +2 -2
- package/dist/shared/{luca.CbQLVJY4.mjs → luca.B-w_fieK.mjs} +1 -1
- package/dist/shared/luca.BTcIy-Mh.mjs +183 -0
- package/dist/shared/{luca.EQGAqeU5.mjs → luca.BiHycbFi.mjs} +3 -3
- package/dist/shared/{luca.DEnRxIjr.mjs → luca.Cf93m-DM.mjs} +1 -1
- package/dist/shared/{luca.CSIEeM0g.mjs → luca.D7w2gjQ5.mjs} +2 -2
- package/dist/shared/{luca.Q3_4GQWh.mjs → luca.DZxAJmyM.mjs} +28 -2
- package/dist/shared/{luca.CZNcKKAw.mjs → luca.lLQ2ZIAB.mjs} +86 -134
- package/package.json +1 -1
- package/dist/shared/luca.Djs7oPPj.mjs +0 -57
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.DZxAJmyM.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 lucaBranchGuardTool } from '../shared/luca.lLQ2ZIAB.mjs';
|
|
12
|
+
import '../shared/luca.BTcIy-Mh.mjs';
|
|
12
13
|
import 'node:os';
|
|
13
|
-
import '../shared/luca.
|
|
14
|
-
import '../shared/luca.
|
|
15
|
-
import '../shared/luca.
|
|
14
|
+
import '../shared/luca.Cf93m-DM.mjs';
|
|
15
|
+
import '../shared/luca.D7w2gjQ5.mjs';
|
|
16
|
+
import '../shared/luca.B-w_fieK.mjs';
|
|
16
17
|
import '../shared/luca.CQ3g1xrD.mjs';
|
|
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.DZxAJmyM.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 { f as readJsonPayload, r as runWriteHandler, t as lucaChecksRunTool } from '../shared/luca.lLQ2ZIAB.mjs';
|
|
12
|
+
import '../shared/luca.BTcIy-Mh.mjs';
|
|
12
13
|
import 'node:os';
|
|
13
|
-
import '../shared/luca.
|
|
14
|
-
import '../shared/luca.
|
|
15
|
-
import '../shared/luca.
|
|
14
|
+
import '../shared/luca.Cf93m-DM.mjs';
|
|
15
|
+
import '../shared/luca.D7w2gjQ5.mjs';
|
|
16
|
+
import '../shared/luca.B-w_fieK.mjs';
|
|
16
17
|
import '../shared/luca.CQ3g1xrD.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.
|
|
3
|
+
import '../shared/luca.DZxAJmyM.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.DZxAJmyM.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.DZxAJmyM.mjs';
|
|
3
|
+
import { l as loadCurrentState, r as resolveActiveSlug } from '../shared/luca.Cf93m-DM.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.D7w2gjQ5.mjs';
|
|
12
12
|
import { l as logger } from '../shared/luca.dM-MKlNE.mjs';
|
|
13
13
|
import 'zod';
|
|
14
|
-
import {
|
|
14
|
+
import { f as readJsonPayload, r as runWriteHandler, w as lucaConfidenceLogTool } from '../shared/luca.lLQ2ZIAB.mjs';
|
|
15
|
+
import '../shared/luca.BTcIy-Mh.mjs';
|
|
15
16
|
import 'node:os';
|
|
16
|
-
import '../shared/luca.
|
|
17
|
+
import '../shared/luca.B-w_fieK.mjs';
|
|
17
18
|
import 'consola';
|
|
18
19
|
import '../shared/luca.CQ3g1xrD.mjs';
|
|
19
|
-
import '../shared/luca.Djs7oPPj.mjs';
|
|
20
20
|
|
|
21
21
|
async function resolveSlug(opts) {
|
|
22
22
|
if (opts.explicit) return opts.explicit;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { writeFile, readFile } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { LUCA_VERSION } from '../index.mjs';
|
|
5
|
+
import 'citty';
|
|
6
|
+
import 'pathe';
|
|
7
|
+
|
|
8
|
+
const CHECK_NAME = "Config version skew";
|
|
9
|
+
function configPath() {
|
|
10
|
+
return join(process.cwd(), ".luca", "config.json");
|
|
11
|
+
}
|
|
12
|
+
function isDevVersion(v) {
|
|
13
|
+
return v === "0.0.0-dev" || v.includes("dev");
|
|
14
|
+
}
|
|
15
|
+
async function readConfig() {
|
|
16
|
+
const p = configPath();
|
|
17
|
+
if (!existsSync(p)) return null;
|
|
18
|
+
try {
|
|
19
|
+
const raw = JSON.parse(await readFile(p, "utf-8"));
|
|
20
|
+
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : null;
|
|
21
|
+
} catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const configVersionSkewCheck = {
|
|
26
|
+
name: CHECK_NAME,
|
|
27
|
+
scope: "project",
|
|
28
|
+
async run() {
|
|
29
|
+
const pass = (message) => ({
|
|
30
|
+
name: CHECK_NAME,
|
|
31
|
+
status: "pass",
|
|
32
|
+
message,
|
|
33
|
+
fixCommand: null,
|
|
34
|
+
details: null
|
|
35
|
+
});
|
|
36
|
+
if (isDevVersion(LUCA_VERSION)) {
|
|
37
|
+
return pass("dev CLI build \u2014 version skew not checked");
|
|
38
|
+
}
|
|
39
|
+
const config = await readConfig();
|
|
40
|
+
if (config === null) {
|
|
41
|
+
return pass("no .luca/config.json to check");
|
|
42
|
+
}
|
|
43
|
+
const stored = config.lucaVersion;
|
|
44
|
+
if (typeof stored !== "string" || stored.length === 0) {
|
|
45
|
+
return pass("config.json has no lucaVersion to compare");
|
|
46
|
+
}
|
|
47
|
+
if (stored === LUCA_VERSION) {
|
|
48
|
+
return pass(`config.lucaVersion matches CLI (${LUCA_VERSION})`);
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
name: CHECK_NAME,
|
|
52
|
+
status: "warning",
|
|
53
|
+
message: `config.lucaVersion ${stored} \u2260 installed CLI ${LUCA_VERSION}`,
|
|
54
|
+
fixCommand: "luca doctor --fix",
|
|
55
|
+
details: [
|
|
56
|
+
`.luca/config.json records lucaVersion="${stored}" but the installed CLI is ${LUCA_VERSION}.`,
|
|
57
|
+
`Skills/agents that branch on lucaVersion may behave as if on the older version.`,
|
|
58
|
+
`Run \`luca doctor --fix\` to reconcile (rewrites lucaVersion, preserves all other config keys).`
|
|
59
|
+
].join("\n ")
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
async fix() {
|
|
63
|
+
if (isDevVersion(LUCA_VERSION)) {
|
|
64
|
+
return { applied: [], errors: [] };
|
|
65
|
+
}
|
|
66
|
+
const config = await readConfig();
|
|
67
|
+
if (config === null) {
|
|
68
|
+
return { applied: [], errors: [] };
|
|
69
|
+
}
|
|
70
|
+
const stored = config.lucaVersion;
|
|
71
|
+
if (stored === LUCA_VERSION) {
|
|
72
|
+
return { applied: [], errors: [] };
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
const next = { ...config, lucaVersion: LUCA_VERSION };
|
|
76
|
+
await writeFile(
|
|
77
|
+
configPath(),
|
|
78
|
+
JSON.stringify(next, null, 2) + "\n"
|
|
79
|
+
);
|
|
80
|
+
return {
|
|
81
|
+
applied: [
|
|
82
|
+
`Reconciled .luca/config.json lucaVersion ${typeof stored === "string" ? stored : "unset"} \u2192 ${LUCA_VERSION}`
|
|
83
|
+
],
|
|
84
|
+
errors: []
|
|
85
|
+
};
|
|
86
|
+
} catch (err) {
|
|
87
|
+
return {
|
|
88
|
+
applied: [],
|
|
89
|
+
errors: [
|
|
90
|
+
`Failed to rewrite .luca/config.json lucaVersion: ${err.message}`
|
|
91
|
+
]
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export { configVersionSkewCheck };
|
package/dist/chunks/doctor.mjs
CHANGED
|
@@ -12,6 +12,7 @@ async function executeDoctor(options = {}) {
|
|
|
12
12
|
const { staleGlobalSymlinksCheck } = await import('./stale-global-symlinks.mjs');
|
|
13
13
|
const { legacyPackageCheck } = await import('./legacy-package.mjs');
|
|
14
14
|
const { strayLocalInstallCheck } = await import('./stray-local-install.mjs');
|
|
15
|
+
const { configVersionSkewCheck } = await import('./config-version-skew.mjs');
|
|
15
16
|
const allChecks = [
|
|
16
17
|
// Prerequisites
|
|
17
18
|
bunRuntimeCheck,
|
|
@@ -22,7 +23,8 @@ async function executeDoctor(options = {}) {
|
|
|
22
23
|
staleGlobalSymlinksCheck,
|
|
23
24
|
legacyPackageCheck,
|
|
24
25
|
// Project (cwd-dependent)
|
|
25
|
-
strayLocalInstallCheck
|
|
26
|
+
strayLocalInstallCheck,
|
|
27
|
+
configVersionSkewCheck
|
|
26
28
|
];
|
|
27
29
|
const checks = scope ? allChecks.filter((check) => check.scope === scope) : allChecks;
|
|
28
30
|
if (checks.length === 0) {
|
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, t as toLucaRelative, a as classifyWritePath, A as AUDIT_PATH_PATTERN, W as WAVE_FILE_RE } from '../shared/luca.DZxAJmyM.mjs';
|
|
3
|
+
import { l as loadCurrentState, r as resolveActiveSlug } from '../shared/luca.Cf93m-DM.mjs';
|
|
4
4
|
import 'node:fs';
|
|
5
5
|
import 'node:fs/promises';
|
|
6
|
-
import
|
|
7
|
-
import { S as STEP_ARTIFACTS } from '../shared/luca.
|
|
8
|
-
import { p as phasePathFor } from '../shared/luca.
|
|
6
|
+
import 'node:path';
|
|
7
|
+
import { l as lucaStateClaimOwnerTool, S as STEP_ARTIFACTS } from '../shared/luca.BTcIy-Mh.mjs';
|
|
8
|
+
import { p as phasePathFor } from '../shared/luca.B-w_fieK.mjs';
|
|
9
9
|
import 'node:crypto';
|
|
10
10
|
import 'node:module';
|
|
11
11
|
import 'node:url';
|
|
@@ -94,7 +94,29 @@ const READONLY_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
94
94
|
"echo",
|
|
95
95
|
"printf",
|
|
96
96
|
"true",
|
|
97
|
-
"false"
|
|
97
|
+
"false",
|
|
98
|
+
// Read-only text filters. These read stdin/files and write to stdout —
|
|
99
|
+
// they never mutate files on their own. Omitting them made any pipeline
|
|
100
|
+
// through a filter (e.g. `find . | sort`) promote to bash-mutate via the
|
|
101
|
+
// unknown-command fallback, blocking read-only inspection in restrictive
|
|
102
|
+
// phases (v13 run report, M1). `tee`/`xargs` are deliberately EXCLUDED:
|
|
103
|
+
// `tee` writes files and `xargs` runs an arbitrary (possibly mutating)
|
|
104
|
+
// command, so they stay conservative.
|
|
105
|
+
"sort",
|
|
106
|
+
"uniq",
|
|
107
|
+
"cut",
|
|
108
|
+
"tr",
|
|
109
|
+
"comm",
|
|
110
|
+
"diff",
|
|
111
|
+
"jq",
|
|
112
|
+
"rg",
|
|
113
|
+
"column",
|
|
114
|
+
"nl",
|
|
115
|
+
"tac",
|
|
116
|
+
"rev",
|
|
117
|
+
"paste",
|
|
118
|
+
"fold",
|
|
119
|
+
"join"
|
|
98
120
|
]);
|
|
99
121
|
const GIT_READONLY_SUBCOMMANDS = /* @__PURE__ */ new Set([
|
|
100
122
|
"status",
|
|
@@ -191,6 +213,16 @@ const PKG_MUTATE_PATTERNS = [
|
|
|
191
213
|
["pnpm", "add"]
|
|
192
214
|
];
|
|
193
215
|
const ALWAYS_DENIED_COMMANDS = /* @__PURE__ */ new Set(["eval", "source", "."]);
|
|
216
|
+
const LUCA_TOPLEVEL_READ = /* @__PURE__ */ new Set(["version", "telemetry", "rules"]);
|
|
217
|
+
const LUCA_TOPLEVEL_WRITE = /* @__PURE__ */ new Set([
|
|
218
|
+
"init",
|
|
219
|
+
"vault:init",
|
|
220
|
+
"retro",
|
|
221
|
+
"claim-verify",
|
|
222
|
+
"classify",
|
|
223
|
+
"doctor",
|
|
224
|
+
"repair"
|
|
225
|
+
]);
|
|
194
226
|
const LUCA_READ_VERBS = /* @__PURE__ */ new Set([
|
|
195
227
|
"read",
|
|
196
228
|
"current",
|
|
@@ -202,7 +234,7 @@ const LUCA_READ_VERBS = /* @__PURE__ */ new Set([
|
|
|
202
234
|
"regression-check"
|
|
203
235
|
]);
|
|
204
236
|
const LUCA_NOUN_VERBS = {
|
|
205
|
-
state: /* @__PURE__ */ new Set(["read", "advance"]),
|
|
237
|
+
state: /* @__PURE__ */ new Set(["read", "advance", "claim-owner", "set-current-phase"]),
|
|
206
238
|
phase: /* @__PURE__ */ new Set(["current", "advance", "archive"]),
|
|
207
239
|
roadmap: /* @__PURE__ */ new Set(["read", "create"]),
|
|
208
240
|
preferences: /* @__PURE__ */ new Set(["read", "write"]),
|
|
@@ -227,7 +259,11 @@ function classifyLucaCommand(rest) {
|
|
|
227
259
|
const noun = rest.find((t) => !t.startsWith("-"));
|
|
228
260
|
if (!noun) return "bash-readonly";
|
|
229
261
|
const verbs = LUCA_NOUN_VERBS[noun];
|
|
230
|
-
if (!verbs)
|
|
262
|
+
if (!verbs) {
|
|
263
|
+
if (LUCA_TOPLEVEL_READ.has(noun)) return "bash-readonly";
|
|
264
|
+
if (LUCA_TOPLEVEL_WRITE.has(noun)) return "luca-write";
|
|
265
|
+
return void 0;
|
|
266
|
+
}
|
|
231
267
|
const afterNoun = rest.slice(rest.indexOf(noun) + 1);
|
|
232
268
|
const verb = afterNoun.find((t) => !t.startsWith("-"));
|
|
233
269
|
if (!verb || !verbs.has(verb)) {
|
|
@@ -499,9 +535,21 @@ async function handleStageGateHook(opts) {
|
|
|
499
535
|
}
|
|
500
536
|
const toolName = parsed.tool_name ?? parsed.toolName;
|
|
501
537
|
const toolInput = parsed.tool_input ?? parsed.toolInput;
|
|
538
|
+
const sessionId = parsed.session_id ?? parsed.sessionId;
|
|
502
539
|
const cwd = opts.cwd ?? process.cwd();
|
|
503
540
|
const homedir = opts.homedir ?? process.env.HOME;
|
|
504
541
|
const state = await loadCurrentState({ cwd });
|
|
542
|
+
if (toolName === "Bash" && sessionId && state.ownerSessionId !== sessionId && isStateAdvanceCommand(
|
|
543
|
+
toolInput?.command ?? ""
|
|
544
|
+
)) {
|
|
545
|
+
try {
|
|
546
|
+
await lucaStateClaimOwnerTool.handler({ sessionId }, { cwd });
|
|
547
|
+
state.ownerSessionId = sessionId;
|
|
548
|
+
} catch (err) {
|
|
549
|
+
log(`stage-gate: owner stamp skipped (${err.message})`);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
const isBystander = Boolean(state.ownerSessionId) && Boolean(sessionId) && state.ownerSessionId !== sessionId;
|
|
505
553
|
const phase = coarsePhaseOf(state.pipelineStep);
|
|
506
554
|
if (phase === "IDLE") {
|
|
507
555
|
log(
|
|
@@ -517,7 +565,7 @@ async function handleStageGateHook(opts) {
|
|
|
517
565
|
log(`stage-gate: ${toolName} without file_path \u2014 allowing`);
|
|
518
566
|
return { exitCode: 0, toolName, toolInput, decision: "allow" };
|
|
519
567
|
}
|
|
520
|
-
const relTarget =
|
|
568
|
+
const relTarget = toLucaRelative(targetPath, cwd);
|
|
521
569
|
const pc = classifyWritePath(targetPath, { homedir, cwd });
|
|
522
570
|
if (pc.class === "denied") {
|
|
523
571
|
pathBlockReason = `${toolName} to '${targetPath}' is always denied: ${pc.reason ?? "forbidden path"}`;
|
|
@@ -579,6 +627,12 @@ async function handleStageGateHook(opts) {
|
|
|
579
627
|
log("stage-gate: could not classify tool \u2014 allowing");
|
|
580
628
|
return { exitCode: 0, toolName, toolInput, decision: "allow" };
|
|
581
629
|
}
|
|
630
|
+
if (isBystander) {
|
|
631
|
+
log(
|
|
632
|
+
`stage-gate: session ${sessionId} is not the run owner (${state.ownerSessionId}) \u2014 exempting ${toolName} (category=${category}) from the phase=${phase} matrix`
|
|
633
|
+
);
|
|
634
|
+
return { exitCode: 0, toolName, toolInput, decision: "allow" };
|
|
635
|
+
}
|
|
582
636
|
const allowed = isToolAllowed({ phase, category });
|
|
583
637
|
if (!allowed) {
|
|
584
638
|
const msg = `stage-gate BLOCK: ${toolName} (category=${category}) is not allowed in phase=${phase} (pipelineStep=${state.pipelineStep})`;
|
|
@@ -596,6 +650,22 @@ async function handleStageGateHook(opts) {
|
|
|
596
650
|
);
|
|
597
651
|
return { exitCode: 0, toolName, toolInput, decision: "allow" };
|
|
598
652
|
}
|
|
653
|
+
function isStateAdvanceCommand(command) {
|
|
654
|
+
if (!command.includes("advance")) return false;
|
|
655
|
+
let entries;
|
|
656
|
+
try {
|
|
657
|
+
entries = parse(command);
|
|
658
|
+
} catch {
|
|
659
|
+
return false;
|
|
660
|
+
}
|
|
661
|
+
const toks = entries.filter((e) => typeof e === "string");
|
|
662
|
+
for (let i = 0; i <= toks.length - 3; i += 1) {
|
|
663
|
+
if (toks[i] === "luca" && toks[i + 1] === "state" && toks[i + 2] === "advance") {
|
|
664
|
+
return true;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
return false;
|
|
668
|
+
}
|
|
599
669
|
const FIXED_PHASE_FILE_ARTIFACTS = /* @__PURE__ */ new Set([
|
|
600
670
|
"research",
|
|
601
671
|
"context",
|
package/dist/chunks/init.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as p from '@clack/prompts';
|
|
2
2
|
import { defineCommand, runMain } from 'citty';
|
|
3
3
|
import { existsSync, chmodSync } from 'node:fs';
|
|
4
|
-
import { mkdir,
|
|
4
|
+
import { mkdir, readFile, writeFile, 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.DZxAJmyM.mjs';
|
|
7
7
|
import 'node:crypto';
|
|
8
8
|
import 'node:module';
|
|
9
9
|
import 'node:url';
|
|
@@ -25,16 +25,21 @@ async function writeProjectSkeleton(opts) {
|
|
|
25
25
|
});
|
|
26
26
|
const lucaDir = join(opts.cwd, ".luca");
|
|
27
27
|
await mkdir(lucaDir, { recursive: true });
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
28
|
+
const statePath = join(lucaDir, "state.json");
|
|
29
|
+
if (existsSync(statePath) && await isActiveState(statePath)) {
|
|
30
|
+
log(` skip: ${statePath} (active workflow \u2014 refusing to overwrite)`);
|
|
31
|
+
} else {
|
|
32
|
+
await writeIfMissing({
|
|
33
|
+
path: statePath,
|
|
34
|
+
contents: JSON.stringify(
|
|
35
|
+
lucaStateSchema.parse({ sessionId: generateRunId() }),
|
|
36
|
+
null,
|
|
37
|
+
2
|
|
38
|
+
) + "\n",
|
|
39
|
+
force: opts.force ?? false,
|
|
40
|
+
log
|
|
41
|
+
});
|
|
42
|
+
}
|
|
38
43
|
await writeIfMissing({
|
|
39
44
|
path: join(lucaDir, "config.json"),
|
|
40
45
|
contents: JSON.stringify(
|
|
@@ -50,6 +55,17 @@ async function writeProjectSkeleton(opts) {
|
|
|
50
55
|
log
|
|
51
56
|
});
|
|
52
57
|
}
|
|
58
|
+
async function isActiveState(statePath) {
|
|
59
|
+
try {
|
|
60
|
+
const raw = JSON.parse(await readFile(statePath, "utf-8"));
|
|
61
|
+
const step = raw.pipelineStep;
|
|
62
|
+
const roadmap = raw.roadmap;
|
|
63
|
+
const currentPhase = raw.currentPhase;
|
|
64
|
+
return typeof step === "string" && step !== "idle" || Array.isArray(roadmap) && roadmap.length > 0 || typeof currentPhase === "number" && currentPhase > 0;
|
|
65
|
+
} catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
53
69
|
async function writeIfMissing(args) {
|
|
54
70
|
if (existsSync(args.path) && !args.force) {
|
|
55
71
|
args.log(` skip: ${args.path} (already exists)`);
|
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.DZxAJmyM.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, c as lucaPhaseCurrentTool, d as lucaPhaseAdvanceTool, e as lucaPhaseArchiveTool } from '../shared/luca.lLQ2ZIAB.mjs';
|
|
12
|
+
import '../shared/luca.BTcIy-Mh.mjs';
|
|
12
13
|
import 'node:os';
|
|
13
|
-
import '../shared/luca.
|
|
14
|
-
import '../shared/luca.
|
|
15
|
-
import '../shared/luca.
|
|
14
|
+
import '../shared/luca.Cf93m-DM.mjs';
|
|
15
|
+
import '../shared/luca.D7w2gjQ5.mjs';
|
|
16
|
+
import '../shared/luca.B-w_fieK.mjs';
|
|
16
17
|
import '../shared/luca.CQ3g1xrD.mjs';
|
|
17
|
-
import '../shared/luca.Djs7oPPj.mjs';
|
|
18
18
|
|
|
19
19
|
const currentCommand = 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.DZxAJmyM.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 { f as readJsonPayload, r as runWriteHandler, o as lucaPrReviewDetectConvergenceTool, p as lucaPrReviewFilterStaleTool, q as lucaPrReviewRegressionCheckTool } from '../shared/luca.lLQ2ZIAB.mjs';
|
|
12
|
+
import '../shared/luca.BTcIy-Mh.mjs';
|
|
12
13
|
import 'node:os';
|
|
13
|
-
import '../shared/luca.
|
|
14
|
-
import '../shared/luca.
|
|
15
|
-
import '../shared/luca.
|
|
14
|
+
import '../shared/luca.Cf93m-DM.mjs';
|
|
15
|
+
import '../shared/luca.D7w2gjQ5.mjs';
|
|
16
|
+
import '../shared/luca.B-w_fieK.mjs';
|
|
16
17
|
import '../shared/luca.CQ3g1xrD.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.
|
|
3
|
+
import '../shared/luca.DZxAJmyM.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 { f as readJsonPayload, r as runWriteHandler, i as lucaPreferencesReadTool, j as lucaPreferencesWriteTool } from '../shared/luca.lLQ2ZIAB.mjs';
|
|
12
|
+
import '../shared/luca.BTcIy-Mh.mjs';
|
|
12
13
|
import 'node:os';
|
|
13
|
-
import '../shared/luca.
|
|
14
|
-
import '../shared/luca.
|
|
15
|
-
import '../shared/luca.
|
|
14
|
+
import '../shared/luca.Cf93m-DM.mjs';
|
|
15
|
+
import '../shared/luca.D7w2gjQ5.mjs';
|
|
16
|
+
import '../shared/luca.B-w_fieK.mjs';
|
|
16
17
|
import '../shared/luca.CQ3g1xrD.mjs';
|
|
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.DZxAJmyM.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.DZxAJmyM.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 { f as readJsonPayload, r as runWriteHandler, s as lucaRepoCleanupApplyTool } from '../shared/luca.lLQ2ZIAB.mjs';
|
|
12
|
+
import '../shared/luca.BTcIy-Mh.mjs';
|
|
12
13
|
import 'node:os';
|
|
13
|
-
import '../shared/luca.
|
|
14
|
-
import '../shared/luca.
|
|
15
|
-
import '../shared/luca.
|
|
14
|
+
import '../shared/luca.Cf93m-DM.mjs';
|
|
15
|
+
import '../shared/luca.D7w2gjQ5.mjs';
|
|
16
|
+
import '../shared/luca.B-w_fieK.mjs';
|
|
16
17
|
import '../shared/luca.CQ3g1xrD.mjs';
|
|
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.DZxAJmyM.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.BiHycbFi.mjs';
|
|
11
|
+
import { l as listRuns } from '../shared/luca.D7w2gjQ5.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.0ssL9rcP.mjs';
|
|
16
|
+
import '../shared/luca.B-w_fieK.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.DZxAJmyM.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 { f as readJsonPayload, r as runWriteHandler, g as lucaRoadmapReadTool, h as lucaRoadmapCreateTool } from '../shared/luca.lLQ2ZIAB.mjs';
|
|
12
|
+
import '../shared/luca.BTcIy-Mh.mjs';
|
|
12
13
|
import 'node:os';
|
|
13
|
-
import '../shared/luca.
|
|
14
|
-
import '../shared/luca.
|
|
15
|
-
import '../shared/luca.
|
|
14
|
+
import '../shared/luca.Cf93m-DM.mjs';
|
|
15
|
+
import '../shared/luca.D7w2gjQ5.mjs';
|
|
16
|
+
import '../shared/luca.B-w_fieK.mjs';
|
|
16
17
|
import '../shared/luca.CQ3g1xrD.mjs';
|
|
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.DZxAJmyM.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.BiHycbFi.mjs';
|
|
12
|
+
import { l as listRuns } from '../shared/luca.D7w2gjQ5.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.0ssL9rcP.mjs';
|
|
17
|
+
import '../shared/luca.B-w_fieK.mjs';
|
|
18
18
|
import 'consola';
|
|
19
19
|
|
|
20
20
|
let tsModuleCache = void 0;
|