litclaude-ai 0.4.3 → 0.4.4

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.
Files changed (28) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +87 -5
  3. package/README_ko-KR.md +87 -5
  4. package/RELEASE_CHECKLIST.md +7 -7
  5. package/bin/litclaude-ai.js +35 -11
  6. package/bin/litfamily-banner.mjs +32 -0
  7. package/package.json +1 -1
  8. package/plugins/litclaude/.claude-plugin/plugin.json +1 -1
  9. package/plugins/litclaude/bin/litclaude-mcp.js +1 -1
  10. package/plugins/litclaude/lib/canonical-skill-resources.mjs +14 -14
  11. package/plugins/litclaude/lib/owner-lock.mjs +78 -17
  12. package/plugins/litclaude/lib/rules/engine.mjs +2 -2
  13. package/plugins/litclaude/lib/rules/session-state.mjs +2 -2
  14. package/plugins/litclaude/lib/secure-path-read.mjs +18 -0
  15. package/plugins/litclaude/lib/skill-loop/common.mjs +6 -5
  16. package/plugins/litclaude/lib/skill-loop/curator.mjs +36 -2
  17. package/plugins/litclaude/lib/skill-loop/mutation-transaction.mjs +29 -5
  18. package/plugins/litclaude/lib/skill-loop/proposal-store.mjs +36 -4
  19. package/plugins/litclaude/lib/skill-loop/review.mjs +4 -3
  20. package/plugins/litclaude/lib/skill-observer.mjs +127 -35
  21. package/plugins/litclaude/lib/start-work-lifecycle.mjs +2 -2
  22. package/plugins/litclaude/lib/wikify-knowledge.mjs +44 -16
  23. package/plugins/litclaude/scripts/scaffold-plan.mjs +259 -41
  24. package/plugins/litclaude/skills/browser-drive/scripts/capability-probe.mjs +24 -3
  25. package/plugins/litclaude/skills/teammode/scripts/team.mjs +2 -2
  26. package/scripts/qa-claude-plugin-smoke.sh +36 -8
  27. package/scripts/qa-portable-install.sh +38 -15
  28. package/scripts/qa-real-surface-lib.mjs +4 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.4 - 2026-09-02 — inode-reuse hardening and Linux rotation safety
4
+
5
+ - Bind regular-file reads and state transitions to ctime/birthtime-aware identities,
6
+ and quarantine/content-check destructive cleanup across owner locks, rule/session/team
7
+ state, skill-loop records, knowledge, observer, review, and scaffold paths. Add
8
+ deterministic inode-reuse regression coverage for the affected readers and cleanup.
9
+ - Make directory pins Linux-safe: directory identity excludes mutable child-driven ctime
10
+ and retained descriptors are compared with final pathname samples. Quarantine short-lived
11
+ scaffold locks so a legitimate next owner can rotate in without being mistaken for residue.
12
+ - Keep browser-drive teardown fail-closed around process-group reuse while accepting
13
+ already-gone or non-owned groups, and add regression coverage for concurrent observer
14
+ first-use writers and normal rotation. Regenerate canonical resource hashes for the
15
+ changed runtime assets so installer integrity checks cover the hardening.
16
+ - During convergence, three Linux-only false-denial cases were captured and resolved:
17
+ directory ctime churn, process-group ID reuse, and lock rotation. Regular files pin
18
+ ctime/birthtime; directories do not, because child creation legitimately changes
19
+ directory ctime. This is a local release candidate only; no publish, tag, or push
20
+ was performed.
21
+
3
22
  ## 0.4.3 - 2026-08-31 — packed-payload integrity and channel routing
4
23
 
5
24
  - Add packed-payload substance, cross-product parity, and referenced-path checks so
package/README.md CHANGED
@@ -1,4 +1,17 @@
1
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/litclaude-ai@0.4.3/cover.png" width="100%" alt="LitClaude — Claude Code-native workflow package" /></p>
1
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/litclaude-ai@0.4.4/cover.png" width="100%" alt="LitClaude — Claude Code-native workflow package" /></p>
2
+
3
+ ```text
4
+ ██╗ ██╗████████╗
5
+ ██║ ██║╚══██╔══╝
6
+ ██║ ██║ ██║
7
+ ███████╗██║ ██║
8
+ ╚══════╝╚═╝ ╚═╝
9
+ ██████╗██╗ █████╗ ██╗ ██╗██████╗ ███████╗
10
+ ██╔════╝██║ ██╔══██╗██║ ██║██╔══██╗██╔════╝
11
+ ██║ ██║ ███████║██║ ██║██║ ██║█████╗
12
+ ╚██████╗███████╗██╔══██║╚██████╔╝██████╔╝███████╗
13
+ ╚═════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝
14
+ ```
2
15
 
3
16
  <h1 align="center">LitClaude</h1>
4
17
  <p align="center">
@@ -9,7 +22,7 @@
9
22
  </p>
10
23
  <p align="center">
11
24
  <img src="https://img.shields.io/badge/npm-litclaude--ai-cb3837" alt="npm: litclaude-ai" />
12
- <img src="https://img.shields.io/badge/version-0.4.3-2ea44f" alt="version 0.4.3" />
25
+ <img src="https://img.shields.io/badge/version-0.4.4-2ea44f" alt="version 0.4.4" />
13
26
  <img src="https://img.shields.io/badge/Claude%20Code-plugin-blueviolet" alt="Claude Code plugin" />
14
27
  <img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT license" />
15
28
  </p>
@@ -39,6 +52,35 @@ ordinary `claude` sessions.
39
52
  - Local MCP/LSP helpers, structured Wikify knowledge, and a managed HUD that
