@litfamily/litclaude 1.0.6 → 1.0.8
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/CHANGELOG.md +13 -7
- package/README.md +18 -38
- package/README_ko-KR.md +18 -37
- package/docs/assets/cover-motion.webp +0 -0
- package/docs/assets/readme/badge-version.svg +1 -1
- package/docs/hooks.md +10 -10
- package/docs/privacy.md +12 -17
- package/package.json +3 -1
- package/plugins/litclaude/.claude-plugin/plugin.json +1 -1
- package/plugins/litclaude/bin/litclaude-hook.js +71 -65
- package/plugins/litclaude/bin/litclaude-hud.js +5 -1
- package/plugins/litclaude/bin/litclaude-mcp.js +1 -1
- package/plugins/litclaude/commands/lit-handoff.md +3 -3
- package/plugins/litclaude/commands/lit-scientific-visualization.md +2 -2
- package/plugins/litclaude/hooks/hooks.json +4 -4
- package/plugins/litclaude/lib/canonical-skill-catalog.mjs +0 -1
- package/plugins/litclaude/lib/canonical-skill-resources.mjs +6 -28
- package/plugins/litclaude/lib/hud-accent-palette.mjs +2 -2
- package/plugins/litclaude/lib/hud-ignition.mjs +74 -0
- package/plugins/litclaude/lib/lit-plan-persistence.mjs +2 -1
- package/plugins/litclaude/lib/litgoal/paths.mjs +10 -8
- package/plugins/litclaude/lib/project-state-root.mjs +22 -0
- package/plugins/litclaude/lib/rules/session-state.mjs +2 -1
- package/plugins/litclaude/lib/start-work-cli.mjs +3 -3
- package/plugins/litclaude/lib/wikify-knowledge-cli.mjs +3 -1
- package/plugins/litclaude/lib/wikify-knowledge.mjs +6 -5
- package/plugins/litclaude/scripts/scaffold-plan.mjs +9 -3
- package/plugins/litclaude/skills/lit-handoff/SKILL.md +2 -2
- package/plugins/litclaude/skills/lit-scientific-visualization/SKILL.md +3 -3
- package/plugins/litclaude/skills/lit-team/scripts/team.mjs +4 -3
- package/plugins/litclaude/skills/litwork/SKILL.md +2 -2
- package/scripts/prepublish-test-gate.mjs +26 -0
- package/scripts/qa-real-surface-lib.mjs +3 -2
- package/scripts/strip-ansi.mjs +1 -0
- package/plugins/litclaude/lib/skill-loop/apply.mjs +0 -391
- package/plugins/litclaude/lib/skill-loop/authority.mjs +0 -129
- package/plugins/litclaude/lib/skill-loop/cli.mjs +0 -67
- package/plugins/litclaude/lib/skill-loop/common.mjs +0 -280
- package/plugins/litclaude/lib/skill-loop/config.mjs +0 -91
- package/plugins/litclaude/lib/skill-loop/curator.mjs +0 -670
- package/plugins/litclaude/lib/skill-loop/hook-runtime.mjs +0 -188
- package/plugins/litclaude/lib/skill-loop/hook-state.mjs +0 -484
- package/plugins/litclaude/lib/skill-loop/ledger.mjs +0 -834
- package/plugins/litclaude/lib/skill-loop/mutation-transaction.mjs +0 -529
- package/plugins/litclaude/lib/skill-loop/proposal-reader.mjs +0 -26
- package/plugins/litclaude/lib/skill-loop/proposal-record.mjs +0 -104
- package/plugins/litclaude/lib/skill-loop/proposal-store.mjs +0 -187
- package/plugins/litclaude/lib/skill-loop/proposals.mjs +0 -26
- package/plugins/litclaude/lib/skill-loop/review-runner.mjs +0 -13
- package/plugins/litclaude/lib/skill-loop/review-transaction.mjs +0 -358
- package/plugins/litclaude/lib/skill-loop/review.mjs +0 -223
- package/plugins/litclaude/lib/skill-loop/usage.mjs +0 -218
- package/plugins/litclaude/lib/skill-observer.mjs +0 -693
- package/plugins/litclaude/skills/skill-observer/SKILL.md +0 -155
- package/plugins/litclaude/skills/skill-observer/references/review-contract.md +0 -77
- package/plugins/litclaude/skills/skill-observer/scripts/skill-loop.mjs +0 -10
|
@@ -23,6 +23,7 @@ import { isAbsolute, join, relative, resolve } from "node:path";
|
|
|
23
23
|
import { acquireOwnerLock, OwnerLockError, releaseOwnerLock } from "../owner-lock.mjs";
|
|
24
24
|
import { POST_COMPACT_REINJECTION_BUDGET } from "./constants.mjs";
|
|
25
25
|
import { pathIdentity, samePathIdentity } from "../secure-path-read.mjs";
|
|
26
|
+
import { resolveProjectStateRoot } from "../project-state-root.mjs";
|
|
26
27
|
|
|
27
28
|
const MAX_TRACKED_KEYS = 500;
|
|
28
29
|
const MAX_STATE_BYTES = 256 * 1024;
|
|
@@ -42,7 +43,7 @@ const isSameOrChildPath = (parentPath, childPath) => {
|
|
|
42
43
|
const emptyState = () => ({ injected: [], postCompactCount: 0 });
|
|
43
44
|
|
|
44
45
|
const safeStateDirectory = (projectRoot, { create }) => {
|
|
45
|
-
const root =
|
|
46
|
+
const root = resolveProjectStateRoot(projectRoot);
|
|
46
47
|
const rootStats = lstatSync(root);
|
|
47
48
|
if (rootStats.isSymbolicLink() || !rootStats.isDirectory()) throw new Error("unsafe project root");
|
|
48
49
|
const realRoot = realpathSync.native(root);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolveProjectStateRoot } from "./project-state-root.mjs";
|
|
2
2
|
import {
|
|
3
3
|
cancelStartWork,
|
|
4
4
|
completeStartWork,
|
|
@@ -141,7 +141,7 @@ const emitError = (io, error, command) => {
|
|
|
141
141
|
return status;
|
|
142
142
|
};
|
|
143
143
|
|
|
144
|
-
export const runStartWorkCli = (argv, io = { stdout: process.stdout, stderr: process.stderr }, defaultRoot =
|
|
144
|
+
export const runStartWorkCli = (argv, io = { stdout: process.stdout, stderr: process.stderr }, defaultRoot = resolveProjectStateRoot()) => {
|
|
145
145
|
const [command, ...args] = argv;
|
|
146
146
|
if (!command || command === "--help" || command === "-h") {
|
|
147
147
|
io.stdout.write(helpText);
|
|
@@ -149,7 +149,7 @@ export const runStartWorkCli = (argv, io = { stdout: process.stdout, stderr: pro
|
|
|
149
149
|
}
|
|
150
150
|
try {
|
|
151
151
|
assertExactOptions(command, args);
|
|
152
|
-
const root =
|
|
152
|
+
const root = resolveProjectStateRoot(value(args, "--root") ?? defaultRoot);
|
|
153
153
|
const result = execute(root, command, args);
|
|
154
154
|
io.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
155
155
|
return 0;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
|
+
|
|
3
|
+
import { resolveProjectStateRoot } from "./project-state-root.mjs";
|
|
2
4
|
import {
|
|
3
5
|
captureKnowledgeEvent,
|
|
4
6
|
queryKnowledge,
|
|
@@ -116,7 +118,7 @@ const emitError = (io, error, command, outputJson) => {
|
|
|
116
118
|
export const runWikifyKnowledgeCli = (
|
|
117
119
|
argv,
|
|
118
120
|
io = { stdout: process.stdout, stderr: process.stderr },
|
|
119
|
-
defaultRoot =
|
|
121
|
+
defaultRoot = resolveProjectStateRoot(),
|
|
120
122
|
) => {
|
|
121
123
|
const [command, ...args] = argv;
|
|
122
124
|
if (!command || command === "--help" || command === "-h") {
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
} from "./secure-path-read.mjs";
|
|
26
26
|
import { decodeStrictUtf8, parseStrictJson } from "./strict-json.mjs";
|
|
27
27
|
import { containsSecret, URI_USERINFO_PATTERN } from "./secret-shapes.mjs";
|
|
28
|
+
import { resolveProjectStateRoot } from "./project-state-root.mjs";
|
|
28
29
|
|
|
29
30
|
const MAX_LEDGER_BYTES = 4 * 1024 * 1024;
|
|
30
31
|
const MAX_TEXT_BYTES = 512;
|
|
@@ -116,7 +117,7 @@ const deterministicId = (kind, text, provenance, evidence) => {
|
|
|
116
117
|
};
|
|
117
118
|
|
|
118
119
|
const canonicalRoot = (root) => {
|
|
119
|
-
const candidate =
|
|
120
|
+
const candidate = resolveProjectStateRoot(root ?? process.cwd());
|
|
120
121
|
try {
|
|
121
122
|
const details = lstatSync(candidate);
|
|
122
123
|
if (details.isSymbolicLink() || !details.isDirectory()) throw new Error("invalid root");
|
|
@@ -137,7 +138,7 @@ const ensurePrivateDirectory = (path) => {
|
|
|
137
138
|
mkdirSync(path, { mode: 0o700 });
|
|
138
139
|
};
|
|
139
140
|
|
|
140
|
-
export const knowledgeDirectory = (root =
|
|
141
|
+
export const knowledgeDirectory = (root = resolveProjectStateRoot()) => {
|
|
141
142
|
const canonical = canonicalRoot(root);
|
|
142
143
|
const litDirectory = join(canonical, ".litclaude");
|
|
143
144
|
const directory = join(litDirectory, "knowledge");
|
|
@@ -150,8 +151,8 @@ export const knowledgeDirectory = (root = process.cwd()) => {
|
|
|
150
151
|
}
|
|
151
152
|
return directory;
|
|
152
153
|
};
|
|
153
|
-
export const knowledgeClaimsPath = (root =
|
|
154
|
-
export const knowledgeSettingsPath = (root =
|
|
154
|
+
export const knowledgeClaimsPath = (root = resolveProjectStateRoot()) => join(knowledgeDirectory(root), "claims.jsonl");
|
|
155
|
+
export const knowledgeSettingsPath = (root = resolveProjectStateRoot()) => join(knowledgeDirectory(root), "settings.json");
|
|
155
156
|
|
|
156
157
|
const prepareKnowledgeDirectory = (root) => {
|
|
157
158
|
const canonical = canonicalRoot(root);
|
|
@@ -510,7 +511,7 @@ const normalizeEvent = (event, surface) => {
|
|
|
510
511
|
};
|
|
511
512
|
};
|
|
512
513
|
|
|
513
|
-
export const readCaptureSettings = (root =
|
|
514
|
+
export const readCaptureSettings = (root = resolveProjectStateRoot()) => {
|
|
514
515
|
return withClaimsLock(root, (directory) => {
|
|
515
516
|
const path = join(directory, "settings.json");
|
|
516
517
|
const snapshot = assertRegularStateFile(path);
|
|
@@ -30,6 +30,7 @@ import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
|
30
30
|
import { fileURLToPath } from "node:url";
|
|
31
31
|
|
|
32
32
|
import { parsePlanTaskRows, planLinesOutsideFences } from "../lib/plan-task-rows.mjs";
|
|
33
|
+
import { resolveProjectStateRoot } from "../lib/project-state-root.mjs";
|
|
33
34
|
import { readRegularStable, samePathIdentity } from "../lib/secure-path-read.mjs";
|
|
34
35
|
|
|
35
36
|
/** Canonical plan section headers, in order. */
|
|
@@ -107,8 +108,9 @@ export function parseArgs(argv) {
|
|
|
107
108
|
|
|
108
109
|
/** Confine a write to `.litclaude/drafts/` or `plans/`, `.md` only. */
|
|
109
110
|
export function resolveSafePlanPath(cwd, relPath) {
|
|
110
|
-
const
|
|
111
|
-
const
|
|
111
|
+
const workspaceRoot = resolveProjectStateRoot(cwd);
|
|
112
|
+
const resolved = resolve(workspaceRoot, relPath);
|
|
113
|
+
const rel = relative(workspaceRoot, resolved);
|
|
112
114
|
if (rel.startsWith("..") || isAbsolute(rel)) {
|
|
113
115
|
throw new Error(`refused: path escapes the workspace root: ${relPath}`);
|
|
114
116
|
}
|
|
@@ -804,6 +806,7 @@ export async function writeGuarded(
|
|
|
804
806
|
onParentState,
|
|
805
807
|
} = {},
|
|
806
808
|
) {
|
|
809
|
+
cwd = resolveProjectStateRoot(cwd);
|
|
807
810
|
const target = resolveSafePlanPath(cwd, relPath);
|
|
808
811
|
const ownInterruption = interruption ?? createInterruptionContext();
|
|
809
812
|
let parentState;
|
|
@@ -874,6 +877,7 @@ export async function writeGuarded(
|
|
|
874
877
|
}
|
|
875
878
|
|
|
876
879
|
export async function scaffold(cwd, { slug, intent, reset = false, force = false, draftOnly = false, reviewRequired = false }) {
|
|
880
|
+
cwd = resolveProjectStateRoot(cwd);
|
|
877
881
|
const interruption = createInterruptionContext();
|
|
878
882
|
const created = [];
|
|
879
883
|
const parentStates = new Set();
|
|
@@ -1007,6 +1011,7 @@ export function checkPlanStructure(text) {
|
|
|
1007
1011
|
}
|
|
1008
1012
|
|
|
1009
1013
|
async function runCheck(checkPath, cwd) {
|
|
1014
|
+
cwd = resolveProjectStateRoot(cwd);
|
|
1010
1015
|
const target = resolveSafePlanPath(cwd, checkPath);
|
|
1011
1016
|
const read = readRegularStable(resolve(cwd), target, undefined, { maxBytes: MAX_PLAN_BYTES });
|
|
1012
1017
|
if (read.failure) {
|
|
@@ -1023,7 +1028,8 @@ async function runCheck(checkPath, cwd) {
|
|
|
1023
1028
|
return 1;
|
|
1024
1029
|
}
|
|
1025
1030
|
|
|
1026
|
-
export async function runScaffoldPlanCli(argv = process.argv, cwd =
|
|
1031
|
+
export async function runScaffoldPlanCli(argv = process.argv, cwd = resolveProjectStateRoot()) {
|
|
1032
|
+
cwd = resolveProjectStateRoot(cwd);
|
|
1027
1033
|
const parsed = parseArgs(argv);
|
|
1028
1034
|
if (parsed.mode === "check") {
|
|
1029
1035
|
return runCheck(parsed.checkPath, cwd);
|
|
@@ -17,7 +17,7 @@ verdicts: [PASS, DEGRADED, FAIL, BLOCKED]
|
|
|
17
17
|
|
|
18
18
|
| Field | Contract | Evidence |
|
|
19
19
|
| --- | --- | --- |
|
|
20
|
-
| activation | Begin the user-visible response with exactly
|
|
20
|
+
| activation | Begin the user-visible response with exactly `🔥 **LIT IGNITED · lit-handoff** 🔥`. | First response line and route receipt. |
|
|
21
21
|
| canonical source | Read the vendored handoff reference completely before acting: `SKILL.md` in the canonical `../../vendor/handoff/` directory. | Source path and destination decision. |
|
|
22
22
|
| completion | Create or update the correct continuation packet without exposing secrets. | Artifact path, checks, and `PASS`, `FAIL`, or `BLOCKED`. |
|
|
23
23
|
|
|
@@ -39,7 +39,7 @@ verdicts: [PASS, DEGRADED, FAIL, BLOCKED]
|
|
|
39
39
|
|
|
40
40
|
## #contract.procedure
|
|
41
41
|
|
|
42
|
-
1. Print
|
|
42
|
+
1. Print `🔥 **LIT IGNITED · lit-handoff** 🔥` as the first visible line.
|
|
43
43
|
2. Resolve every linked resource relative to this loaded `SKILL.md` through Claude Code's Skill resource root, never relative to the process cwd. For the exact-bare hook route, use the absolute installed source root injected by the hook. Never assume `~/skills` exists after package installation.
|
|
44
44
|
3. Read the vendored handoff reference `SKILL.md` in full. Follow every destination, stale-state, secret-redaction, and verification rule in that source without abbreviating it.
|
|
45
45
|
4. Inspect existing handoff files and live ledgers or JSONL surfaces before choosing the destination. Prefer live operational truth over stale prose.
|
|
@@ -17,7 +17,7 @@ verdicts: [PASS, DEGRADED, FAIL, BLOCKED]
|
|
|
17
17
|
|
|
18
18
|
| Field | Contract | Evidence |
|
|
19
19
|
| --- | --- | --- |
|
|
20
|
-
| activation | Begin the response with the exact
|
|
20
|
+
| activation | Begin the response with the exact probe `🔥 **LIT IGNITED · lit-scientific-visualization** 🔥`. | First visible response line. |
|
|
21
21
|
| canonical source | Read `../../vendor/scientific-visualization/SKILL.md` completely before plotting. | Source-root receipt. |
|
|
22
22
|
| runtime | Preflight Python and plotting dependencies without installing them. | PASS or DEGRADED doctor output. |
|
|
23
23
|
| completion | Produce and inspect the requested figure artifacts. | Files, dimensions, formats, DPI, and visual QA. |
|
|
@@ -35,14 +35,14 @@ verdicts: [PASS, DEGRADED, FAIL, BLOCKED]
|
|
|
35
35
|
| --- | --- | --- |
|
|
36
36
|
| direct-skill | Claude Code loads `Skill(lit-scientific-visualization)`. | Explicit user intent is required; there is no generic visualization auto-trigger. |
|
|
37
37
|
| command-routed | `/litclaude:lit-scientific-visualization` is invoked. | Follow the command and this full adapter. |
|
|
38
|
-
| hook-routed | The complete UserPromptSubmit prompt is exactly `lit-scientific-visualization` after outer whitespace. | Show
|
|
38
|
+
| hook-routed | The complete UserPromptSubmit prompt is exactly `lit-scientific-visualization` after outer whitespace. | Show `🔥 LIT IGNITED · lit-scientific-visualization 🔥` in the hook `systemMessage`, inject this adapter and the complete canonical source, and keep all mixed or near-miss prompts inert. |
|
|
39
39
|
| core-ready | Python and matplotlib are available. | Use packaged scripts and verify real exports. |
|
|
40
40
|
| degraded | Python or matplotlib is unavailable. | Report `DEGRADED:` with the missing capability; do not claim artifact creation. |
|
|
41
41
|
| optional-degraded | seaborn, pandas, scipy, plotly, kaleido, numpy, or MDAnalysis is missing. | Use a valid core fallback or report the specific blocked workflow. |
|
|
42
42
|
|
|
43
43
|
## #contract.procedure
|
|
44
44
|
|
|
45
|
-
1. Begin the reply with the exact
|
|
45
|
+
1. Begin the reply with the exact probe `🔥 **LIT IGNITED · lit-scientific-visualization** 🔥` on its own line. The exact-bare UserPromptSubmit route renders `🔥 LIT IGNITED · lit-scientific-visualization 🔥` as its plain-text hook `systemMessage`; the model probe appears exactly once. Do not treat generic visualization prose as equivalent invocation.
|
|
46
46
|
2. Resolve every linked resource relative to this loaded `SKILL.md` through Claude Code's Skill resource root, never relative to the process cwd. Never hard-code `~/skills` or the source checkout.
|
|
47
47
|
3. Read the [canonical `SKILL.md`](../../vendor/scientific-visualization/SKILL.md) completely, then read only the referenced source files needed for the requested figure. Preserve every restraint, including `rcparams()`, scatter-only semantics, journal sizing, legend treatment, grids, fonts, layout, and export requirements.
|
|
48
48
|
4. Resolve the [bundled doctor](../../bin/litclaude-scientific-visualization-doctor.js) as an installed Skill resource and invoke its absolute path with Node, or use `litclaude doctor`; never run a cwd-relative shell path. Never install Python, matplotlib, or optional packages silently. Ask before any dependency or environment mutation.
|
|
@@ -38,6 +38,7 @@ import { isAbsolute, join, relative, resolve } from "node:path";
|
|
|
38
38
|
import { pathToFileURL } from "node:url";
|
|
39
39
|
|
|
40
40
|
import { acquireOwnerLock, OwnerLockError, releaseOwnerLock } from "../../../lib/owner-lock.mjs";
|
|
41
|
+
import { resolveProjectStateRoot } from "../../../lib/project-state-root.mjs";
|
|
41
42
|
import { pathIdentity, samePathIdentity } from "../../../lib/secure-path-read.mjs";
|
|
42
43
|
|
|
43
44
|
const MIN_MEMBERS = 2;
|
|
@@ -61,7 +62,7 @@ const requireTeamId = (teamId) => {
|
|
|
61
62
|
return teamId;
|
|
62
63
|
};
|
|
63
64
|
|
|
64
|
-
export const teamsRoot = (cwd =
|
|
65
|
+
export const teamsRoot = (cwd = resolveProjectStateRoot()) => join(resolveProjectStateRoot(cwd), ".litclaude", "teams");
|
|
65
66
|
export const teamDir = (cwd, teamId) => join(teamsRoot(cwd), requireTeamId(teamId));
|
|
66
67
|
export const teamStatePath = (cwd, teamId) => join(teamDir(cwd, teamId), "team.json");
|
|
67
68
|
|
|
@@ -87,7 +88,7 @@ const isSameOrChildPath = (parentPath, childPath) => {
|
|
|
87
88
|
};
|
|
88
89
|
|
|
89
90
|
const safeDirectory = (cwd, components, { create }) => {
|
|
90
|
-
const root =
|
|
91
|
+
const root = resolveProjectStateRoot(cwd);
|
|
91
92
|
const rootStats = lstatSync(root);
|
|
92
93
|
if (rootStats.isSymbolicLink() || !rootStats.isDirectory()) throw new TeamError("workspace root is not a safe directory", 65);
|
|
93
94
|
const realRoot = realpathSync.native(root);
|
|
@@ -379,7 +380,7 @@ const archive = (cwd, args) => {
|
|
|
379
380
|
|
|
380
381
|
const commands = { init, "add-member": addMember, prompt, report, block, status, archive };
|
|
381
382
|
|
|
382
|
-
export const runTeamCli = (argv, io = { stdout: process.stdout, stderr: process.stderr }, cwd =
|
|
383
|
+
export const runTeamCli = (argv, io = { stdout: process.stdout, stderr: process.stderr }, cwd = resolveProjectStateRoot()) => {
|
|
383
384
|
const [command, ...rest] = argv;
|
|
384
385
|
if (!command || command === "--help" || command === "-h") {
|
|
385
386
|
io.stdout.write(`Usage: team.mjs <${Object.keys(commands).join("|")}> [...args]\n`);
|
|
@@ -583,8 +583,8 @@ history-safety detail when the operation grows past a single commit.
|
|
|
583
583
|
|
|
584
584
|
## Output discipline
|
|
585
585
|
|
|
586
|
-
- First line, literally:
|
|
587
|
-
anything else, exactly once. The harness
|
|
586
|
+
- First line, literally: `🔥 **LIT IGNITED · litwork** 🔥`, on its own line, before
|
|
587
|
+
anything else, exactly once. The harness shows its plain-text status mark separately; do not draw ASCII art or add a second probe line.
|
|
588
588
|
- After bootstrap in reader mode: the current result, decision, or next required
|
|
589
589
|
action. Keep the notepad path internal unless the request asks for it.
|
|
590
590
|
- During execution in reader mode, surface only a current result, material
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
|
|
3
|
+
const env = Object.fromEntries(
|
|
4
|
+
Object.entries(process.env).filter(([key]) => key.toLowerCase() !== "npm_config_dry_run"),
|
|
5
|
+
);
|
|
6
|
+
const npmExecPath = process.env.npm_execpath;
|
|
7
|
+
const result = npmExecPath
|
|
8
|
+
? spawnSync(process.execPath, [npmExecPath, "test"], { env, stdio: "inherit" })
|
|
9
|
+
: spawnSync(process.platform === "win32" ? "npm.cmd" : "npm", ["test"], {
|
|
10
|
+
env,
|
|
11
|
+
shell: process.platform === "win32",
|
|
12
|
+
stdio: "inherit",
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
if (result.error) {
|
|
16
|
+
console.error(`prepublish test gate could not start npm test: ${result.error.message}`);
|
|
17
|
+
process.exitCode = 1;
|
|
18
|
+
} else if (result.signal) {
|
|
19
|
+
console.error(`prepublish test gate interrupted by ${result.signal}`);
|
|
20
|
+
process.exitCode = 1;
|
|
21
|
+
} else if (Number.isInteger(result.status)) {
|
|
22
|
+
process.exitCode = result.status;
|
|
23
|
+
} else {
|
|
24
|
+
console.error("prepublish test gate received a non-integer npm test exit status");
|
|
25
|
+
process.exitCode = 1;
|
|
26
|
+
}
|
|
@@ -25,6 +25,7 @@ import { tmpdir } from "node:os";
|
|
|
25
25
|
import { join, resolve } from "node:path";
|
|
26
26
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
27
27
|
import { deflateSync } from "node:zlib";
|
|
28
|
+
import { stripAnsi } from "./strip-ansi.mjs";
|
|
28
29
|
|
|
29
30
|
export const repoRoot = resolve(fileURLToPath(new URL("..", import.meta.url)));
|
|
30
31
|
|
|
@@ -606,8 +607,8 @@ function phaseCorrect(phase, run) {
|
|
|
606
607
|
if (phase.id === "session_start") return context.startsWith("LitClaude rules loaded for ");
|
|
607
608
|
if (phase.id === "s1_activation") {
|
|
608
609
|
return /LITWORK MODE ENABLED/u.test(context)
|
|
609
|
-
&&
|
|
610
|
-
&&
|
|
610
|
+
&& /🔥 LIT IGNITED · lit-loop 🔥/u.test(stripAnsi(run.parsed.systemMessage ?? ""))
|
|
611
|
+
&& /🔥 \*\*LIT IGNITED · lit-loop\*\* 🔥/u.test(context);
|
|
611
612
|
}
|
|
612
613
|
return run.parsed.systemMessage === undefined
|
|
613
614
|
&& context === "LitClaude prompt hook checked: no workflow activation.";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { stripVTControlCharacters as stripAnsi } from "node:util";
|