@litfamily/lithermes 1.0.5 → 1.0.6

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/README.md CHANGED
@@ -1,7 +1,7 @@
1
- <p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/cover-motion-still.webp" /><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/cover-motion.webp" width="100%" alt="LitHermes cover art. A lime signal moves through orbital paths above the HERMES AGENT wordmark; a still frame from this motion cover appears when reduced motion is preferred." /></picture></p>
2
- <p align="center"><a href="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/cover.webp">View the static family cover</a></p>
1
+ <p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/cover-motion-still.webp" /><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/cover-motion.webp" width="100%" alt="LitHermes cover art. A lime signal moves through orbital paths above the HERMES AGENT wordmark; a still frame from this motion cover appears when reduced motion is preferred." /></picture></p>
2
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/cover.webp" width="100%" alt="Five armored robots, one for each LitFamily product, beneath the words KEEP THE WORK LIT." /></p>
3
3
 
4
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/ascii-readme.svg" width="480" alt="LIT ASCII B mark" /></p>
4
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/ascii-readme.svg" width="480" alt="LIT ASCII B mark" /></p>
5
5
 
6
6
  <details>
7
7
  <summary>Copy ASCII logo</summary>
@@ -31,19 +31,19 @@
31
31
 
32
32
  </details>
33
33
 
34
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/lithermes-wordmark.svg" width="480" alt="LITHERMES display type" /></p>
35
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/lithermes-clay-icon.png" width="160" alt="LitHermes clay mark" /></p>
34
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/lithermes-wordmark.svg" width="480" alt="LITHERMES display type" /></p>
35
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/lithermes-clay-icon.png" width="160" alt="LitHermes clay mark" /></p>
36
36
 
37
37
  <p align="center">
38
- <a href="#install"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/badge-version.svg" alt="1.0.5" /></a>
39
- <a href="https://github.com/wjgoarxiv/lithermes/blob/main/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/badge-license.svg" alt="MIT license" /></a>
38
+ <a href="#install"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/badge-version.svg" alt="1.0.6" /></a>
39
+ <a href="https://github.com/wjgoarxiv/lithermes/blob/main/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/badge-license.svg" alt="MIT license" /></a>
40
40
  </p>
41
41
 
42
42
  <p align="center">
43
- <a href="https://github.com/wjgoarxiv/lithermes/blob/main/docs/guide.md"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/lucide-book-open.svg" width="16" alt="" /> Docs</a> &nbsp;
43
+ <a href="https://github.com/wjgoarxiv/lithermes/blob/main/docs/guide.md"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/lucide-book-open.svg" width="16" alt="" /> Docs</a> &nbsp;
44
44
  <a href="#install">Install</a> &nbsp;
45
- <a href="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/ignition-film.mp4"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/lucide-play.svg" width="16" alt="" /> Ignition</a> &nbsp;
46
- <a href="https://github.com/wjgoarxiv/lithermes/blob/main/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/lucide-shield-check.svg" width="16" alt="" /> MIT</a>
45
+ <a href="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/ignition-film.mp4"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/lucide-play.svg" width="16" alt="" /> Ignition</a> &nbsp;
46
+ <a href="https://github.com/wjgoarxiv/lithermes/blob/main/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/lucide-shield-check.svg" width="16" alt="" /> MIT</a>
47
47
  </p>
48
48
 
49
49
  # LitHermes
@@ -52,11 +52,11 @@
52
52
 
53
53
  **What it is:** LitHermes connects planning, execution, review, and handoff inside **Hermes Agent**.
54
54
 