40
53
  can be safely removed with `uninstall`.
41
54
 
55
+ **The workflow closes on evidence.** A plan remains open until each item has a binary check, and a slice closes only after its real Claude surface produces evidence and its temporary QA resources are gone. A passing test is necessary, but it is not the finish line.
56
+
57
+ ```mermaid
58
+ flowchart TD
59
+ R["a request<br/>make it better"] --> DI["<b>deep-interview</b><br/>turn it into a decision-complete brief"]
60
+ DI --> P["<b>lit-plan</b><br/>objective · non-goals<br/>action / output / <b>binary verification</b>"]
61
+ P --> GATE{"user approves?"}
62
+ GATE -->|no| P
63
+ GATE -->|yes| SW["<b>start-work</b><br/>execute one slice"]
64
+
65
+ subgraph LOOP["each slice: RED to GREEN to SURFACE to CLEAN"]
66
+ SW --> RED["failing test first"]
67
+ RED --> GREEN["smallest change that passes"]
68
+ GREEN --> SURF["exercise the <b>real surface</b><br/>not just the test"]
69
+ SURF --> CLEAN["tear down · cleanup receipt"]
70
+ end
71
+
72
+ CLEAN --> EV{"evidence complete?"}
73
+ EV -->|"tests only"| SW
74
+ EV -->|"artifact + receipt"| RW["<b>review-work</b><br/>scope · evidence · payload<br/>security · real surface"]
75
+ RW -->|findings| SW
76
+ RW -->|clean| HO["<b>lit-handoff</b><br/>resumable packet"]
77
+
78
+ style GATE fill:#fff3cd,stroke:#856404
79
+ style EV fill:#fff3cd,stroke:#856404
80
+ style SURF fill:#d4edda,stroke:#155724
81
+ style RW fill:#d1ecf1,stroke:#0c5460
82
+ ```
83
+
42
84
  ## Install
43
85
 
44
86
  For the current published package:
@@ -50,13 +92,13 @@ npx --yes litclaude-ai@latest install
50
92
  For a reproducible install, pin the current package version:
51
93
 
52
94
  ```bash
53
- npm view litclaude-ai@0.4.3 version
95
+ npm view litclaude-ai@0.4.4 version
54
96
  ```
55
97
 
56
- If that lookup returns `0.4.3`, the exact install is available:
98
+ If that lookup returns `0.4.4`, the exact install is available:
57
99
 
58
100
  ```bash
59
- npx --yes litclaude-ai@0.4.3 install
101
+ npx --yes litclaude-ai@0.4.4 install
60
102
  ```
61
103
 
62
104
  Otherwise, wait for explicit human publication before using that pin. Check the
@@ -125,6 +167,30 @@ the hook; namespaced slash commands use Claude Code's native command surface and
125
167
  do not double-activate the hook. For an explicit skill invocation, use a route
126
168
  such as `/litclaude:lit-loop`.
127
169
 
170
+ **Where Claude Code hands control to LitClaude.** Session and tool events feed the rules, routing, authority, and ledger surfaces; together they expose the package's 34 skills, 17 commands, and 11 agents without hiding the host boundary.
171
+
172
+ ```mermaid
173
+ flowchart LR
174
+ subgraph CC["Claude Code"]
175
+ H1["SessionStart"]; H2["UserPromptSubmit"]; H3["PreToolUse"]
176
+ H4["PostToolUse"]; H5["Stop"]; H6["SubagentStart / SubagentStop"]; H7["SessionEnd"]
177
+ end
178
+ subgraph LC["LitClaude plugin"]
179
+ RULES["rules engine<br/>project rules into context"]
180
+ ROUTE["trigger routing<br/><code>lit</code> · <code>/litclaude:*</code>"]
181
+ AUTH["bounded authority<br/>pause on a new boundary"]
182
+ LEDGER[("durable ledger<br/><code>.litclaude/</code>")]
183
+ end
184
+ H1 --> RULES --> LEDGER
185
+ H2 --> ROUTE --> LEDGER
186
+ H3 --> AUTH
187
+ H4 --> LEDGER
188
+ H5 --> LEDGER
189
+ H6 --> LEDGER
190
+ H7 --> LEDGER
191
+ LC --> S["34 skills · 17 commands · 11 agents"]
192
+ ```
193
+
128
194
  ## Core routes
129
195
 
130
196
  | Type this | Purpose |
@@ -172,6 +238,22 @@ consolidates skills. SessionStart runs this maintenance only when project-local
172
238
  skill-loop usage state already exists; untouched projects receive no new
173
239
  `.litclaude` state.
174
240
 
241
+ **Why a fresh install can still execute the skills.** A self-contained skill needs an explicit allowlist reason, while a skill that names a corpus must carry that corpus inside the packed tarball. These payload gates prevent a checkout-only reference from becoming a user's runtime failure.
242
+
243
+ ```mermaid
244
+ flowchart LR
245
+ SK["a skill"] --> Q{"does it declare<br/>a capability?"}
246
+ Q -->|"self-contained<br/>procedure"| AL["explicit allowlist entry<br/>with a written reason"]
247
+ Q -->|"needs a corpus"| C["corpus must resolve<br/>inside the <b>packed payload</b>"]
248
+ AL --> G1
249
+ C --> G1["<b>payload-substance</b>"]
250
+ G1 --> G2["<b>cross-product parity</b><br/>one product cannot ship a stub<br/>where the family ships substance"]
251
+ G2 --> G3["<b>referenced-path resolution</b><br/>every path in a SKILL.md<br/>must exist in the tarball"]
252
+ G3 --> OK["installs and works<br/>on a machine that has<br/>nothing else"]
253
+ style C fill:#d4edda,stroke:#155724
254
+ style OK fill:#d4edda,stroke:#155724
255
+ ```
256
+
175
257
  `lit start work <plan>` is intentionally a `BLOCKED:` handoff. Use
