@litfamily/litclaude 1.0.7 β 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 +8 -2
- package/README.md +16 -9
- package/README_ko-KR.md +16 -9
- package/docs/assets/readme/badge-version.svg +1 -1
- package/docs/hooks.md +10 -10
- package/package.json +1 -1
- package/plugins/litclaude/.claude-plugin/plugin.json +1 -1
- package/plugins/litclaude/bin/litclaude-hook.js +51 -8
- 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/lib/canonical-skill-resources.mjs +1 -1
- package/plugins/litclaude/lib/hud-accent-palette.mjs +2 -2
- package/plugins/litclaude/lib/hud-ignition.mjs +74 -0
- 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/litwork/SKILL.md +2 -2
- package/scripts/qa-real-surface-lib.mjs +3 -2
- package/scripts/strip-ansi.mjs +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.8
|
|
4
|
+
|
|
5
|
+
- Paint the activation logo and its `π₯ LIT IGNITED Β· <discipline> π₯` label with a bold truecolor gradient that runs from ignition orange through the HUD hot pink to electric cyan. The hook sets the colour depth itself because its output is always piped, so terminal detection cannot drop it to monochrome; `NO_COLOR` still prints plain text, and the reply line the model is asked to print stays free of escape codes.
|
|
6
|
+
- Show a bold, ignition-orange `π₯ LIT IGNITED Β· <discipline> π₯` mark in the HUD status line whenever the prompt hook activates a LitClaude discipline. The prompt hook records the selected discipline per session under `litclaude-hud/` in the per-user temp directory (`LITCLAUDE_HUD_STATE_ROOT` overrides it; the repository state root and home directory stay untouched), and the HUD reads that record back, so the mark reflects the hook's decision rather than model output. Turns without an activation clear the record and the mark disappears.
|
|
7
|
+
- Ask model replies to start with `π₯ **LIT IGNITED Β· <discipline>** π₯`, while hook messages and the HUD render the same activation mark without Markdown.
|
|
8
|
+
|
|
3
9
|
## 1.0.7
|
|
4
10
|
|
|
5
11
|
- Add the animated cover to both README pages, with a static cover for reduced-motion settings.
|
|
@@ -85,9 +91,9 @@
|
|
|
85
91
|
fallback, and plain text for non-UTF-8 or dumb terminals. Keep the install-plan
|
|
86
92
|
frame and add `--help`. Respect NO_COLOR, piped output, JSON, and CI.
|
|
87
93
|
- Render a standard mark once per session through the SessionStart system message
|
|
88
|
-
and
|
|
94
|
+
and an ignition mark with the discipline on prompt activation. Preserve the session
|
|
89
95
|
receipt across resume and compaction. Model replies begin with exactly one
|
|
90
|
-
|
|
96
|
+
`π₯ **LIT IGNITED Β· <discipline>** π₯` probe line; the model does not redraw the harness logo.
|
|
91
97
|
Refresh skill-resource pins and verify runtime closures before the major version transition.
|
|
92
98
|
|
|
93
99
|
- Rename skills: `hyperplan` β `lit-crucible`, `init-deep` β `lit-init`,
|
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
<p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
2
|
-
<p align="center"><a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
1
|
+
<p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.8/docs/assets/cover.webp" /><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.8/docs/assets/cover-motion.webp" width="100%" alt="LitClaude cover art. An orange signal moves through orbital paths above the CLAUDE CODE wordmark. The static family cover appears for reduced-motion preference." /></picture></p>
|
|
2
|
+
<p align="center"><a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.8/docs/assets/cover.webp">View the static cover</a></p>
|
|
3
3
|
|
|
4
4
|
<h1 align="center">LitClaude</h1>
|
|
5
5
|
<p align="center"><strong>Keep the work lit.</strong></p>
|
|
@@ -39,12 +39,12 @@
|
|
|
39
39
|
|
|
40
40
|
</details>
|
|
41
41
|
|
|
42
|
-
<p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
43
|
-
<p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
42
|
+
<p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.8/docs/assets/litclaude-wordmark.svg" width="480" alt="LITCLAUDE display type" /></p>
|
|
43
|
+
<p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.8/docs/assets/litclaude-clay-icon.png" width="160" alt="LitClaude clay mark" /></p>
|
|
44
44
|
|
|
45
45
|
<p align="center">
|
|
46
|
-
<img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
47
|
-
<a href="./LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
46
|
+
<img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.8/docs/assets/readme/badge-version.svg" alt="1.0.8" />
|
|
47
|
+
<a href="./LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.8/docs/assets/readme/badge-license.svg" alt="MIT license" /></a>
|
|
48
48
|
</p>
|
|
49
49
|
|
|
50
50
|
<p align="center">
|
|
@@ -355,13 +355,13 @@ npm exec --yes --package @litfamily/litclaude@latest -- litclaude install
|
|
|
355
355
|
For a reproducible install, pin the current package version:
|
|
356
356
|
|
|
357
357
|
```bash
|
|
358
|
-
npm view @litfamily/litclaude@1.0.
|
|
358
|
+
npm view @litfamily/litclaude@1.0.8 version
|
|
359
359
|
```
|
|
360
360
|
|
|
361
|
-
If that lookup returns `1.0.
|
|
361
|
+
If that lookup returns `1.0.8`, the exact install is available:
|
|
362
362
|
|
|
363
363
|
```bash
|
|
364
|
-
npm exec --yes --package @litfamily/litclaude@1.0.
|
|
364
|
+
npm exec --yes --package @litfamily/litclaude@1.0.8 -- litclaude install
|
|
365
365
|
```
|
|
366
366
|
|
|
367
367
|
Otherwise, wait for explicit human publication before using that pin. Check the
|
|
@@ -413,6 +413,13 @@ Interactive installation previews the available HUD accents. The LitClaude HUD
|
|
|
413
413
|
uses `[π₯LITCLAUDE vX.Y.Z]`, a compact `ctx [βββ]` bar, and a `5h [ββ] 4% β»`
|
|
414
414
|
rate-limit reset countdown. Set `LITCLAUDE_HUD_ACCENT` before installation to
|
|
415
415
|
choose an accent.
|
|
416
|
+
When the prompt hook activates a LitClaude discipline, the HUD adds a bold,
|
|
417
|
+
ignition-orange `π₯ LIT IGNITED Β· lit-loop π₯` mark right after the brand until
|
|
418
|
+
the next turn without an activation; the hook records the selected discipline
|
|
419
|
+
per session under `litclaude-hud/` in the per-user temp directory, never in the
|
|
420
|
+
repository or your home directory (`LITCLAUDE_HUD_STATE_ROOT` overrides the location).
|
|
421
|
+
The reply starts with `π₯ **LIT IGNITED Β· <discipline>** π₯`; the hook system
|
|
422
|
+
message and HUD display the same mark without Markdown.
|
|
416
423
|
|
|
417
424
|
HUD appearance and color capability are independent. By default (`dark`) the
|
|
418
425
|
model, context, usage, reset, and Git text carry the selected accent, usage
|
package/README_ko-KR.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
<p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
2
|
-
<p align="center"><a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
1
|
+
<p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.8/docs/assets/cover.webp" /><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.8/docs/assets/cover-motion.webp" width="100%" alt="LitClaude cover art. An orange signal moves through orbital paths above the CLAUDE CODE wordmark. The static family cover appears for reduced-motion preference." /></picture></p>
|
|
2
|
+
<p align="center"><a href="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.8/docs/assets/cover.webp">μ μ§ νμ§ λ³΄κΈ°</a></p>
|
|
3
3
|
|
|
4
4
|
<h1 align="center">LitClaude</h1>
|
|
5
5
|
<p align="center"><strong>Keep the work lit.</strong></p>
|
|
@@ -39,12 +39,12 @@
|
|
|
39
39
|
|
|
40
40
|
</details>
|
|
41
41
|
|
|
42
|
-
<p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
43
|
-
<p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
42
|
+
<p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.8/docs/assets/litclaude-wordmark.svg" width="480" alt="LITCLAUDE λμ€νλ μ΄ νμ
" /></p>
|
|
43
|
+
<p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.8/docs/assets/litclaude-clay-icon.png" width="160" alt="LitClaude ν΄λ μ΄ λ§ν¬" /></p>
|
|
44
44
|
|
|
45
45
|
<p align="center">
|
|
46
|
-
<img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
47
|
-
<a href="./LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.
|
|
46
|
+
<img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.8/docs/assets/readme/badge-version.svg" alt="1.0.8" />
|
|
47
|
+
<a href="./LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litclaude@1.0.8/docs/assets/readme/badge-license.svg" alt="MIT license" /></a>
|
|
48
48
|
</p>
|
|
49
49
|
|
|
50
50
|
<p align="center">
|
|
@@ -350,13 +350,13 @@ npm exec --yes --package @litfamily/litclaude@latest -- litclaude install
|
|
|
350
350
|
μ€μΉλ₯Ό μ¬ννλ €λ©΄ registryμμ νμ¬ package versionμ μ‘°νν λ€ κ³ μ ν©λλ€.
|
|
351
351
|
|
|
352
352
|
```bash
|
|
353
|
-
npm view @litfamily/litclaude@1.0.
|
|
353
|
+
npm view @litfamily/litclaude@1.0.8 version
|
|
354
354
|
```
|
|
355
355
|
|
|
356
|
-
μ‘°ν κ²°κ³Όκ° `1.0.
|
|
356
|
+
μ‘°ν κ²°κ³Όκ° `1.0.8`μ΄λ©΄ exact installμ μ¬μ©ν μ μμ΅λλ€.
|
|
357
357
|
|
|
358
358
|
```bash
|
|
359
|
-
npm exec --yes --package @litfamily/litclaude@1.0.
|
|
359
|
+
npm exec --yes --package @litfamily/litclaude@1.0.8 -- litclaude install
|
|
360
360
|
```
|
|
361
361
|
|
|
362
362
|
κ·Έλ μ§ μμΌλ©΄ λͺ
μμ μΈ human publicationμ κΈ°λ€λ¦½λλ€. Pinμ κ·Έ λ€μ μ¬μ©ν©λλ€.
|
|
@@ -389,6 +389,13 @@ Interactive μ€μΉμμλ HUD accent ν보λ₯Ό ν°λ―Έλμμ 미리 λ³Ό μ
|
|
|
389
389
|
LitClaude HUDλ `[π₯LITCLAUDE vX.Y.Z]`, `ctx [βββ]` context bar,
|
|
390
390
|
`5h [ββ] 4% β»` rate-limit reset countdownμ μ¬μ©ν©λλ€. μ€μΉ μ μ
|
|
391
391
|
`LITCLAUDE_HUD_ACCENT`λ₯Ό μ§μ ν΄ accentλ₯Ό μ νν μ μμ΅λλ€.
|
|
392
|
+
prompt hookμ΄ LitClaude disciplineμ νμ±ννλ©΄ HUDλ brand λ°λ‘ λ€μ κ΅΅μ
|
|
393
|
+
ignition-orange `π₯ LIT IGNITED Β· lit-loop π₯` νμλ₯Ό λΆμ΄κ³ , νμ±νκ° μλ λ€μ
|
|
394
|
+
ν΄μμ μ§μλλ€. hookμ μ νλ disciplineμ μΈμ
λ³λ‘ μ¬μ©μ μμ λλ ν°λ¦¬μ
|
|
395
|
+
`litclaude-hud/`μ κΈ°λ‘νκ³ (μ μ₯μμ ν λλ ν°λ¦¬λ 건λλ¦¬μ§ μμ)
|
|
396
|
+
`LITCLAUDE_HUD_STATE_ROOT`λ‘ μμΉλ₯Ό λ°κΏ μ μμ΅λλ€.
|
|
397
|
+
λͺ¨λΈ μλ΅μ `π₯ **LIT IGNITED Β· <discipline>** π₯`λ‘ μμνλ©°, hook system
|
|
398
|
+
messageμ HUDλ Markdown μμ΄ κ°μ νμλ₯Ό λ³΄μ¬ μ€λλ€.
|
|
392
399
|
|
|
393
400
|
HUDμ λ°°κ²½ μ€μ κ³Ό ν°λ―Έλ μμ μ§μ μμ€μ λ³κ°μ
λλ€. κΈ°λ³Έκ°(`dark`)μμλ model,
|
|
394
401
|
context, usage, reset, Git κΈμμ μ νν accentκ° λ€μ΄κ°κ³ , μ¬μ©λ νΌμΌνΈλ μμ€μ
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="146" height="20" role="img" aria-label="release: 1.0.
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="146" height="20" role="img" aria-label="release: 1.0.8"><title>release: 1.0.8</title><g shape-rendering="crispEdges"><rect width="49" height="20" fill="#080d14"/><rect x="49" width="97" height="20" fill="#ff6337"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="255" y="140" textLength="390" transform="scale(.1)">release</text><text x="965" y="140" textLength="870" transform="scale(.1)" fill="#080D14">1.0.8</text></g></svg>
|
package/docs/hooks.md
CHANGED
|
@@ -51,7 +51,7 @@ verdicts: [PASS, FAIL, BLOCKED]
|
|
|
51
51
|
## #contract.outputs
|
|
52
52
|
|
|
53
53
|
- Claude Code hook JSON containing `continue: true`, `hookSpecificOutput.hookEventName`, and route-specific `additionalContext`.
|
|
54
|
-
- Optional `systemMessage` for the once-per-session mark and active route
|
|
54
|
+
- Optional `systemMessage` for the once-per-session mark and active route ignition marks.
|
|
55
55
|
- `DELIVERABLE_HEDGE_VIOLATION` as `PostToolUse` `additionalContext` after a client-deliverable write contains a matched limitation phrase; the file has already been written, so the response asks Claude to revise it rather than claiming the write was prevented.
|
|
56
56
|
- `BLOCKED:` text for natural-language start-work, unavailable native goal binding, disabled Dynamic workflow, or gated agent-team setup.
|
|
57
57
|
- Unavailable native goal binding also includes `READY_TO_PASTE` and one bounded `/goal` command for the user to copy, paste, and send; the hook never enters or submits it.
|
|
@@ -273,7 +273,7 @@ lit-scientific-visualization
|
|
|
273
273
|
```
|
|
274
274
|
|
|
275
275
|
When a LIT trigger is present, the hook returns additional context containing
|
|
276
|
-
`LITWORK MODE ENABLED` and a visible
|
|
276
|
+
`LITWORK MODE ENABLED` and a visible `π₯ LIT IGNITED Β· <discipline> π₯` system
|
|
277
277
|
message. That context is guidance for Claude Code; it is not executed as a
|
|
278
278
|
command. Slash commands and slash-command mentions are native Claude Code
|
|
279
279
|
surfaces and do not activate this prompt hook; code spans, substrings, and
|
|
@@ -316,8 +316,8 @@ against another process with the same uid.
|
|
|
316
316
|
|
|
317
317
|
`handoff` is a separate exact-bare route: only the complete prompt `handoff`
|
|
318
318
|
after outer whitespace activates `Skill(lit-handoff)` and injects the complete
|
|
319
|
-
canonical bundled source. Its system message shows
|
|
320
|
-
|
|
319
|
+
canonical bundled source. Its system message shows `π₯ LIT IGNITED Β· lit-handoff π₯`;
|
|
320
|
+
the model begins with exactly one `π₯ **LIT IGNITED Β· lit-handoff** π₯` probe line. Explanatory mentions, quoted or fenced
|
|
321
321
|
text, compound prompts, `/litclaude:lit-handoff`, and secret-bearing multiline
|
|
322
322
|
content do not activate the hook. The slash command remains a native Claude
|
|
323
323
|
Code command surface.
|
|
@@ -325,8 +325,8 @@ Code command surface.
|
|
|
325
325
|
Scientific visualization has one exact-bare UserPromptSubmit route: only the
|
|
326
326
|
complete prompt `lit-scientific-visualization` after outer whitespace activates
|
|
327
327
|
`Skill(lit-scientific-visualization)`, injects the full adapter and canonical
|
|
328
|
-
source, and shows
|
|
329
|
-
The model begins with exactly one
|
|
328
|
+
source, and shows `π₯ LIT IGNITED Β· lit-scientific-visualization π₯` in its system
|
|
329
|
+
message. The model begins with exactly one `π₯ **LIT IGNITED Β· lit-scientific-visualization** π₯` probe line.
|
|
330
330
|
Generic visualization, plot, chart, figure, and scientific visualization prose,
|
|
331
331
|
mentions, quoted or fenced text, mixed prompts, near misses, and
|
|
332
332
|
`/litclaude:lit-scientific-visualization` text do not activate the prompt hook.
|
|
@@ -495,11 +495,11 @@ or symlinked cwd and missing project roots also suppress decoration; unsafe root
|
|
|
495
495
|
state never falls back to a nested state directory.
|
|
496
496
|
A compact event never repeats the session mark.
|
|
497
497
|
|
|
498
|
-
Activated UserPromptSubmit routes render the
|
|
499
|
-
|
|
498
|
+
Activated UserPromptSubmit routes render the plain mark
|
|
499
|
+
`π₯ LIT IGNITED Β· <discipline> π₯` in `systemMessage`. Inactive prompts stay silent.
|
|
500
500
|
`additionalContext` requires the model's reply to begin with exactly one
|
|
501
|
-
|
|
502
|
-
the
|
|
501
|
+
`π₯ **LIT IGNITED Β· <discipline>** π₯` line. The system mark and reply probe are
|
|
502
|
+
separate outputs; the model must not draw ASCII art or emit a second probe.
|
|
503
503
|
|
|
504
504
|
Hook JSON uses uncolored rows. CLI output uses the 44Γ20 Ignition B banner and
|
|
505
505
|
native product column inside the existing installer frame; `--help` and doctor
|
package/package.json
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
import { existsSync, lstatSync, readFileSync } from "node:fs";
|
|
4
4
|
import { dirname, extname, join, resolve } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
-
import { standard, micro, supportsBlocks } from "../lib/lit-mark.mjs";
|
|
6
|
+
import { standard, micro, colorMode, supportsBlocks } from "../lib/lit-mark.mjs";
|
|
7
|
+
import { NEON_END, NEON_START } from "../lib/hud-accent-palette.mjs";
|
|
8
|
+
import { ignitionMark, writeIgnitionState } from "../lib/hud-ignition.mjs";
|
|
7
9
|
import { renameAliases, renameNote } from "../lib/rename-aliases.mjs";
|
|
8
10
|
import { transcriptHasContextPressure } from "../lib/context-pressure.mjs";
|
|
9
11
|
import { extractMutatedFilePaths, serializeUntrustedData } from "../lib/mutated-file-paths.mjs";
|
|
@@ -114,11 +116,36 @@ const writeContext = (additionalContext, systemMessage, shouldContinue = true) =
|
|
|
114
116
|
);
|
|
115
117
|
};
|
|
116
118
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const
|
|
119
|
+
const activationStops = Object.freeze([Object.freeze([255, 99, 55]), NEON_START, NEON_END]);
|
|
120
|
+
|
|
121
|
+
const lerp = (stops, t) => {
|
|
122
|
+
const segment = Math.min(stops.length - 2, Math.floor(t * (stops.length - 1)));
|
|
123
|
+
const progress = t * (stops.length - 1) - segment;
|
|
124
|
+
return stops[segment].map((value, channel) => Math.round(value + (stops[segment + 1][channel] - value) * progress));
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const paint = (text) => {
|
|
128
|
+
const chars = [...text];
|
|
129
|
+
const length = chars.length;
|
|
130
|
+
return `\x1b[1m${chars.map((char, index) => {
|
|
131
|
+
if (char === " ") return char;
|
|
132
|
+
const [red, green, blue] = lerp(activationStops, length === 1 ? 0 : index / (length - 1));
|
|
133
|
+
return `\x1b[38;2;${red};${green};${blue}m${char}`;
|
|
134
|
+
}).join("")}\x1b[0m`;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// Claude Code renders ANSI in activation systemMessage; the model probe remains markdown text.
|
|
138
|
+
const activationMessage = (discipline) => {
|
|
139
|
+
if (!supportsBlocks()) return `\nLIT\n${ignitionMark(discipline)}`;
|
|
140
|
+
if (colorMode({ isTTY: true }) === "none") {
|
|
141
|
+
return `\n${micro.map((row, index) => index === 2 ? `${row} ${ignitionMark(discipline)}` : row).join("\n")}`;
|
|
142
|
+
}
|
|
143
|
+
const width = Math.max(...micro.map((row) => [...row.trimEnd()].length));
|
|
144
|
+
const rows = micro.map((row) => row.trimEnd().padEnd(width));
|
|
145
|
+
const label = `LIT IGNITED Β· ${discipline}`;
|
|
146
|
+
return `\n${rows.map((row, index) => index === 2 ? `${paint(row)} π₯ ${paint(label)} π₯` : paint(row)).join("\n")}`;
|
|
147
|
+
};
|
|
148
|
+
const probeInstruction = (discipline) => `Begin your reply with the exact probe line \`${ignitionMark(discipline, { markdown: true })}\` on its own line, exactly once before anything else. The harness status mark is a separate plain-text surface; do not draw ASCII art or repeat the probe.`;
|
|
122
149
|
|
|
123
150
|
const plainWordBoundary = /^[A-Za-z0-9]$/u;
|
|
124
151
|
const compoundWordBoundary = /^[A-Za-z0-9_-]$/u;
|
|
@@ -403,7 +430,7 @@ const handoffContext = () => {
|
|
|
403
430
|
}
|
|
404
431
|
|
|
405
432
|
return [
|
|
406
|
-
|
|
433
|
+
`HANDOFF MODE ENABLED: ${probeInstruction("lit-handoff")}`,
|
|
407
434
|
"Treat this exact bare prompt as an explicit request for /litclaude:lit-handoff and Skill(lit-handoff).",
|
|
408
435
|
llmContractReference,
|
|
409
436
|
`Canonical source root: ${inertFilesystemData(canonicalRoot)}. Read and follow the complete canonical source body below; resolve its template, example, and eval resources relative to this absolute installed source root rather than the process cwd or ~/skills.`,
|
|
@@ -424,7 +451,7 @@ const scientificVisualizationContext = () => {
|
|
|
424
451
|
}
|
|
425
452
|
|
|
426
453
|
return [
|
|
427
|
-
|
|
454
|
+
`SCIENTIFIC VISUALIZATION MODE ENABLED: ${probeInstruction("lit-scientific-visualization")}`,
|
|
428
455
|
"Treat this exact bare prompt as an explicit request for /litclaude:lit-scientific-visualization and Skill(lit-scientific-visualization).",
|
|
429
456
|
llmContractReference,
|
|
430
457
|
`Canonical source root: ${inertFilesystemData(canonicalRoot)}. Read and follow the complete canonical source body below; resolve its references, scripts, assets, evals, and tests relative to this absolute installed source root rather than the process cwd or ~/skills.`,
|
|
@@ -1023,6 +1050,22 @@ switch (eventName) {
|
|
|
1023
1050
|
const exactBareHandoff = isExactBareHandoff(prompt);
|
|
1024
1051
|
const exactBareScientificVisualization = isExactBareScientificVisualization(prompt);
|
|
1025
1052
|
const trigger = exactBareHandoff || exactBareScientificVisualization || isDiagnosticLiteralPrompt(prompt) ? undefined : findWorkflowTrigger(prompt);
|
|
1053
|
+
// The HUD status line reads this record back, so the visible ignition mark tracks the
|
|
1054
|
+
// discipline actually selected for this turn instead of anything the model chooses to draw.
|
|
1055
|
+
try {
|
|
1056
|
+
writeIgnitionState({
|
|
1057
|
+
sessionId: input.session_id,
|
|
1058
|
+
discipline: trustedResume
|
|
1059
|
+
? "start-work"
|
|
1060
|
+
: exactBareHandoff
|
|
1061
|
+
? "lit-handoff"
|
|
1062
|
+
: exactBareScientificVisualization
|
|
1063
|
+
? "lit-scientific-visualization"
|
|
1064
|
+
: trigger?.discipline ?? null,
|
|
1065
|
+
});
|
|
1066
|
+
} catch {
|
|
1067
|
+
// A HUD record is cosmetic; an unwritable home never alters the prompt hook.
|
|
1068
|
+
}
|
|
1026
1069
|
// The Stop-hook persistence gate only knows about a lit-plan turn through this record,
|
|
1027
1070
|
// so every other prompt clears it: the gate must never outlive the turn that armed it.
|
|
1028
1071
|
try {
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
normalizeHudAppearance,
|
|
13
13
|
} from "../lib/hud-accent-palette.mjs";
|
|
14
14
|
import { latestUsageTokens } from "../lib/cache-measurement.mjs";
|
|
15
|
+
import { readIgnitionState, renderIgnitionSegment } from "../lib/hud-ignition.mjs";
|
|
15
16
|
|
|
16
17
|
const pluginRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
17
18
|
const pluginManifestPath = join(pluginRoot, ".claude-plugin", "plugin.json");
|
|
@@ -263,7 +264,10 @@ const main = async () => {
|
|
|
263
264
|
appearance,
|
|
264
265
|
});
|
|
265
266
|
const contextText = `${text("ctx")} ${accent("[")}${makeContextBar(contextPct)}${accent("]")} ${text(`${contextPct}%/${maxK}k`)}`;
|
|
266
|
-
const
|
|
267
|
+
const ignition = renderIgnitionSegment(readIgnitionState(status.session_id), {
|
|
268
|
+
depth: plainOutput ? "plain" : colorDepth,
|
|
269
|
+
});
|
|
270
|
+
const line = `${prefix}${ignition ? ` ${ignition}` : ""} ${accent("|")} ${text(model)} ${accent(sep)} ${contextText}${usageText}${git ? ` ${accent(sep)} ${text("git")} ${text(git)}` : ""}`;
|
|
267
271
|
process.stdout.write(`${line}\n`);
|
|
268
272
|
|
|
269
273
|
const lastMessage = latestUserMessage(status.transcript_path);
|
|
@@ -17,7 +17,7 @@ verdicts: [PASS, DEGRADED, FAIL, BLOCKED]
|
|
|
17
17
|
|
|
18
18
|
| Field | Obligation | Evidence |
|
|
19
19
|
| --- | --- | --- |
|
|
20
|
-
| banner | Begin with exactly
|
|
20
|
+
| banner | Begin with exactly `π₯ **LIT IGNITED Β· lit-handoff** π₯`. | First visible response line. |
|
|
21
21
|
| skill | Load and follow `Skill(lit-handoff)`. | Route receipt. |
|
|
22
22
|
| source | Read the immutable bundled handoff `SKILL.md` completely. | Canonical source path. |
|
|
23
23
|
|
|
@@ -37,7 +37,7 @@ verdicts: [PASS, DEGRADED, FAIL, BLOCKED]
|
|
|
37
37
|
|
|
38
38
|
## #contract.procedure
|
|
39
39
|
|
|
40
|
-
1. Begin with
|
|
40
|
+
1. Begin with `π₯ **LIT IGNITED Β· lit-handoff** π₯`.
|
|
41
41
|
2. Load `Skill(lit-handoff)` and read its canonical vendored source completely.
|
|
42
42
|
3. Reconcile stale handoff prose with current live state.
|
|
43
43
|
4. Create or update only the correct continuation artifact.
|
|
@@ -73,4 +73,4 @@ body verbatim merely because it was generated.
|
|
|
73
73
|
|
|
74
74
|
Use `Skill(lit-handoff)` now. The first visible response line must be exactly:
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
`π₯ **LIT IGNITED Β· lit-handoff** π₯`
|
|
@@ -17,7 +17,7 @@ verdicts: [PASS, DEGRADED, FAIL, BLOCKED]
|
|
|
17
17
|
|
|
18
18
|
| Field | Obligation | Evidence |
|
|
19
19
|
| --- | --- | --- |
|
|
20
|
-
| banner | Begin with exactly
|
|
20
|
+
| banner | Begin with exactly `π₯ **LIT IGNITED Β· lit-scientific-visualization** π₯`. | First visible response line. |
|
|
21
21
|
| skill | Load `Skill(lit-scientific-visualization)`. | Route receipt. |
|
|
22
22
|
| runtime | Preflight without silent dependency installation. | PASS or DEGRADED report. |
|
|
23
23
|
|
|
@@ -71,4 +71,4 @@ their full scientific content.
|
|
|
71
71
|
|
|
72
72
|
Use `Skill(lit-scientific-visualization)` now. The first visible response line must be exactly:
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
`π₯ **LIT IGNITED Β· lit-scientific-visualization** π₯`
|
|
@@ -170,7 +170,7 @@ export const canonicalSkillResourceManifest = Object.freeze(
|
|
|
170
170
|
["skills/lit-team/SKILL.md", "6d4ca726d1240db7692ccc95802ab6abfd45588147ec663dafa1b3b233a08a13"],
|
|
171
171
|
["skills/lit-team/scripts/team.mjs", "a0be61f09cc1c10989b12709135ac4b99260496f840dcf58514478082e239fe7"],
|
|
172
172
|
["skills/litresearch/ATTRIBUTION.md", "1ed8b43d48a13d7fc106cbfd86bc1bac0316529bdac4e2e38043fafeae2a8e15"],
|
|
173
|
-
["skills/litwork/SKILL.md", "
|
|
173
|
+
["skills/litwork/SKILL.md", "5c5964d4df69c0e7cc7505f2dec38beed9413e79d64eb61f325012215e86d0ba"],
|
|
174
174
|
["skills/visual-qa/SKILL.md", "089d26a14800b461cfd628b4789f676308d5e09fe13e9e24632b8fd6305c8517"],
|
|
175
175
|
["skills/visual-qa/references/capture-playbook.md", "92cad16893118c9e878cabbb49dc2187049ec6e759fcc4e6006d79bdae998689"],
|
|
176
176
|
["skills/visual-qa/references/complete-contract.md", "8dd878975eb386b8b5d0b5439ed7bc50de9c4e3ee2aeff6d553c4299c5b30cb4"],
|
|
@@ -61,8 +61,8 @@ export const ansi16CodeForAccent = (value) => ({
|
|
|
61
61
|
// to bright-magenta bold; NO_COLOR is plain text. The π₯ is mandatory and the
|
|
62
62
|
// brand is accent-independent (LITCLAUDE_HUD_ACCENT still themes the HUD body).
|
|
63
63
|
const NEON_BRAND = "LITCLAUDE";
|
|
64
|
-
const NEON_START = [255, 45, 149]; // #ff2d95 hot pink
|
|
65
|
-
const NEON_END = [0, 229, 255]; // #00e5ff electric cyan
|
|
64
|
+
export const NEON_START = Object.freeze([255, 45, 149]); // #ff2d95 hot pink
|
|
65
|
+
export const NEON_END = Object.freeze([0, 229, 255]); // #00e5ff electric cyan
|
|
66
66
|
|
|
67
67
|
export const supportsTruecolor = (env = process.env) => {
|
|
68
68
|
// The portable signal: terminals that export COLORTERM=truecolor|24bit.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
|
|
5
|
+
// Per-session ignition record: the prompt hook writes it on every UserPromptSubmit and the HUD
|
|
6
|
+
// status line reads it back, so the status bar reflects the discipline actually selected for
|
|
7
|
+
// the current turn instead of anything the model chooses to draw. Mode is per turn and never
|
|
8
|
+
// durable, so the record lives in the per-user temp directory: not in the repository state
|
|
9
|
+
// root (activation must stay side-effect-free there) and not in the home directory.
|
|
10
|
+
|
|
11
|
+
const IGNITION_PALETTE = Object.freeze({
|
|
12
|
+
truecolor: "\x1b[38;2;255;99;55m",
|
|
13
|
+
"256": "\x1b[38;5;203m",
|
|
14
|
+
"16": "\x1b[91m",
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export const ignitionStateRoot = (env = process.env) => {
|
|
18
|
+
const override = env.LITCLAUDE_HUD_STATE_ROOT?.trim();
|
|
19
|
+
if (override) return override;
|
|
20
|
+
const tmp = env.TMPDIR?.trim() || tmpdir();
|
|
21
|
+
return join(tmp, "litclaude-hud");
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const safeSessionFile = (sessionId) => {
|
|
25
|
+
const raw = typeof sessionId === "string" && sessionId.trim() ? sessionId.trim() : "unknown-session";
|
|
26
|
+
return `${raw.replace(/[^A-Za-z0-9._-]/gu, "_").replace(/^\.+/u, "_")}.json`;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const ignitionStatePath = (sessionId, env = process.env) => join(ignitionStateRoot(env), safeSessionFile(sessionId));
|
|
30
|
+
|
|
31
|
+
export function ignitionMark(discipline, { markdown = false } = {}) {
|
|
32
|
+
const label = `LIT IGNITED Β· ${discipline}`;
|
|
33
|
+
return markdown ? `π₯ **${label}** π₯` : `π₯ ${label} π₯`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function writeIgnitionState({ sessionId, discipline }, env = process.env, now = () => new Date()) {
|
|
37
|
+
const root = ignitionStateRoot(env);
|
|
38
|
+
mkdirSync(root, { recursive: true });
|
|
39
|
+
const target = ignitionStatePath(sessionId, env);
|
|
40
|
+
const record = {
|
|
41
|
+
sessionId: typeof sessionId === "string" ? sessionId : null,
|
|
42
|
+
discipline: typeof discipline === "string" && discipline ? discipline : null,
|
|
43
|
+
at: now().toISOString(),
|
|
44
|
+
};
|
|
45
|
+
const staging = `${target}.${process.pid}.tmp`;
|
|
46
|
+
writeFileSync(staging, `${JSON.stringify(record)}\n`);
|
|
47
|
+
renameSync(staging, target);
|
|
48
|
+
return record;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function readIgnitionState(sessionId, env = process.env) {
|
|
52
|
+
const target = ignitionStatePath(sessionId, env);
|
|
53
|
+
if (!existsSync(target)) return null;
|
|
54
|
+
try {
|
|
55
|
+
const parsed = JSON.parse(readFileSync(target, "utf8"));
|
|
56
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
57
|
+
return {
|
|
58
|
+
sessionId: typeof parsed.sessionId === "string" ? parsed.sessionId : null,
|
|
59
|
+
discipline: typeof parsed.discipline === "string" && parsed.discipline ? parsed.discipline : null,
|
|
60
|
+
at: typeof parsed.at === "string" ? parsed.at : null,
|
|
61
|
+
};
|
|
62
|
+
} catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function renderIgnitionSegment(state, { depth = "plain" } = {}) {
|
|
68
|
+
const discipline = state?.discipline ?? null;
|
|
69
|
+
if (!discipline) return "";
|
|
70
|
+
const label = ignitionMark(discipline);
|
|
71
|
+
if (depth === "plain") return label;
|
|
72
|
+
const paint = IGNITION_PALETTE[depth] ?? IGNITION_PALETTE["256"];
|
|
73
|
+
return `\x1b[1m${paint}${label}\x1b[0m`;
|
|
74
|
+
}
|
|
@@ -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.
|
|
@@ -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
|
|
@@ -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";
|