55
- [한국어](https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/README_Ko-KR.md) · [npm](https://www.npmjs.com/package/@litfamily/lithermes) · [GitHub](https://github.com/wjgoarxiv/lithermes)
55
+ [한국어](https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/README_Ko-KR.md) · [npm](https://www.npmjs.com/package/@litfamily/lithermes) · [GitHub](https://github.com/wjgoarxiv/lithermes)
56
56
 
57
57
  ## Install
58
58
 
59
- Source version: `@litfamily/lithermes@1.0.5`. Have Hermes Agent and Node.js 18+ installed, with write access to your Hermes home (normally `~/.hermes`).
59
+ Source version: `@litfamily/lithermes@1.0.6`. Have Hermes Agent and Node.js 18+ installed, with write access to your Hermes home (normally `~/.hermes`).
60
60
 
61
61
  The installer targets your Hermes home. For an isolated trial, set `HERMES_HOME` to a new empty directory before installation and use that same value when starting Hermes. Keep your existing home and settings. `--no-patch-installed-hermes` also prevents compatibility edits to the detected host installation outside that profile.
62
62
 
@@ -161,6 +161,7 @@ For Telegram gateway dispatch, use `/lit_loop` and `/lit_plan`. The complete com
161
161
  - Native `/goal` is user-managed and unobserved. Durable `goal_*` state is authoritative; there is no automatic update, clear, or resume of native `/goal`.
162
162
  - Hermes uses a global child model route. Per-task model overrides and named reviewer routes are unavailable. A configuration receipt does not prove an effective child execution.
163
163
  - The generated negative gate matrix uses an isolated HOME and `HERMES_HOME`; its receipt is safe to compare across concurrent sessions.
164
+ - Hermes resolves a bare skill name (not the `lithermes:<name>` explicit-load form) against Hermes `config.yaml`'s `skills.external_dirs` and local `<HERMES_HOME>/skills` before it reaches the LitHermes plugin. If one of those locations holds a same-named skill, `lithermes doctor` prints a `skill shadow check: WARNING` line naming the skill and the shadowing path; load the LitHermes copy explicitly as `lithermes:<name>`, or remove/rename the other copy. This warning never changes doctor's pass/fail exit status.
164
165
 
165
166
  ### Verify and uninstall
166
167
 
@@ -198,6 +199,4 @@ MIT License.
198
199
 
199
200
  ### LITFAMILY
200
201
 
201
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/cover.webp" width="100%" alt="Five armored robots, one for each LitFamily product, beneath the words KEEP THE WORK LIT." /></p>
202
-
203
202
  Install each product separately in its supported agent harness.
package/README_Ko-KR.md CHANGED
@@ -1,7 +1,7 @@
1
- <p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/cover-motion-still.webp" /><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/cover-motion.webp" width="100%" alt="LitHermes 표지. 라임색 신호가 궤도를 지나 HERMES AGENT 워드마크로 이어집니다. 모션을 줄이도록 설정하면 이 모션 표지에서 추출한 정지 프레임을 표시합니다." /></picture></p>
2
- <p align="center"><a href="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/cover.webp">정지 패밀리 표지 보기</a></p>
1
+ <p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/cover-motion-still.webp" /><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/cover-motion.webp" width="100%" alt="LitHermes 표지. 라임색 신호가 궤도를 지나 HERMES AGENT 워드마크로 이어집니다. 모션을 줄이도록 설정하면 이 모션 표지에서 추출한 정지 프레임을 표시합니다." /></picture></p>
2
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/cover.webp" width="100%" alt="LitFamily 다섯 제품을 나타내는 장갑 로봇 패널과 KEEP THE WORK LIT. 문구" /></p>
3
3
 
4
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/ascii-readme.svg" width="480" alt="LIT ASCII B 마크" /></p>
4
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/ascii-readme.svg" width="480" alt="LIT ASCII B 마크" /></p>
5
5
 
6
6
  <details>
7
7
  <summary>ASCII 로고 복사</summary>
@@ -31,19 +31,19 @@
31
31
 
32
32
  </details>
33
33
 
34
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/lithermes-wordmark.svg" width="480" alt="LITHERMES 디스플레이 서체" /></p>
35
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/lithermes-clay-icon.png" width="160" alt="LitHermes 클레이 마크" /></p>
34
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/lithermes-wordmark.svg" width="480" alt="LITHERMES 디스플레이 서체" /></p>
35
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/lithermes-clay-icon.png" width="160" alt="LitHermes 클레이 마크" /></p>
36
36
 
37
37
  <p align="center">
38
- <a href="#설치"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/badge-version.svg" alt="1.0.5" /></a>
39
- <a href="https://github.com/wjgoarxiv/lithermes/blob/main/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/badge-license.svg" alt="MIT license" /></a>
38
+ <a href="#설치"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/badge-version.svg" alt="1.0.6" /></a>
39
+ <a href="https://github.com/wjgoarxiv/lithermes/blob/main/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/badge-license.svg" alt="MIT license" /></a>
40
40
  </p>
41
41
 
42
42
  <p align="center">
43
- <a href="https://github.com/wjgoarxiv/lithermes/blob/main/docs/guide.ko.md"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/lucide-book-open.svg" width="16" alt="" /> 문서</a> &nbsp;
43
+ <a href="https://github.com/wjgoarxiv/lithermes/blob/main/docs/guide.ko.md"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/lucide-book-open.svg" width="16" alt="" /> 문서</a> &nbsp;
44
44
  <a href="#설치">설치</a> &nbsp;
45
- <a href="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/ignition-film.mp4"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/lucide-play.svg" width="16" alt="" /> Ignition</a> &nbsp;
46
- <a href="https://github.com/wjgoarxiv/lithermes/blob/main/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/lucide-shield-check.svg" width="16" alt="" /> MIT</a>
45
+ <a href="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/ignition-film.mp4"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/lucide-play.svg" width="16" alt="" /> Ignition</a> &nbsp;
46
+ <a href="https://github.com/wjgoarxiv/lithermes/blob/main/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/readme-assets/lucide-shield-check.svg" width="16" alt="" /> MIT</a>
47
47
  </p>
48
48
 
49
49
  # LitHermes
@@ -52,11 +52,11 @@
52
52
 
53
53
  **무엇인가요:** LitHermes는 **Hermes Agent**에서 계획, 실행, 검토, 인계를 이어갑니다.
54
54
 
55
- [English](https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/README.md) · [npm](https://www.npmjs.com/package/@litfamily/lithermes) · [GitHub](https://github.com/wjgoarxiv/lithermes)
55
+ [English](https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.6/README.md) · [npm](https://www.npmjs.com/package/@litfamily/lithermes) · [GitHub](https://github.com/wjgoarxiv/lithermes)
56
56
 
57
57
  ## 설치
58
58
 
59
- 소스 기준 버전은 `@litfamily/lithermes@1.0.5`입니다. Hermes Agent와 Node.js 18+가 필요하며, Hermes 홈(기본 `~/.hermes`)에 쓰기 권한이 있어야 합니다.
59
+ 소스 기준 버전은 `@litfamily/lithermes@1.0.6`입니다. Hermes Agent와 Node.js 18+가 필요하며, Hermes 홈(기본 `~/.hermes`)에 쓰기 권한이 있어야 합니다.
60
60
 
61
61
  설치기는 Hermes 홈을 대상으로 합니다. 별도 체험을 하려면 설치 전에 `HERMES_HOME`을 새 빈 디렉터리로 지정하고 Hermes를 시작할 때도 같은 값을 사용하세요. 기존 홈과 설정은 보관합니다. `--no-patch-installed-hermes`는 해당 프로필 밖에서 감지된 호스트 설치본에 호환성 패치를 적용하지 못하게 합니다.
62
62
 
@@ -161,6 +161,7 @@ Telegram gateway에서는 `/lit_loop`와 `/lit_plan` 별칭을 사용합니다.
161
161
  - native `/goal`은 사용자가 관리하며 plugin은 관찰하지 않습니다. durable `goal_*` 상태가 기준이며 native `/goal`을 자동으로 갱신·초기화·재개하지 않습니다.
162
162
  - Hermes 하위 모델은 공통 모델 경로를 사용합니다. 작업별 모델 재정의와 지정 reviewer 경로는 지원하지 않습니다. 설정 receipt가 실제 child 실행을 증명하지 않습니다.
163
163
  - 생성되는 negative gate matrix는 분리된 HOME과 `HERMES_HOME`을 사용하므로 동시 세션의 receipt를 비교할 수 있습니다.
164
+ - Hermes는 bare skill 이름(명시적 로드 형태인 `lithermes:<name>`이 아닌 경우)을 Hermes `config.yaml`의 `skills.external_dirs`와 로컬 `<HERMES_HOME>/skills`에서 먼저 찾은 뒤 LitHermes plugin으로 넘어갑니다. 이 위치 중 하나에 같은 이름의 skill이 있으면 `lithermes doctor`가 `skill shadow check: WARNING` 줄로 해당 skill과 가리는 경로를 알려줍니다. `lithermes:<name>`으로 명시적으로 불러오거나, 다른 위치의 사본을 제거·이름 변경하세요. 이 경고는 doctor의 성공/실패 종료 상태를 바꾸지 않습니다.
164
165
 
165
166
  ### 확인 및 삭제
166
167
 
@@ -198,6 +199,4 @@ MIT License.
198
199
 
199
200
  ### LITFAMILY
200
201
 
201
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.5/readme-assets/cover.webp" width="100%" alt="LitFamily 다섯 제품을 나타내는 장갑 로봇 패널과 KEEP THE WORK LIT. 문구" /></p>
202
-
203
202
  각 제품은 지원하는 에이전트 환경에 따로 설치해 사용합니다.
@@ -106,8 +106,8 @@ _SKILL_ROUTE_CONTRACTS = {
106
106
  "implementation and rendered inspection. Record a compact direction and evolve the "
107
107
  "Design Contract with the work; do not stop at a contract or demand routine reapproval.",
108
108
  "Review-only and plan-only requests are read-only. Incidental UI words grant no write "
109
- "authority. Ask one material question if the target or direction conflicts; retain "
110
- "the answer on resume and continue once it resolves the conflict.",
109
+ "authority. Ask one material question per turn while target or direction conflicts or "
110
+ "named directions stay undecided (not defaults); retain answers, build once resolved.",
111
111
  "Every field you record must be one the shipped validator accepts. `design_contract_validation` "
112
112
  "answers `contract has unapproved keys [...]` and exits 1 on anything else; the reference "
113
113
  "documents name the real fields.",
@@ -1,7 +1,7 @@
1
1
  {
2
- "syncedAt": "2026-09-23T12:56:08.744Z",
2
+ "syncedAt": "2026-09-24T07:38:36.208Z",
3
3
  "source": "bundled-payload",
4
- "sourceHash": "e7ac8bd0623eb0ef78d7d97e76daa0bb3d5cd7aab909da0f0e2f3af19f08964b",
4
+ "sourceHash": "ae1d45a687de0c01415820ff467295f77a175cc393e4923b940729668f58c49b",
5
5
  "files": [
6
6
  {
7
7
  "path": "NOTICE.md",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  {
39
39
  "path": "core_contexts.py",
40
- "sha256": "0bb379b099bfedb9ce51141cae0f7c11a827fe35487249a9ca7fe6dfd345b257"
40
+ "sha256": "a60c32bd38a47ecac6bffc39a8549d2ea1b3b87733d666fbb1be4b5685f2fbbb"
41
41
  },
42
42
  {
43
43
  "path": "core_contract.py",
@@ -157,7 +157,7 @@
157
157
  },
158
158
  {
159
159
  "path": "plugin.yaml",
160
- "sha256": "6a3baf875b758fdf6d7973d5f9ef1a5727702452cd4b4a6f4a8268f130b32341"
160
+ "sha256": "9a82f3005c45dab04f48b1bdd4ef79937bdbf7dae7e0f2fcd9a5a391a64c3c96"
161
161
  },
162
162
  {
163
163
  "path": "provider_metrics.py",
@@ -1245,7 +1245,7 @@
1245
1245
  },
1246
1246
  {
1247
1247
  "path": "skills/frontend-ui-ux/references/complete-contract.md",
1248
- "sha256": "7aff009df5222d5cfbcdcc505f651104a7e8145c3b8477246c098a9f9b295f6f"
1248
+ "sha256": "1a7d471fc7a12ec4eb74d7a78110e5104564a64417f2687e90df89dd80c3b249"
1249
1249
  },
1250
1250
  {
1251
1251
  "path": "skills/frontend-ui-ux/references/composition.md",
@@ -1289,7 +1289,7 @@
1289
1289
  },
1290
1290
  {
1291
1291
  "path": "skills/frontend-ui-ux/references/production.md",
1292
- "sha256": "af5d4483340c2410572488c3c6239b0624e83fb24eabda0cc49398d091e85312"
1292
+ "sha256": "f859bbca4a70621c4440feb4b288d6225e6ecdd206ef4e32baeea199526df2a3"
1293
1293
  },
1294
1294
  {
1295
1295
  "path": "skills/frontend-ui-ux/references/redesign-playbook.md",
@@ -1857,7 +1857,7 @@
1857
1857
  },
1858
1858
  {
1859
1859
  "path": "skills/readme-studio/SKILL.md",
1860
- "sha256": "40b9ed081c86db22386fd586903b6457248cbc1185b3a283c007f6bac0e98be4"
1860
+ "sha256": "010f567e56dbfb73da49acbaa2762737a7351cd0856123e86ac49b5b8d2b3533"
1861
1861
  },
1862
1862
  {
1863
1863
  "path": "skills/readme-studio/references/decoration-patterns.md",
@@ -1873,7 +1873,7 @@
1873
1873
  },
1874
1874
  {
1875
1875
  "path": "skills/readme-studio/references/production-interview.md",
1876
- "sha256": "be6169bff980aef9813e86e6670763d92166efbdbaaa9fa1cc98b733f00224e4"
1876
+ "sha256": "7ec8fcd79e3d55e8d17642696793f557717db0453ba7f0008eb3e80cc6e471a2"
1877
1877
  },
1878
1878
  {
1879
1879
  "path": "skills/readme-studio/references/type-and-images.md",
@@ -1969,7 +1969,7 @@
1969
1969
  },
1970
1970
  {
1971
1971
  "path": "skills/visual-qa/references/complete-contract.md",
1972
- "sha256": "c3008c41017bc548982cc424a3ec90bd338c2d5c2d49bebb5385a640531aabff"
1972
+ "sha256": "fa3842123069e693ee20784e40f08e79a9e0f6854bf62af89d44f9faf13c39f8"
1973
1973
  },
1974
1974
  {
1975
1975
  "path": "skills/visual-qa/schemas/evidence-manifest-v1alpha1.schema.json",
@@ -1,5 +1,5 @@
1
1
  name: lithermes
2
- version: 1.0.5
2
+ version: 1.0.6
3
3
  description: "Hermes-native workflow toolkit: litgoal durable runtime, 5-lane review orchestrator, Litwork commands, skills, and prompt steering."
4
4
  author: "LitHermes contributors"
5
5
  kind: standalone
@@ -431,7 +431,7 @@ isolated Hermes home. Use `--hermes-home`; never `--home`.
431
431
 
432
432
  ```text
433
433
  $ node packages/lithermes-installer/bin/lithermes.js install --yes --offline --no-hud --hermes-home "$ISOLATED"
434
- Installed LitHermes 1.0.5
434
+ Installed LitHermes 1.0.6
435
435
  plugin: $ISOLATED/plugins/lithermes
436
436
  model config: updated
437
437
 
@@ -448,7 +448,7 @@ installed payload: PASS
448
448
  enabled config: PASS
449
449
 
450
450
  $ hermes lithermes doctor
451
- [OK] plugin.yaml readable (version 1.0.5)
451
+ [OK] plugin.yaml readable (version 1.0.6)
452
452
  [OK] skills bundled: 32
453
453
  [OK] litgoal durable runtime importable
454
454
  ```
@@ -4,7 +4,7 @@ Hermes loads this document through the selected frontend-ui-ux skill. Read the r
4
4
 
5
5
  Before editing, identify the actual page, stack, user task, preserved brand elements and actions/states. Keep this direction note small enough to revise. The evidence-capable v1beta2 contract remains the final inventory for verification, and evolves during the build. Older references that call this a freeze describe a versioned review snapshot, not an extra approval gate or a requirement to finish JSON before writing UI. Review/plan-only intent remains read-only even if other guidance says implement.
6
6
 
7
- There is no mandatory interview. Ask only when two plausible answers would materially change scope, architecture, permissions, accessibility, or visual direction. Ask one high-impact question at a time, wait for its answer, then resolve the next material uncertainty in a later turn; continue for as many rounds as materially necessary. Retain earlier answers across rounds in the conversation and task-local direction note, reread them on resume, and do not re-ask a resolved question. When the brief already bounds the work, state the default and proceed without pausing for an interview. Review, plan, and keyword-only requests remain read-only. A cancellation suspends new writes and captures partial status; resumption reuses confirmed assets and source.
7
+ There is no mandatory interview. Ask only when two plausible answers would materially change scope, architecture, permissions, accessibility, or visual direction. Ask one high-impact question at a time, wait for its answer, then resolve the next material uncertainty in a later turn; continue for as many rounds as materially necessary. Retain earlier answers across rounds in the conversation and task-local direction note, reread them on resume, and do not re-ask a resolved question. If a brief lists competing visual directions and leaves them undecided, that choice is still open: calling each option "acceptable" is not a choice or a delegation. Ask it in a separate round after higher-impact questions are answered; you may recommend one option in the question, but do not declare a default for it or start building until the user chooses. A brief that gives no visual direction at all is different: use the authored default direction without asking. Defaults cover only what the brief settles, what it explicitly hands to you, and details that do not materially change the result. When the brief already bounds the work, state the default and proceed without pausing for an interview. Review, plan, and keyword-only requests remain read-only. A cancellation suspends new writes and captures partial status; resumption reuses confirmed assets and source.
8
8
 
9
9
  When the brief does not specify another direction, use the authored tokens in `references/default-editorial-pixel.json` and make an original, task-specific pixel illustration the primary visual anchor. Render each cell at least 6 CSS px and preserve crisp integer-grid edges with nearest-neighbor scaling; do not smooth or blur the illustration. Build the surrounding editorial hierarchy with generous spacing, compact display lines, a terminal accent and deliberate asymmetry. A rounded abstract symbol or a generic gradient cannot stand in for the task-specific illustration. Keep pixel art decorative when the task is conveyed in real text; add meaningful alternative text when it conveys unique content. Never borrow a reference site's artwork, proprietary font or copy.
10
10
 
@@ -23,7 +23,7 @@ Use the authorized repository, applicable instructions, current README, real pac
23
23
  | Mode | Trigger | Contract |
24
24
  | --- | --- | --- |
25
25
  | production | Create or improve the README/cover | Inspect facts, state defaults for a bounded brief, create scoped files and inspect the resulting composition |
26
- | question | Two plausible choices materially change scope, architecture, permissions, accessibility or visual direction | Apply `references/production-interview.md`; ask one high-impact question at a time and retain answers across rounds |
26
+ | question | Two plausible choices materially change scope, architecture, permissions, accessibility or visual direction | Apply `references/production-interview.md`; ask one high-impact question at a time and retain answers across rounds; open competing directions: ask before choosing |
27
27
  | review/plan | Review-only or plan-only | Read-only findings or plan; no asset generation or file edits |
28
28
  | partial | A required tool, font, source or permission is absent | Name the affected deliverable and prerequisite; continue independent work |
29
29
 
@@ -6,6 +6,8 @@ There is no mandatory interview. Ask only when two plausible answers would mater
6
6
 
7
7
  When the brief already bounds the work, state the default and proceed. Use repository evidence and established identity for defaults; state assumptions that materially affect the result. Do not pause for a ceremonial approval of a bounded brief.
8
8
 
9
+ If a brief lists competing visual directions and leaves them undecided, that choice is still open: calling each option "acceptable" is not a choice or a delegation. Ask it in a separate round after higher-impact questions are answered; you may recommend one option in the question, but do not declare a default for it or start building until the user chooses. A brief that gives no visual direction at all is different: follow established identity or the default cover direction without asking. Defaults cover only what the brief settles, what it explicitly hands to you, and details that do not materially change the result.
10
+
9
11
  ## How to ask
10
12
 
11
13
  Ask one high-impact question at a time, in one turn. Present the distinct alternatives that change the deliverable and name their practical effect. Do not combine unrelated decisions into a questionnaire or ask the user to repeat the brief. Wait for the answer before asking about another unresolved material choice. Continue for as many rounds as materially necessary, and stop once remaining choices can safely follow stated defaults.
@@ -485,7 +485,7 @@ isolated Hermes home. Use `--hermes-home`; never `--home`.
485
485
 
486
486
  ```text
487
487
  $ node packages/lithermes-installer/bin/lithermes.js install --yes --offline --no-hud --hermes-home "$ISOLATED"
488
- Installed LitHermes 1.0.5
488
+ Installed LitHermes 1.0.6
489
489
  plugin: $ISOLATED/plugins/lithermes
490
490
  model config: updated
491
491
 
@@ -502,7 +502,7 @@ installed payload: PASS
502
502
  enabled config: PASS
503
503
 
504
504
  $ hermes lithermes doctor
505
- [OK] plugin.yaml readable (version 1.0.5)
505
+ [OK] plugin.yaml readable (version 1.0.6)
506
506
  [OK] skills bundled: 32
507
507
  [OK] litgoal durable runtime importable
508
508
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@litfamily/lithermes",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "npx/bunx installer for the LitHermes Hermes plugin",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="146" height="20" role="img" aria-label="release: 1.0.5"><title>release: 1.0.5</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.5</text></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="146" height="20" role="img" aria-label="release: 1.0.6"><title>release: 1.0.6</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.6</text></g></svg>
package/src/lib/check.js CHANGED
@@ -1,8 +1,8 @@
1
1
  const fs = require("node:fs");
2
2
  const path = require("node:path");
3
3
  const { spawnSync } = require("node:child_process");
4
- const { configHasLitHermes, inspectHermesCapabilities, readConfig } = require("./config");
5
- const { detectHermesRuntimeRepo, detectHermesVersion, ensureHermesHome, inspectHermesHostCapabilities, LitHermesError } = require("./hermesDiscovery");
4
+ const { configHasLitHermes, inspectHermesCapabilities, readConfig, readExternalSkillDirsConfig } = require("./config");
5
+ const { detectHermesRuntimeRepo, detectHermesVersion, ensureHermesHome, expandHome, inspectHermesHostCapabilities, LitHermesError } = require("./hermesDiscovery");
6
6
  const { formatManagedRoute } = require("./modelRoutePolicy");
7
7
  const { inspectPythonCache } = require("./files");
8
8
  const { assetRoot, pluginDest } = require("./install");
@@ -112,6 +112,75 @@ function loadedStatusMatchesOrigin(output, expectedPluginPath) {
112
112
  }
113
113
  }
114
114
 
115
+ function isRegularSkillFile(file) {
116
+ try {
117
+ return fs.lstatSync(file).isFile();
118
+ } catch {
119
+ return false;
120
+ }
121
+ }
122
+
123
+ // Bounded, non-symlink-following scan for `<HERMES_HOME>/skills/**/<id>/SKILL.md`.
124
+ // Real local-skill trees are shallow, so a small depth/entry cap keeps this cheap
125
+ // while still catching a collision a couple of category folders deep.
126
+ function collectLocalSkillShadows(hermesHome, skillIds, { maxDepth = 3, maxEntries = 2000 } = {}) {
127
+ const remaining = new Set(skillIds);
128
+ const found = new Map();
129
+ let visited = 0;
130
+ function walk(dir, depth) {
131
+ if (!remaining.size || depth > maxDepth || visited >= maxEntries) return;
132
+ let entries;
133
+ try {
134
+ entries = fs.readdirSync(dir, { withFileTypes: true });
135
+ } catch {
136
+ return;
137
+ }
138
+ for (const entry of entries) {
139
+ if (!remaining.size || visited >= maxEntries) return;
140
+ visited += 1;
141
+ if (!entry.isDirectory()) continue;
142
+ const full = path.join(dir, entry.name);
143
+ if (remaining.has(entry.name)) {
144
+ const skillFile = path.join(full, "SKILL.md");
145
+ if (isRegularSkillFile(skillFile)) {
146
+ found.set(entry.name, skillFile);
147
+ remaining.delete(entry.name);
148
+ continue;
149
+ }
150
+ }
151
+ walk(full, depth + 1);
152
+ }
153
+ }
154
+ walk(path.join(hermesHome, "skills"), 0);
155
+ return found;
156
+ }
157
+
158
+ // Hermes resolves a bare skill name (not the `lithermes:<name>` explicit-load form)
159
+ // against `skills.external_dirs` and local `<HERMES_HOME>/skills`; a same-named entry
160
+ // there is picked instead of the LitHermes plugin copy. This is advisory: it never
161
+ // changes doctor's pass/fail status, only surfaces the collision.
162
+ function detectSkillShadows({ configText, hermesHome, skillIds = requiredSkills }) {
163
+ const externalDirs = readExternalSkillDirsConfig(configText)
164
+ .map((dir) => path.resolve(expandHome(dir)));
165
+ const localShadows = collectLocalSkillShadows(hermesHome, skillIds);
166
+ const warnings = [];
167
+ for (const id of skillIds) {
168
+ const externalDir = externalDirs.find((dir) => isRegularSkillFile(path.join(dir, id, "SKILL.md")));
169
+ if (externalDir) {
170
+ warnings.push({ id, path: path.join(externalDir, id, "SKILL.md"), source: "skills.external_dirs" });
171
+ continue;
172
+ }
173
+ const localPath = localShadows.get(id);
174
+ if (localPath) warnings.push({ id, path: localPath, source: "local skills" });
175
+ }
176
+ return warnings;
177
+ }
178
+
179
+ function formatSkillShadowWarning(shadow) {
180
+ return `WARNING: skill "${shadow.id}" bare name resolves to ${shadow.path} (${shadow.source}); `
181
+ + `use lithermes:${shadow.id} to load LitHermes's copy, or remove/rename the other copy.`;
182
+ }
183
+
115
184
  function checkLitHermes(flags = {}) {
116
185
  const { hermesHome, hermesRepo } = ensureHermesHome(flags);
117
186
  const pluginPath = pluginDest(hermesHome);
@@ -187,6 +256,7 @@ function doctorLitHermes(flags = {}) {
187
256
  const unsafeRecursion = recursion.status === "unavailable" && recursion.reason.startsWith("nested delegation");
188
257
  const unsafeModelRoute = modelSafety.status === "blocked";
189
258
  const runtime = capabilities.runtime;
259
+ const skillShadows = detectSkillShadows({ configText, hermesHome });
190
260
  const lines = [
191
261
  `plugin discovery: ${installedPass && configOk ? "PASS" : "PATCH_AVAILABLE"}`,
192
262
  `bundled source: ${bundledPass ? "PASS" : "FAIL"}`,
@@ -198,6 +268,8 @@ function doctorLitHermes(flags = {}) {
198
268
  `installed payload: ${installedPass ? "PASS" : "FAIL"}`,
199
269
  `enabled config: ${configOk ? "PASS" : "PARTIAL"}`,
200
270
  `loaded plugin: ${loaded.status} (${loaded.reason})`,
271
+ `skill shadow check: ${skillShadows.length ? "WARNING" : "PASS"}`,
272
+ ...skillShadows.map(formatSkillShadowWarning),
201
273
  `auto-compaction: ${auto.status}${auto.reason ? ` (${auto.reason})` : ""}`,
202
274
  `concurrency: ${concurrency.status}${concurrency.status === "hard" ? ` (per batch ${concurrency.limit}; async batches ${concurrency.asyncBatchLimit}; potential children ${concurrency.potentialChildCeiling})` : ` (${concurrency.reason})`}`,
203
275
  `recursion: ${recursion.status}${recursion.status === "hard" ? recursion.flatBy === "depth" ? ` (depth ${recursion.limit}, flat)` : ` (configured depth ${recursion.limit}, flat via orchestrator kill switch)` : ` (${recursion.reason})`}`,
@@ -222,6 +294,7 @@ module.exports = {
222
294
  checkGatewaySource,
223
295
  checkLitHermes,
224
296
  checkTuiSource,
297
+ detectSkillShadows,
225
298
  doctorLitHermes,
226
299
  enabledUserJsonIncludesPlugin,
227
300
  loadedStatusMatchesOrigin,
package/src/lib/config.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const fs = require("node:fs");
2
2
  const path = require("node:path");
3
+ const { parseDocument } = require("yaml");
3
4
  const { writeFileAtomic } = require("./files");
4
5
  const modelConfig = require("./modelConfig");
5
6
 
@@ -205,6 +206,27 @@ function clearOutputStyleConfig(text) {
205
206
  return `${updated.replace(/\n*$/, "")}\n`;
206
207
  }
207
208
 
209
+ // Hermes `skills.external_dirs` (config.yaml key, default []): bare-name skill
210
+ // resolution searches these directories, so a same-named directory there can shadow
211
+ // a LitHermes plugin skill (which is only reachable unambiguously as `lithermes:<name>`).
212
+ // Malformed YAML fails closed to an empty list rather than throwing during doctor.
213
+ function readExternalSkillDirsConfig(text) {
214
+ const str = String(text || "");
215
+ if (!str.trim()) return [];
216
+ try {
217
+ const document = parseDocument(str, { strict: true, uniqueKeys: true });
218
+ if (document.errors.length) return [];
219
+ const node = document.getIn(["skills", "external_dirs"], true);
220
+ const value = node && typeof node.toJS === "function" ? node.toJS(document) : node;
221
+ if (!Array.isArray(value)) return [];
222
+ return value
223
+ .filter((entry) => typeof entry === "string" && entry.trim())
224
+ .map((entry) => entry.trim());
225
+ } catch {
226
+ return [];
227
+ }
228
+ }
229
+
208
230
  function writeConfig(hermesHome, text) {
209
231
  fs.mkdirSync(hermesHome, { recursive: true });
210
232
  writeFileAtomic(configPath(hermesHome), text, "utf8");
@@ -220,6 +242,7 @@ module.exports = {
220
242
  enableLitHermesConfig,
221
243
  readConfig,
222
244
  readDisplaySkinConfig,
245
+ readExternalSkillDirsConfig,
223
246
  readOutputStyleConfig,
224
247
  readTuiAgentsNudgeConfig,
225
248
  setDisplaySkinConfig,