176
258
  `/start-work` or `/litclaude:start-work` with the approved plan. `lit workflow`
177
259
  proposes a native `Workflow` and calls it only after user opt-in. LitClaude does not auto-type `/goal`
package/README_ko-KR.md CHANGED
@@ -1,4 +1,17 @@
1
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/litclaude-ai@0.4.3/cover.png" width="100%" alt="LitClaude — Claude Code-native workflow package" /></p>
1
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/litclaude-ai@0.4.4/cover.png" width="100%" alt="LitClaude — Claude Code-native workflow package" /></p>
2
+
3
+ ```text
4
+ ██╗ ██╗████████╗
5
+ ██║ ██║╚══██╔══╝
6
+ ██║ ██║ ██║
7
+ ███████╗██║ ██║
8
+ ╚══════╝╚═╝ ╚═╝
9
+ ██████╗██╗ █████╗ ██╗ ██╗██████╗ ███████╗
10
+ ██╔════╝██║ ██╔══██╗██║ ██║██╔══██╗██╔════╝
11
+ ██║ ██║ ███████║██║ ██║██║ ██║█████╗
12
+ ╚██████╗███████╗██╔══██║╚██████╔╝██████╔╝███████╗
13
+ ╚═════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝
14
+ ```
2
15
 
3
16
  <h1 align="center">LitClaude</h1>
4
17
  <p align="center">
@@ -9,7 +22,7 @@
9
22
  </p>
10
23
  <p align="center">
11
24
  <img src="https://img.shields.io/badge/npm-litclaude--ai-cb3837" alt="npm: litclaude-ai" />
12
- <img src="https://img.shields.io/badge/version-0.4.3-2ea44f" alt="version 0.4.3" />
25
+ <img src="https://img.shields.io/badge/version-0.4.4-2ea44f" alt="version 0.4.4" />
13
26
  <img src="https://img.shields.io/badge/Claude%20Code-plugin-blueviolet" alt="Claude Code plugin" />
14
27
  <img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT license" />
15
28
  </p>
@@ -40,6 +53,35 @@ state route, compact status-line HUD를 제공합니다. 한 번 설치하면
40
53
  - local MCP/LSP helper, 구조화된 Wikify knowledge, 안전하게 제거할 수 있는
41
54
  managed HUD
42
55
 
56
+ **이 workflow가 닫히는 조건을 한눈에 보세요.** 각 계획 항목에 binary check가 있어야 다음 단계로 갈 수 있고, 실제 Claude surface에서 evidence를 남기고 임시 QA resource까지 정리해야 하나의 slice가 끝납니다. Test가 통과했다는 사실만으로는 충분하지 않습니다.
57
+
58
+ ```mermaid
59
+ flowchart TD
60
+ R["a request<br/>make it better"] --> DI["<b>deep-interview</b><br/>turn it into a decision-complete brief"]
61
+ DI --> P["<b>lit-plan</b><br/>objective · non-goals<br/>action / output / <b>binary verification</b>"]
62
+ P --> GATE{"user approves?"}
63
+ GATE -->|no| P
64
+ GATE -->|yes| SW["<b>start-work</b><br/>execute one slice"]
65
+
66
+ subgraph LOOP["each slice: RED to GREEN to SURFACE to CLEAN"]
67
+ SW --> RED["failing test first"]
68
+ RED --> GREEN["smallest change that passes"]
69
+ GREEN --> SURF["exercise the <b>real surface</b><br/>not just the test"]
70
+ SURF --> CLEAN["tear down · cleanup receipt"]
71
+ end
72
+
73
+ CLEAN --> EV{"evidence complete?"}
74
+ EV -->|"tests only"| SW
75
+ EV -->|"artifact + receipt"| RW["<b>review-work</b><br/>scope · evidence · payload<br/>security · real surface"]
76
+ RW -->|findings| SW
77
+ RW -->|clean| HO["<b>lit-handoff</b><br/>resumable packet"]
78
+
79
+ style GATE fill:#fff3cd,stroke:#856404
80
+ style EV fill:#fff3cd,stroke:#856404
81
+ style SURF fill:#d4edda,stroke:#155724
82
+ style RW fill:#d1ecf1,stroke:#0c5460
83
+ ```
84
+
43
85
  ## 설치
44
86
 
45
87
  현재 공개된 package를 설치합니다.
@@ -52,13 +94,13 @@ npx --yes litclaude-ai@latest install
52
94
  뒤 고정합니다.
53
95
 
54
96
  ```bash
55
- npm view litclaude-ai@0.4.3 version
97
+ npm view litclaude-ai@0.4.4 version
56
98
  ```
57
99
 
58
- 조회 결과가 `0.4.3`이면 exact install을 사용할 수 있습니다.
100
+ 조회 결과가 `0.4.4`이면 exact install을 사용할 수 있습니다.
59
101
 
60
102
  ```bash
61
- npx --yes litclaude-ai@0.4.3 install
103
+ npx --yes litclaude-ai@0.4.4 install
62
104
  ```
63
105
 
64
106
  그렇지 않으면 명시적인 human publication을 기다립니다. Pin은 그 뒤에 사용합니다.
@@ -109,6 +151,30 @@ namespaced slash command는 Claude Code native command surface에서 처리되
109
151
  hook을 중복 활성화하지 않습니다. 명시적으로 skill을 실행하려면
