@alecsibilia/luca 13.0.0-alpha.3 → 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 +86 -10
- 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/agents/debater.md +88 -0
- package/dist/claude/.claude/agents/discussion.md +13 -26
- package/dist/claude/.claude/agents/executor.md +6 -18
- package/dist/claude/.claude/agents/learner.md +31 -71
- package/dist/claude/.claude/agents/plan-reviewer.md +5 -9
- package/dist/claude/.claude/agents/researcher.md +5 -9
- package/dist/claude/.claude/agents/reviewer.md +18 -15
- package/dist/claude/.claude/agents/shadow-scanner.md +23 -26
- package/dist/claude/.claude/agents/test-writer.md +89 -0
- package/dist/claude/.claude/agents/verifier.md +5 -5
- package/dist/claude/.claude/commands/gh-pr-address.md +4 -4
- package/dist/claude/.claude/commands/lu-review.md +1 -1
- package/dist/claude/.claude/commands/lu.md +5 -5
- package/dist/claude/.claude/commands/milestone-new.md +1 -1
- package/dist/claude/.claude/commands/phase-execute.md +1 -1
- package/dist/claude/.claude/commands/phase-plan.md +1 -1
- package/dist/claude/.claude/commands/repo-cleanup.md +8 -5
- 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/autopilot/SKILL.md +22 -32
- package/dist/claude/skills/gh-pr-address/SKILL.md +4 -4
- package/dist/claude/skills/lu/SKILL.md +8 -8
- package/dist/claude/skills/lu-review/SKILL.md +1 -1
- package/dist/claude/skills/luca-write-surface/SKILL.md +8 -3
- package/dist/claude/skills/milestone-audit/SKILL.md +41 -61
- package/dist/claude/skills/milestone-complete/SKILL.md +1 -1
- package/dist/claude/skills/phase-discuss/SKILL.md +5 -5
- package/dist/claude/skills/phase-execute/SKILL.md +60 -67
- package/dist/claude/skills/phase-plan/SKILL.md +11 -13
- package/dist/claude/skills/phase-research/SKILL.md +1 -1
- package/dist/claude/skills/post-init-tour/SKILL.md +1 -1
- package/dist/claude/skills/project-new/SKILL.md +19 -77
- package/dist/claude/skills/quick/SKILL.md +2 -8
- package/dist/claude/skills/repo-audit/SKILL.md +5 -5
- package/dist/claude/skills/repo-cleanup/SKILL.md +8 -5
- package/dist/claude/skills/session-plan/SKILL.md +9 -9
- package/dist/claude/skills/workflow-save/SKILL.md +4 -4
- package/dist/index.mjs +1 -1
- package/dist/shared/{luca.BQXFn5yo.mjs → luca.0ssL9rcP.mjs} +2 -2
- package/dist/shared/{luca.pqZahLS5.mjs → luca.B-w_fieK.mjs} +1 -1
- package/dist/shared/luca.BTcIy-Mh.mjs +183 -0
- package/dist/shared/{luca.BhM9TDAo.mjs → luca.BiHycbFi.mjs} +3 -3
- package/dist/shared/{luca.BH2GZl5z.mjs → luca.Cf93m-DM.mjs} +1 -1
- package/dist/shared/{luca.CuvqWf4b.mjs → luca.D7w2gjQ5.mjs} +2 -2
- package/dist/shared/{luca.DXUcpbIe.mjs → luca.DZxAJmyM.mjs} +28 -2
- package/dist/shared/{luca.DykMxS_D.mjs → luca.lLQ2ZIAB.mjs} +159 -100
- 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,17 +213,28 @@ 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",
|
|
197
229
|
"list",
|
|
198
230
|
"guard",
|
|
231
|
+
"aggregate",
|
|
199
232
|
"filter-stale",
|
|
200
233
|
"detect-convergence",
|
|
201
234
|
"regression-check"
|
|
202
235
|
]);
|
|
203
236
|
const LUCA_NOUN_VERBS = {
|
|
204
|
-
state: /* @__PURE__ */ new Set(["read", "advance"]),
|
|
237
|
+
state: /* @__PURE__ */ new Set(["read", "advance", "claim-owner", "set-current-phase"]),
|
|
205
238
|
phase: /* @__PURE__ */ new Set(["current", "advance", "archive"]),
|
|
206
239
|
roadmap: /* @__PURE__ */ new Set(["read", "create"]),
|
|
207
240
|
preferences: /* @__PURE__ */ new Set(["read", "write"]),
|
|
@@ -215,13 +248,22 @@ const LUCA_NOUN_VERBS = {
|
|
|
215
248
|
checks: /* @__PURE__ */ new Set(["run"]),
|
|
216
249
|
branch: /* @__PURE__ */ new Set(["guard"]),
|
|
217
250
|
workflow: /* @__PURE__ */ new Set(["reset"]),
|
|
218
|
-
confidence: /* @__PURE__ */ new Set(["log"])
|
|
251
|
+
confidence: /* @__PURE__ */ new Set(["log"]),
|
|
252
|
+
// Read-side surfaces over the per-phase verify.json files.
|
|
253
|
+
verification: /* @__PURE__ */ new Set(["read", "aggregate"])
|
|
219
254
|
};
|
|
220
255
|
function classifyLucaCommand(rest) {
|
|
256
|
+
if (rest.some((t) => ["--help", "-h", "--version"].includes(t))) {
|
|
257
|
+
return "bash-readonly";
|
|
258
|
+
}
|
|
221
259
|
const noun = rest.find((t) => !t.startsWith("-"));
|
|
222
260
|
if (!noun) return "bash-readonly";
|
|
223
261
|
const verbs = LUCA_NOUN_VERBS[noun];
|
|
224
|
-
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
|
+
}
|
|
225
267
|
const afterNoun = rest.slice(rest.indexOf(noun) + 1);
|
|
226
268
|
const verb = afterNoun.find((t) => !t.startsWith("-"));
|
|
227
269
|
if (!verb || !verbs.has(verb)) {
|
|
@@ -493,9 +535,21 @@ async function handleStageGateHook(opts) {
|
|
|
493
535
|
}
|
|
494
536
|
const toolName = parsed.tool_name ?? parsed.toolName;
|
|
495
537
|
const toolInput = parsed.tool_input ?? parsed.toolInput;
|
|
538
|
+
const sessionId = parsed.session_id ?? parsed.sessionId;
|
|
496
539
|
const cwd = opts.cwd ?? process.cwd();
|
|
497
540
|
const homedir = opts.homedir ?? process.env.HOME;
|
|
498
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;
|
|
499
553
|
const phase = coarsePhaseOf(state.pipelineStep);
|
|
500
554
|
if (phase === "IDLE") {
|
|
501
555
|
log(
|
|
@@ -511,7 +565,7 @@ async function handleStageGateHook(opts) {
|
|
|
511
565
|
log(`stage-gate: ${toolName} without file_path \u2014 allowing`);
|
|
512
566
|
return { exitCode: 0, toolName, toolInput, decision: "allow" };
|
|
513
567
|
}
|
|
514
|
-
const relTarget =
|
|
568
|
+
const relTarget = toLucaRelative(targetPath, cwd);
|
|
515
569
|
const pc = classifyWritePath(targetPath, { homedir, cwd });
|
|
516
570
|
if (pc.class === "denied") {
|
|
517
571
|
pathBlockReason = `${toolName} to '${targetPath}' is always denied: ${pc.reason ?? "forbidden path"}`;
|
|
@@ -573,6 +627,12 @@ async function handleStageGateHook(opts) {
|
|
|
573
627
|
log("stage-gate: could not classify tool \u2014 allowing");
|
|
574
628
|
return { exitCode: 0, toolName, toolInput, decision: "allow" };
|
|
575
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
|
+
}
|
|
576
636
|
const allowed = isToolAllowed({ phase, category });
|
|
577
637
|
if (!allowed) {
|
|
578
638
|
const msg = `stage-gate BLOCK: ${toolName} (category=${category}) is not allowed in phase=${phase} (pipelineStep=${state.pipelineStep})`;
|
|
@@ -590,6 +650,22 @@ async function handleStageGateHook(opts) {
|
|
|
590
650
|
);
|
|
591
651
|
return { exitCode: 0, toolName, toolInput, decision: "allow" };
|
|
592
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
|
+
}
|
|
593
669
|
const FIXED_PHASE_FILE_ARTIFACTS = /* @__PURE__ */ new Set([
|
|
594
670
|
"research",
|
|
595
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;
|