110
152
  `/litclaude:lit-loop` 같은 route를 사용하세요.
111
153
 
154
+ **Claude Code와 LitClaude가 만나는 지점입니다.** Session과 tool event는 rules, routing, authority, ledger surface로 들어가며, 그 결과 34개 skill·17개 command·11개 agent가 host 경계를 넘지 않고 연결됩니다.
155
+
156
+ ```mermaid
157
+ flowchart LR
158
+ subgraph CC["Claude Code"]
159
+ H1["SessionStart"]; H2["UserPromptSubmit"]; H3["PreToolUse"]
160
+ H4["PostToolUse"]; H5["Stop"]; H6["SubagentStart / SubagentStop"]; H7["SessionEnd"]
161
+ end
162
+ subgraph LC["LitClaude plugin"]
163
+ RULES["rules engine<br/>project rules into context"]
164
+ ROUTE["trigger routing<br/><code>lit</code> · <code>/litclaude:*</code>"]
165
+ AUTH["bounded authority<br/>pause on a new boundary"]
166
+ LEDGER[("durable ledger<br/><code>.litclaude/</code>")]
167
+ end
168
+ H1 --> RULES --> LEDGER
169
+ H2 --> ROUTE --> LEDGER
170
+ H3 --> AUTH
171
+ H4 --> LEDGER
172
+ H5 --> LEDGER
173
+ H6 --> LEDGER
174
+ H7 --> LEDGER
175
+ LC --> S["34 skills · 17 commands · 11 agents"]
176
+ ```
177
+
112
178
  ## 주요 라우트
113
179
 
114
180
  | 입력 | 용도 |
@@ -156,6 +222,22 @@ backup한 다음 archive하는 것입니다. Skill을 delete하거나 consolidat
156
222
  있을 때만 실행되므로 untouched project에 새 `.litclaude` state를 만들지
157
223
  않습니다.
158
224
 
225
+ **아무것도 남아 있지 않은 machine에서도 skill이 작동하는 이유입니다.** Self-contained skill은 allowlist에 명시적인 근거가 있어야 하고, corpus를 참조하는 skill은 packed tarball 안에서 그 corpus를 찾아야 합니다. 이 payload gate가 checkout에만 남은 reference를 설치 후 장애로 만들지 않습니다.
226
+
227
+ ```mermaid
228
+ flowchart LR
229
+ SK["a skill"] --> Q{"does it declare<br/>a capability?"}
230
+ Q -->|"self-contained<br/>procedure"| AL["explicit allowlist entry<br/>with a written reason"]
231
+ Q -->|"needs a corpus"| C["corpus must resolve<br/>inside the <b>packed payload</b>"]
232
+ AL --> G1
233
+ C --> G1["<b>payload-substance</b>"]
234
+ G1 --> G2["<b>cross-product parity</b><br/>one product cannot ship a stub<br/>where the family ships substance"]
235
+ G2 --> G3["<b>referenced-path resolution</b><br/>every path in a SKILL.md<br/>must exist in the tarball"]
236
+ G3 --> OK["installs and works<br/>on a machine that has<br/>nothing else"]
237
+ style C fill:#d4edda,stroke:#155724
238
+ style OK fill:#d4edda,stroke:#155724
239
+ ```
240
+
159
241
  `lit start work <plan>`은 의도적으로 `BLOCKED:` handoff를 반환합니다. 승인된
160
242
  plan과 함께 `/start-work` 또는 `/litclaude:start-work`를 사용하세요. `lit
161
243
  workflow`는 native `Workflow`를 먼저 제안하고, 사용자가 opt-in한 뒤에만
@@ -1,6 +1,6 @@
1
1
  # LitClaude Release Checklist
2
2
 
3
- Status: `litclaude-ai@0.4.3` is the current release candidate — exact canonical
3
+ Status: `litclaude-ai@0.4.4` is the current release candidate — exact canonical
4
4
  frontend corpus plus Claude-native `autoresearch`, `autoconference`, and `wikify`
5
5
  workflow-family integration. It byte-pins the frontend library, legal companions,
6
6
  family source closures, and adapters through independent commitments and package
@@ -45,9 +45,9 @@ side-effect-free, the launcher starts only a separate Claude Code
45
45
  print/background worker, and the release preserves the Korean polishing
46
46
  command, strict multi-agent review pipeline, fidelity guardrails, package
47
47
  hygiene checks, native route gates, and safe start-work handoff behavior.
48
- `package.json` is aligned to `0.4.3`,
49
- `plugins/litclaude/.claude-plugin/plugin.json` is aligned to `0.4.3`, and the
50
- plugin-local MCP server reports `0.4.3`.
48
+ `package.json` is aligned to `0.4.4`,
49
+ `plugins/litclaude/.claude-plugin/plugin.json` is aligned to `0.4.4`, and the
50
+ plugin-local MCP server reports `0.4.4`.
51
51
 
52
52
  This candidate adds an approval-gated skill learning loop. Validated
53
53
  consultations, bounded corrections, iteration signals, and coverage gaps may
@@ -295,9 +295,9 @@ checkout and from an isolated install of the packed tarball:
295
295
  Before requesting publication approval, confirm these artifacts from the current
296
296
  checkout:
297
297
 
298
- - `package.json` version is `0.4.3`.
299
- - `plugins/litclaude/.claude-plugin/plugin.json` version is `0.4.3`.
300
- - `plugins/litclaude/bin/litclaude-mcp.js` reports server version `0.4.3`.
298
+ - `package.json` version is `0.4.4`.
299
+ - `plugins/litclaude/.claude-plugin/plugin.json` version is `0.4.4`.
300
+ - `plugins/litclaude/bin/litclaude-mcp.js` reports server version `0.4.4`.
301
301
  - Prompt-hook tests cover bundled `SKILL.md` body injection for bare `hyperplan`, `litresearch`, `lit research`, `init-deep`, and explicit leading `$start-work`; diagnostic/copy mentions stay inert while leading natural-language `lit start work` stays BLOCKED.
302
302
  - `lit search` and `lit query` route to `/litclaude:litresearch` without activating on slash mentions, code spans, or non-lit prompts.
303
303
  - Litresearch web lanes require public API/feed preference, validator-first checks, route traces, prompt-injection quarantine, and honest auth/paywall/private-data stop reasons.
@@ -33,6 +33,7 @@ import { runWorkflowCheckCli } from "../plugins/litclaude/lib/workflow-check.mjs
33
33
  import { runWikifyKnowledgeCli } from "../plugins/litclaude/lib/wikify-knowledge-cli.mjs";
34
34
  import { automaticUpdateRoot, runAutomaticUpdate } from "../plugins/litclaude/lib/automatic-update.mjs";
35
35
  import { runUpdateNotifier } from "./update-notifier.mjs";
36
+ import { render as renderLitFamilyWordmark, width as litFamilyWordmarkWidth } from "./litfamily-banner.mjs";
36
37
 
37
38
  const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
38
39
  const packageJson = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
@@ -248,16 +249,16 @@ const formatInstallStep = (label) => {
248
249
  };
249
250
 
250
251
  // Shared LitFamily banner frame (plans/references/installer-choice-contract.md):
251
- // a 46-glyph rule, the spaced wordmark, and ╭─/│/╰─ stage frames. Byte-identical
252
- // glyphs across products; only name, version, and tagline differ.
252
+ // the authoritative ANSI Shadow wordmark plus the existing install plan frame.
253
+ // Glyph rows live in bin/litfamily-banner.mjs and stay byte-identical across products.
253
254
  const FAMILY_RULE = ` ${"━".repeat(46)}`;
254
255
  const trueColorSupported = () => /truecolor|24bit/iu.test(process.env.COLORTERM ?? "");
255
- const brandOrange = (text) => {
256
- if (!shouldColorInstall()) return text;
256
+ const brandOrange = (text, color = shouldColorInstall()) => {
257
+ if (!color) return text;
257
258
  return trueColorSupported() ? `\x1b[38;2;255;90;31m${text}\x1b[0m` : `\x1b[38;5;202m${text}\x1b[0m`;
258
259
  };
259
- const planYellow = (text) => {
260
- if (!shouldColorInstall()) return text;
260
+ const planYellow = (text, color = shouldColorInstall()) => {
261
+ if (!color) return text;
261
262
  return trueColorSupported() ? `\x1b[38;2;250;204;21m${text}\x1b[0m` : `\x1b[38;5;220m${text}\x1b[0m`;
262
263
  };
263
264
  const INSTALL_STAGES = [
@@ -267,19 +268,38 @@ const INSTALL_STAGES = [
267
268
  ["04", "Cache", "refresh the compatibility pointer"],
268
269
  ["05", "Verify", "confirm every installed surface"],
269
270
  ];
270
- const familyBanner = () => [
271
- brandOrange(FAMILY_RULE),
271
+ const renderLitClaudeWordmark = () => {
272
+ const litRows = renderLitFamilyWordmark("lit");
273
+ const claudeRows = renderLitFamilyWordmark("claude");
274
+ if (litFamilyWordmarkWidth(litRows) !== 20 || litFamilyWordmarkWidth(claudeRows) !== 49) {
275
+ throw new Error("LitFamily wordmark width contract changed");
276
+ }
277
+ return [
278
+ ...litRows,
279
+ ...claudeRows.map((row, index) => index === 0 ? `${row} v${version}` : row),
280
+ ];
281
+ };
282
+
283
+ const familyBanner = ({ color = shouldColorInstall() } = {}) => [
284
+ brandOrange(FAMILY_RULE, color),
272
285
  "",
273
- ` ${brandOrange("🔥")} l i t claude v${version}`,
286
+ ...renderLitClaudeWordmark().map((row) => brandOrange(row, color)),
274
287
  ` ${packageJson.description}`,
275
288
  "",
276
- brandOrange(FAMILY_RULE),
289
+ brandOrange(FAMILY_RULE, color),
277
290
  " ╭─ INSTALL PLAN",
278
- ...INSTALL_STAGES.map(([number, name, description]) => ` │ ${planYellow(number)} · ${name.padEnd(10)}${description}`),
291
+ ...INSTALL_STAGES.map(([number, name, description]) => ` │ ${planYellow(number, color)} · ${name.padEnd(10)}${description}`),
279
292
  " ╰─ Model selection: host-owned · unrelated Claude settings preserved",
280
293
  "",
281
294
  ].join("\n");
282
295
 
296
+ const printCommandBanner = (parsed) => {
297
+ if (["install", "update"].includes(parsed.command)) return;
298
+ if (parsed.rest.some((arg) => arg === "--json" || arg.startsWith("--json="))) return;
299
+ const color = shouldColorInstall() && Boolean(process.stdout.isTTY && !process.env.CI);
300
+ process.stdout.write(`${renderLitClaudeWordmark().map((row) => brandOrange(row, color)).join("\n")}\n`);
301
+ };
302
+
283
303
  const createInstallProgress = () => {
284
304
  const animated = shouldAnimateInstall();
285
305
  let frameIndex = 0;
@@ -292,6 +312,7 @@ const createInstallProgress = () => {
292
312
  return {
293
313
  prepare({ claudeTarget, litTarget }) {
294
314
  if (!animated) {
315
+ process.stdout.write(`\n${familyBanner({ color: false })}`);
295
316
  process.stdout.write(`INSTALL_STEP: Installing LitClaude ${version}\n`);
296
317
  return;
297
318
  }
@@ -1017,6 +1038,7 @@ const install = async ({ dryRun, rest }) => {
1017
1038
  const progress = createInstallProgress();
1018
1039
 
1019
1040
  if (dryRun) {
1041
+ process.stdout.write(`${familyBanner({ color: false })}\n`);
1020
1042
  process.stdout.write(`DRY_RUN: install LitClaude ${version}\n`);
1021
1043
  process.stdout.write("Model selection: host-owned (Claude Code exposes no native route surface)\n");
1022
1044
  process.stdout.write(`Would copy: ${sourcePlugin} -> ${targetPlugin}\n`);
@@ -1399,6 +1421,8 @@ const main = async () => {
1399
1421
  return;
1400
1422
  }
1401
1423
 
1424
+ printCommandBanner(parsed);
1425
+
1402
1426
  switch (command) {
1403
1427
  case "install":
1404
1428
  case "update":
@@ -0,0 +1,32 @@
1
+ // ANSI Shadow, compressed to 5 rows: the standard 6-row face with its duplicate
2
+ // middle row dropped, keeping the closing row. This matches the approved preview.
3
+ export const GLYPHS = {
4
+ a:[" █████╗ ","██╔══██╗","███████║","██╔══██║","╚═╝ ╚═╝"],
5
+ c:[" ██████╗","██╔════╝","██║ ","╚██████╗"," ╚═════╝"],
6
+ d:["██████╗ ","██╔══██╗","██║ ██║","██████╔╝","╚═════╝ "],
7
+ e:["███████╗","██╔════╝","█████╗ ","███████╗","╚══════╝"],
8
+ g:[" ██████╗ ","██╔════╝ ","██║ ███╗","╚██████╔╝"," ╚═════╝ "],
9
+ h:["██╗ ██╗","██║ ██║","███████║","██║ ██║","╚═╝ ╚═╝"],
10
+ i:["██╗","██║","██║","██║","╚═╝"],
11
+ k:["██╗ ██╗","██║ ██╔╝","█████╔╝ ","██║ ██╗","╚═╝ ╚═╝"],
12
+ l:["██╗ ","██║ ","██║ ","███████╗","╚══════╝"],
13
+ m:["███╗ ███╗","████╗ ████║","██╔████╔██║","██║ ╚═╝ ██║","╚═╝ ╚═╝"],
14
+ n:["███╗ ██╗","████╗ ██║","██╔██╗ ██║","██║ ╚████║","╚═╝ ╚═══╝"],
15
+ o:[" ██████╗ ","██╔═══██╗","██║ ██║","╚██████╔╝"," ╚═════╝ "],
16
+ p:["██████╗ ","██╔══██╗","██████╔╝","██║ ","╚═╝ "],
17
+ r:["██████╗ ","██╔══██╗","██████╔╝","██║ ██║","╚═╝ ╚═╝"],
18
+ s:["███████╗","██╔════╝","███████╗","███████║","╚══════╝"],
19
+ t:["████████╗","╚══██╔══╝"," ██║ "," ██║ "," ╚═╝ "],
20
+ u:["██╗ ██╗","██║ ██║","██║ ██║","╚██████╔╝"," ╚═════╝ "],
21
+ x:["██╗ ██╗","╚██╗██╔╝"," ╚███╔╝ ","██╔╝ ██╗","╚═╝ ╚═╝"],
22
+ };
23
+ export function render(word){
24
+ const rows=["","","","",""];
25
+ for(const ch of word){
26
+ const g=GLYPHS[ch];
27
+ if(!g) throw new Error(`missing glyph for '${ch}' in '${word}'`);
28
+ for(let i=0;i<5;i++) rows[i]+=g[i];
29
+ }
30
+ return rows;
31
+ }
32
+ export const width = (rows)=>Math.max(...rows.map(r=>[...r].length));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litclaude-ai",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "Claude Code-native workflow distribution.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "litclaude",
3
3
  "description": "Claude Code-native workflow plugin with a bounded-authority start-work lifecycle.",
4
- "version": "0.4.3",
4
+ "version": "0.4.4",
5
5
  "author": {
6
6
  "name": "LitClaude contributors"
7
7
  },
@@ -9,7 +9,7 @@ import {
9
9
  } from "../lib/wikify-knowledge.mjs";
10
10
 
11
11
  const protocolVersion = "2024-11-05";
12
- const serverVersion = "0.4.3";
12
+ const serverVersion = "0.4.4";
13
13
 
14
14
  const publicSourceReadTool = {
15
15
  name: "public_source_read",
@@ -9,46 +9,46 @@ export const canonicalSkillResourceManifest = Object.freeze(
9
9
  ["lib/deliverable-hedge-guard.mjs", "ed5b3becf69f2a3f5cb2255affd33830c33f38f01386c77171014758ac08f72f"],
10
10
  ["lib/durable-plan.mjs", "33fc7c2ba6305602c73650c8f29e6141e93b8ac32a444f772807e11bf8c22e44"],
11
11
  ["lib/immutable-expected-file-map.mjs", "4061486bc8eda8a53e56b7b346a1e400e7c858c0a682c83362fea460b46dfd4b"],
12
- ["lib/owner-lock.mjs", "804a5e94863be5d573a217ad1eb597889b6f9fe43bbc6d9f539f15ac2df0ea8b"],
12
+ ["lib/owner-lock.mjs", "2368724b7e48ce14c83121b529e4d491319201348c012b6141f137dd3451b65c"],
13
13
  ["lib/plan-task-rows.mjs", "5ba6c6e3cd04fb3f1be33cf5692a05f46948390e70ca096b9516f1589c6ddde9"],
14
14
  ["lib/rules/constants.mjs", "de97cc08ca834c35ba89a3d384517ae3f24fd52502b8ccd7a3c8227981e3f6c9"],
15
15
  ["lib/rules/discovery.mjs", "8a3d445c2d55c4d65c721c2724c4f927ffbd6dfa31472be857d9c827274c6456"],
16
- ["lib/rules/engine.mjs", "5b24a912b3683170838f58e7f9d9f214685c354dd4b8ba5e11c9aa7df5a837ff"],
16
+ ["lib/rules/engine.mjs", "ce7a019d51c87af875d5ef21004c08f0c333c4cf9696afa28b85fc7ece3cd5d1"],
17
17
  ["lib/rules/format.mjs", "3def47d9c479ed123f94602ad6eb1fcec8ce992ef0ff23516826860e92456e8f"],
18
18
  ["lib/rules/frontmatter.mjs", "d0272fb934407b20a425a546c7762ba90e6d6d3bbdad083228698e9bd5b58b4b"],
19
19
  ["lib/rules/glob.mjs", "e0b138279b9608e879af5f680643a0c4aefb00b388e0ba42f98f6eead3c08caf"],
20
20
  ["lib/rules/matcher.mjs", "83334358a035a9fedf3d7970b2454825d4ca8d0082b5a8779efc8ad8fdeecd5b"],
21
21
  ["lib/rules/ordering.mjs", "c6da1ef0b228b8f0932b54422d2bc9744eb6bfbb8f5bb70b30b8f1a798765d1c"],
22
22
  ["lib/rules/scanner.mjs", "c62d672a66af25f29fe1d05b09288583425a2bf55f20d788f81d1578035f79f9"],
23
- ["lib/rules/session-state.mjs", "5bc8668299877cce36c343e3aaff44d773959c62c53301e7b8555b9f48132e3c"],
23
+ ["lib/rules/session-state.mjs", "792d8d493de6914c04d73ddab00ab87db8e96e1a8167f05ae5cb9df3e85dcfc4"],
24
24
  ["lib/secret-shapes.mjs", "73733bb5927d6d1e00c529acc847b79d8664d10f94100bcc7452824615ab87ba"],
25
- ["lib/secure-path-read.mjs", "d8d6bea57facd4ec6b600bb46a14c6d242ff488989f4bd5a3dcb86a7fb568c4b"],
25
+ ["lib/secure-path-read.mjs", "c2991d0279f7399c3022c78babe28e653260f2a2e9ff4a5df692883ccf8807fd"],
26
26
  ["lib/skill-loop/apply.mjs", "c00aa7a40d76cb5390ac7c13af4a2eda4ff8d090f10c2a4f1e4a72ac158d3ac9"],
27
27
  ["lib/skill-loop/authority.mjs", "41911124a5141480538bbd9887c4d5cec2ea38552ed03c05bd3d3412f0c11b1d"],
28
28
  ["lib/skill-loop/cli.mjs", "333135a39c36e7eab6b10d5a3859dce68ba98b7c83bbf36144d53b19f4bdc1f4"],
29
- ["lib/skill-loop/common.mjs", "23b5c13003ba88e500068a8035a6006595840e34ebcde48d7a6b28257b186c0a"],
29
+ ["lib/skill-loop/common.mjs", "c65eec46eaad369b989337876960dcba9a0f25f40320862dc1c4a298a7e7a730"],
30
30
  ["lib/skill-loop/config.mjs", "833e73f74ffdf43068a95aa6c50dc29e9080b0549871bdc0a5669a01c752cba6"],
31
- ["lib/skill-loop/curator.mjs", "cc2a2102a3af2f417472b67983842f0f42467f2c594abd5210db4a5a87831e3d"],
31
+ ["lib/skill-loop/curator.mjs", "6776eb46fb0c1f79a2a217f495b2195e54cac044f61dfe9298447c9b2bd2de76"],
32
32
  ["lib/skill-loop/hook-runtime.mjs", "128f7ce2897a1197d90b49bf9284d0a2b8d53d8e5b68ef9dcbb84e0021f83b5e"],
33
33
  ["lib/skill-loop/hook-state.mjs", "cbe544247069ee004acb389f70ef7d9f25f0afd8a5df9c5567c365bf47989938"],
34
34
  ["lib/skill-loop/ledger.mjs", "5367b62c21f8bad2e8efb34caa9e2a5c79de85d9d762d7a583cc66ea9da325e5"],
35
- ["lib/skill-loop/mutation-transaction.mjs", "85b57fe9c3e47f41ac5c11b1fc47cc5116216236081a810d01d0fc3b05b66a50"],
35
+ ["lib/skill-loop/mutation-transaction.mjs", "485b871b3cc5e8c3234df9bf0a84f240fddc4f91dbff94607d1e046248bf33f9"],
36
36
  ["lib/skill-loop/proposal-reader.mjs", "b979d2a848eef091fabb001ce2e8a8a4fd8dc6e16e874add0f34dc99b3575af4"],
37
37
  ["lib/skill-loop/proposal-record.mjs", "352888ab9d0b7235414ca9ce068c119fb2230d1abe46bcff602d55feff0552bc"],
38
- ["lib/skill-loop/proposal-store.mjs", "d2fe53c76b31ad04ece68e34ea7d6a172ade9401838dbeda1473ee975c03e8ac"],
38
+ ["lib/skill-loop/proposal-store.mjs", "07e06e035a8fd5b58baf41fd6df244f120bb14a857ea6b98f0d71f362dd4c358"],
39
39
  ["lib/skill-loop/proposals.mjs", "bc0a880b149c8293065d458eaf464ba79e08da93b1912c695239af8cbb8cedec"],
40
40
  ["lib/skill-loop/review-runner.mjs", "fcd4f1c122b3c50934358c376cda544808c0286793e1e882fee72277258d4c7c"],
41
41
  ["lib/skill-loop/review-transaction.mjs", "a74f21f6d24014d1ade5c6bf760d7452ed491df4471f7d14a8ef3423028db4c3"],
42
- ["lib/skill-loop/review.mjs", "53db0b54af52dc84cfdb106791337ef14163188e26064c81c6f1f59cc2f1ce34"],
42
+ ["lib/skill-loop/review.mjs", "90118466b694bc56aa605e4eeb1fbd34ce57367c4075adbb52d2ec2f2182bc45"],
43
43
  ["lib/skill-loop/usage.mjs", "9a80b2979014c46bdd9527140ef193abacd3a1b4eafd458f32315d5902aa2b99"],
44
- ["lib/skill-observer.mjs", "6feabcb01bbd9d8141d36176cce88441788a590fa60aa1e9c4193ab107b87eb3"],
44
+ ["lib/skill-observer.mjs", "13466c511a870cb4809e327c8a9181cdba17da9883ef05995f6ca8c698a925b6"],
45
45
  ["lib/strict-json.mjs", "d941f327aabce5ffc212770852cfbc7e08dd03471e4e9bc9560eff54f06d489a"],
46
46
  ["lib/wikify-knowledge-cli.mjs", "d98e4b3ea0efe3dcd483750c2dc3a5d0dfd14bc6eb349437902b1e01b8fa2ff4"],
47
- ["lib/wikify-knowledge.mjs", "c548926af6943932baebd44ef0005d6de1dfc2346a9d2e0137e049d0cbf926f3"],
48
- ["scripts/scaffold-plan.mjs", "b131a4b2d7576515dfb570fce9fd3750740a750b57764a1e9f6e222be938c7f1"],
47
+ ["lib/wikify-knowledge.mjs", "4d2f4e0ac3bc0b40ac513470b324e853e2aeeb3f009216c13d8e12ec08e6c28b"],
48
+ ["scripts/scaffold-plan.mjs", "2a252075114c9d692db51a3254931c8a2559161fc185fc00f9b2fa8c7c624e1a"],
49
49
  ["skills/autoconference/SKILL.md", "6403a26653dfb3db31f15eaee379dac7f18df1180429d11b9db288a23d8485cd"],
50
50
  ["skills/autoresearch/SKILL.md", "2b3de204f6c0a75b205e12bb7c5fb5736dc6de24aeb1f287496f5d20c3e208c9"],
51
- ["skills/browser-drive/scripts/capability-probe.mjs", "3236a5fc4f2ecbafd3362488533af7bd83c5703dca74940ebed0a7cd78d7e94b"],
51
+ ["skills/browser-drive/scripts/capability-probe.mjs", "e767912bc034eaf9081256d8aa2f2bf63c7d9d29e39cb5e56f390e872df794f7"],
52
52
  ["skills/frontend-ui-ux/LICENSE", "738f69dfa83db5c347c678fb9d90e560877059f0de93a327c39001bff92dc014"],
53
53
  ["skills/frontend-ui-ux/PROVENANCE.json", "a00be969523fe376a07d310b7418be0c41824f01241294bdf00e82eb4d736e87"],
54
54
  ["skills/frontend-ui-ux/SKILL.md", "3642233f9d3d275aaa21311fa70e82d175114f5b24448ae9a6a62187178d6ceb"],
@@ -99,7 +99,7 @@ export const canonicalSkillResourceManifest = Object.freeze(
99
99
  ["skills/skill-observer/references/review-contract.md", "f55dc8334f3b8d8498c84d57725fa03af8fbd689b2dd7cce25e49931629ee54f"],
100
100
  ["skills/skill-observer/scripts/skill-loop.mjs", "36915455a8f22a03975108d48dea83e8f6aa827936f9fdac3c09eca3fec9072d"],
101
101
  ["skills/teammode/SKILL.md", "ba8aa473fa0929325f92dfd5ba848914e0f88e6c9d54721552664ad83839724a"],
102
- ["skills/teammode/scripts/team.mjs", "bd741c3d0ec41385c1fd7a1bbca0cdb0f757691ad25f301659340e937dcad60b"],
102
+ ["skills/teammode/scripts/team.mjs", "43128f909bdc0d05c5ce5d0028e4dcbd321da858d645e4730b1f577c09124fa8"],
103
103
  ["skills/visual-qa/SKILL.md", "9d78f633b7cd9f9308b3718cdeecb8fe448099cc13b6716787f7a64065aee79c"],
104
104
  ["skills/visual-qa/references/capture-playbook.md", "92cad16893118c9e878cabbb49dc2187049ec6e759fcc4e6006d79bdae998689"],
105
105
  ["skills/visual-qa/references/complete-contract.md", "8785c95a259124fef04c5ae7b8ee0636e6390a5fda98ab2321bc4da185d57b98"],