@litfamily/lithermes 1.0.6 → 1.0.7

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.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>
1
+ <p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.7/readme-assets/cover-motion-still.webp" /><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.7/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.7/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.6/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.7/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.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>
34
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.7/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.7/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.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>
38
+ <a href="#install"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.7/readme-assets/badge-version.svg" alt="1.0.7" /></a>
39
+ <a href="https://github.com/wjgoarxiv/lithermes/blob/main/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.7/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.6/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.7/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.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>
45
+ <a href="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.7/readme-assets/ignition-film.mp4"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.7/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.7/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.6/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.7/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.6`. Have Hermes Agent and Node.js 18+ installed, with write access to your Hermes home (normally `~/.hermes`).
59
+ Source version: `@litfamily/lithermes@1.0.7`. 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
 
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.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>
1
+ <p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.7/readme-assets/cover-motion-still.webp" /><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.7/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.7/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.6/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.7/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.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>
34
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.7/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.7/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.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>
38
+ <a href="#설치"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.7/readme-assets/badge-version.svg" alt="1.0.7" /></a>
39
+ <a href="https://github.com/wjgoarxiv/lithermes/blob/main/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.7/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.6/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.7/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.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>
45
+ <a href="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.7/readme-assets/ignition-film.mp4"><img src="https://cdn.jsdelivr.net/npm/@litfamily/lithermes@1.0.7/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.7/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.6/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.7/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.6`입니다. Hermes Agent와 Node.js 18+가 필요하며, Hermes 홈(기본 `~/.hermes`)에 쓰기 권한이 있어야 합니다.
59
+ 소스 기준 버전은 `@litfamily/lithermes@1.0.7`입니다. Hermes Agent와 Node.js 18+가 필요하며, Hermes 홈(기본 `~/.hermes`)에 쓰기 권한이 있어야 합니다.
60
60
 
61
61
  설치기는 Hermes 홈을 대상으로 합니다. 별도 체험을 하려면 설치 전에 `HERMES_HOME`을 새 빈 디렉터리로 지정하고 Hermes를 시작할 때도 같은 값을 사용하세요. 기존 홈과 설정은 보관합니다. `--no-patch-installed-hermes`는 해당 프로필 밖에서 감지된 호스트 설치본에 호환성 패치를 적용하지 못하게 합니다.
62
62
 
@@ -84,6 +84,27 @@ _OPENAI_CATALOG_EFFORTS = {
84
84
  }
85
85
  _REVIEWER_ROUTE_NAME = "".join(chr(code) for code in (109, 111, 109, 117, 115))
86
86
  SUPPORTED_HERMES_HOST_VERSIONS = frozenset(("0.17.0", "0.19.0"))
87
+ _MINIMUM_HERMES_HOST_VERSION = (0, 17, 0)
88
+
89
+
90
+ def _classify_hermes_host_version(host_version: str) -> str:
91
+ if re.fullmatch(r"[0-9]+\.[0-9]+\.[0-9]+", host_version) is None:
92
+ return "unsupported"
93
+ version = tuple(int(part) for part in host_version.split("."))
94
+ if version < _MINIMUM_HERMES_HOST_VERSION:
95
+ return "unsupported"
96
+ if host_version in SUPPORTED_HERMES_HOST_VERSIONS:
97
+ return "verified"
98
+ return "beyond-verified"
99
+
100
+
101
+ def _beyond_verified_host_note(host_version: str) -> str | None:
102
+ if _classify_hermes_host_version(host_version) != "beyond-verified":
103
+ return None
104
+ return (
105
+ f"[NOTE] Hermes host {host_version} is beyond the verified matrix "
106
+ "(0.17.0, 0.19.0); diagnostics are read-only"
107
+ )
87
108
 
88
109
 
89
110
  @dataclass(frozen=True, slots=True)
@@ -94,6 +115,7 @@ class ModelCapabilities:
94
115
  child_effort: str
95
116
  concurrency: int
96
117
  async_batches: int
118
+ shared_async_cap: bool
97
119
  spawn_depth: int
98
120
  flat: bool
99
121
  approved: bool
@@ -203,7 +225,7 @@ def _cataloged_route(model: object, effort: object) -> bool:
203
225
 
204
226
 
205
227
  def _parse_capabilities(host_version: str) -> CapabilityResult:
206
- if host_version not in SUPPORTED_HERMES_HOST_VERSIONS:
228
+ if _classify_hermes_host_version(host_version) == "unsupported":
207
229
  return UnavailableCapabilities("unsupported Hermes host version")
208
230
  try:
209
231
  text = _host_config_path().read_text(encoding="utf-8")
@@ -221,7 +243,8 @@ def _parse_capabilities(host_version: str) -> CapabilityResult:
221
243
  return UnavailableCapabilities("malformed host config")
222
244
  if _has_credential_key(config):
223
245
  return UnavailableCapabilities("credential-risk host config")
224
- if config.get("_config_version") != 30:
246
+ schema_version = config.get("_config_version")
247
+ if type(schema_version) is not int or schema_version < 30:
225
248
  return UnavailableCapabilities("unknown host config schema")
226
249
  for key in _SAFE_CHILDREN:
227
250
  if key in config and not isinstance(config[key], dict):
@@ -256,7 +279,8 @@ def _parse_capabilities(host_version: str) -> CapabilityResult:
256
279
  child_effort = effort if child_effort_raw is None or child_effort_raw == "" else child_effort_raw
257
280
  child_provider = provider if child_provider_raw is None or child_provider_raw == "" else child_provider_raw
258
281
  concurrency_raw = delegation_config.get("max_concurrent_children", "")
259
- async_raw = delegation_config.get("max_async_children", 3)
282
+ shared_async_cap = schema_version >= 33
283
+ async_raw = 1 if shared_async_cap else delegation_config.get("max_async_children", 3)
260
284
  depth_raw = delegation_config.get("max_spawn_depth", 1)
261
285
  orchestrator_enabled = delegation_config.get("orchestrator_enabled", True)
262
286
  delegation_provider = delegation_config.get("provider") or provider
@@ -355,6 +379,7 @@ def _parse_capabilities(host_version: str) -> CapabilityResult:
355
379
  child_effort=child_effort,
356
380
  concurrency=concurrency,
357
381
  async_batches=async_batches,
382
+ shared_async_cap=shared_async_cap,
358
383
  spawn_depth=spawn_depth,
359
384
  flat=flat,
360
385
  approved=approved,
@@ -369,16 +394,22 @@ def _recursion_detail(spawn_depth: int, flat: bool) -> str:
369
394
  return f"hard (configured depth {spawn_depth}, flat via orchestrator kill switch)"
370
395
 
371
396
 
397
+ def _concurrency_detail(concurrency: int, async_batches: int, shared_async_cap: bool) -> str:
398
+ if shared_async_cap:
399
+ return f"per batch {concurrency}; background cap {concurrency}; potential children {concurrency}"
400
+ return f"per batch {concurrency}; async batches {async_batches}; potential children {concurrency * async_batches}"
401
+
402
+
372
403
  def _capability_status_lines(host_version: str) -> list[str]:
373
404
  result = _parse_capabilities(host_version)
374
405
  match result:
375
- case ModelCapabilities(parent_model=parent_model, parent_effort=parent_effort, child_model=child_model, child_effort=child_effort, concurrency=concurrency, async_batches=async_batches, spawn_depth=spawn_depth, flat=flat):
406
+ case ModelCapabilities(parent_model=parent_model, parent_effort=parent_effort, child_model=child_model, child_effort=child_effort, concurrency=concurrency, async_batches=async_batches, shared_async_cap=shared_async_cap, spawn_depth=spawn_depth, flat=flat):
376
407
  lines = [
377
408
  f"parent model: {parent_model}",
378
409
  f"parent effort: {parent_effort}",
379
410
  f"global child route: configured ({child_model}, effort {child_effort}, provider inherited)",
380
411
  "child execution proof: unavailable (delegate_task receipt required)",
381
- f"concurrency: hard (per batch {concurrency}; async batches {async_batches}; potential children {concurrency * async_batches})",
412
+ f"concurrency: hard ({_concurrency_detail(concurrency, async_batches, shared_async_cap)})",
382
413
  f"recursion: {_recursion_detail(spawn_depth, flat)}",
383
414
  "auto-compaction: unavailable (ratio-only compression; no exact 650K schema)",
384
415
  f"runtime: hard ({_OPENAI_PROVIDER} {_RESPONSES_MODE})",
@@ -408,7 +439,7 @@ def _capability_status_lines(host_version: str) -> list[str]:
408
439
  def status_report(host_version: str | None = None) -> str:
409
440
  version = host_version or hermes_host_version()
410
441
  skills = _skill_names()
411
- return "\n".join([
442
+ lines = [
412
443
  f"LitHermes plugin {plugin_version()} (Hermes host {version})",
413
444
  f"plugin dir: {PLUGIN_ROOT}",
414
445
  f"hooks ({len(HOOKS)}): {', '.join(HOOKS)}",
@@ -424,7 +455,11 @@ def status_report(host_version: str | None = None) -> str:
424
455
  f"litgoal evidence kinds: {', '.join(_evidence_kinds())}",
425
456
  f"scientific visualization: {_science.dependency_summary()}",
426
457
  *_capability_status_lines(version),
427
- ])
458
+ ]
459
+ host_note = _beyond_verified_host_note(version)
460
+ if host_note:
461
+ lines.insert(1, host_note)
462
+ return "\n".join(lines)
428
463
 
429
464
 
430
465
  def doctor_report(host_version: str | None = None) -> tuple[list[str], int]:
@@ -463,14 +498,17 @@ def doctor_report(host_version: str | None = None) -> tuple[list[str], int]:
463
498
  lines.append(f"[OK] Hermes host detected (v{version})")
464
499
  else:
465
500
  lines.append("[NOTE] Hermes host version unknown (running outside Hermes?)")
501
+ host_note = _beyond_verified_host_note(version)
502
+ if host_note:
503
+ lines.append(host_note)
466
504
  capabilities = _parse_capabilities(version)
467
505
  match capabilities:
468
- case ModelCapabilities(parent_model=parent_model, parent_effort=parent_effort, child_model=child_model, child_effort=child_effort, concurrency=concurrency, async_batches=async_batches, spawn_depth=spawn_depth, flat=flat):
506
+ case ModelCapabilities(parent_model=parent_model, parent_effort=parent_effort, child_model=child_model, child_effort=child_effort, concurrency=concurrency, async_batches=async_batches, shared_async_cap=shared_async_cap, spawn_depth=spawn_depth, flat=flat):
469
507
  lines.extend([
470
508
  f"[OK] parent model {parent_model} / effort {parent_effort}",
471
509
  f"[NOTE] global child route configured ({child_model}, effort {child_effort}, provider inherited)",
472
510
  "[NOTE] child execution proof unavailable (delegate_task receipt required)",
473
- f"[OK] concurrency hard (per batch {concurrency}; async batches {async_batches}; potential children {concurrency * async_batches})",
511
+ f"[OK] concurrency hard ({_concurrency_detail(concurrency, async_batches, shared_async_cap)})",
474
512
  f"[{'OK' if flat else 'WARN'}] recursion {_recursion_detail(spawn_depth, flat)}",
475
513
  "[OK] auto-compaction unavailable (ratio-only compression; no exact 650K schema)",
476
514
  f"[OK] runtime hard ({_OPENAI_PROVIDER} {_RESPONSES_MODE})",
@@ -1,7 +1,7 @@
1
1
  {
2
- "syncedAt": "2026-09-24T07:38:36.208Z",
2
+ "syncedAt": "2026-09-24T15:44:37.289Z",
3
3
  "source": "bundled-payload",
4
- "sourceHash": "ae1d45a687de0c01415820ff467295f77a175cc393e4923b940729668f58c49b",
4
+ "sourceHash": "ab8de1105823a7d9d640d47cb0e65d2818dbb1080e5b6dc68898e6db21f5d831",
5
5
  "files": [
6
6
  {
7
7
  "path": "NOTICE.md",
@@ -85,7 +85,7 @@
85
85
  },
86
86
  {
87
87
  "path": "diagnostics.py",
88
- "sha256": "8d8196c1c50a6dfa44a68f8681a22b3c84428776bc7b0af1847d80d30346f0d0"
88
+ "sha256": "f81d995ed89fda91716db19aaed536c45b961211d41039186637b5f454d7701c"
89
89
  },
90
90
  {
91
91
  "path": "handoff.py",
@@ -157,7 +157,7 @@
157
157
  },
158
158
  {
159
159
  "path": "plugin.yaml",
160
- "sha256": "9a82f3005c45dab04f48b1bdd4ef79937bdbf7dae7e0f2fcd9a5a391a64c3c96"
160
+ "sha256": "7a95bad1937cb8d455e3c89d5d4ee300ea42e0fb1320357f024ff9cdbbb7aca3"
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": "1a7d471fc7a12ec4eb74d7a78110e5104564a64417f2687e90df89dd80c3b249"
1248
+ "sha256": "8d753d41b63d666bd1cdd64f8f580faa8bab5bae52ddab5c32c9c710e63f0f59"
1249
1249
  },
1250
1250
  {
1251
1251
  "path": "skills/frontend-ui-ux/references/composition.md",
@@ -1969,7 +1969,7 @@
1969
1969
  },
1970
1970
  {
1971
1971
  "path": "skills/visual-qa/references/complete-contract.md",
1972
- "sha256": "fa3842123069e693ee20784e40f08e79a9e0f6854bf62af89d44f9faf13c39f8"
1972
+ "sha256": "b35b71a8751a90ac8ce40251b8a2d18860068db96e7bd4eedda88fd7b548b362"
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.6
2
+ version: 1.0.7
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.6
434
+ Installed LitHermes 1.0.7
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.6)
451
+ [OK] plugin.yaml readable (version 1.0.7)
452
452
  [OK] skills bundled: 32
453
453
  [OK] litgoal durable runtime importable
454
454
  ```
@@ -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.6
488
+ Installed LitHermes 1.0.7
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.6)
505
+ [OK] plugin.yaml readable (version 1.0.7)
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.6",
3
+ "version": "1.0.7",
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.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>
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="146" height="20" role="img" aria-label="release: 1.0.7"><title>release: 1.0.7</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.7</text></g></svg>
package/src/lib/check.js CHANGED
@@ -1,7 +1,7 @@
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, readExternalSkillDirsConfig } = require("./config");
4
+ const { configHasLitHermes, formatConcurrencyCapability, inspectHermesCapabilities, readConfig, readExternalSkillDirsConfig } = require("./config");
5
5
  const { detectHermesRuntimeRepo, detectHermesVersion, ensureHermesHome, expandHome, inspectHermesHostCapabilities, LitHermesError } = require("./hermesDiscovery");
6
6
  const { formatManagedRoute } = require("./modelRoutePolicy");
7
7
  const { inspectPythonCache } = require("./files");
@@ -271,7 +271,7 @@ function doctorLitHermes(flags = {}) {
271
271
  `skill shadow check: ${skillShadows.length ? "WARNING" : "PASS"}`,
272
272
  ...skillShadows.map(formatSkillShadowWarning),
273
273
  `auto-compaction: ${auto.status}${auto.reason ? ` (${auto.reason})` : ""}`,
274
- `concurrency: ${concurrency.status}${concurrency.status === "hard" ? ` (per batch ${concurrency.limit}; async batches ${concurrency.asyncBatchLimit}; potential children ${concurrency.potentialChildCeiling})` : ` (${concurrency.reason})`}`,
274
+ `concurrency: ${formatConcurrencyCapability(concurrency)}`,
275
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})`}`,
276
276
  `model route safety: ${modelSafety.status}${modelSafety.code ? ` (${modelSafety.code}; ${modelSafety.reason})` : ` (${modelSafety.reason})`}`,
277
277
  `runtime: ${runtime.status}${runtime.status === "hard" ? ` (${runtime.provider} ${runtime.apiMode})` : ` (${runtime.reason})`}`,
@@ -5,6 +5,7 @@ const {
5
5
  configHasLitHermes,
6
6
  disableLitHermesConfig,
7
7
  enableLitHermesConfig,
8
+ formatConcurrencyCapability,
8
9
  inspectHermesCapabilities,
9
10
  planModelConfig,
10
11
  readConfig,
@@ -245,9 +246,7 @@ function capabilityLines(plan, { dryRun = false } = {}) {
245
246
  const auto = autoCompaction.status === "hard"
246
247
  ? `hard (${autoCompaction.limit} tokens)`
247
248
  : `unavailable (${autoCompaction.reason.replace(/^Hermes 0\.17\.0 exposes /, "")})`;
248
- const sync = concurrency.status === "hard"
249
- ? `hard (per batch ${concurrency.limit}; async batches ${concurrency.asyncBatchLimit}; potential children ${concurrency.potentialChildCeiling})`
250
- : `${concurrency.status} (${concurrency.reason})`;
249
+ const sync = formatConcurrencyCapability(concurrency);
251
250
  const nesting = recursion.status === "hard"
252
251
  ? recursion.flatBy === "depth"
253
252
  ? `hard (depth ${recursion.limit}, flat)`
@@ -1,7 +1,7 @@
1
1
  const fs = require("node:fs");
2
2
  const path = require("node:path");
3
3
  const { writeFileAtomic } = require("./files");
4
- const { OPENAI_PROVIDER, RESPONSES_MODE, classifyHostVersion,
4
+ const { OPENAI_PROVIDER, RESPONSES_MODE, VERIFIED_CONFIG_VERSION, classifyHostVersion,
5
5
  exactHostVersion, parseBoundary, sourceHash } = require("./modelConfigBoundary");
6
6
  const {
7
7
  ASTRA_MODEL,
@@ -138,6 +138,14 @@ function unavailableCapabilities(reason) {
138
138
  };
139
139
  }
140
140
 
141
+ function formatConcurrencyCapability(concurrency) {
142
+ if (concurrency.status !== "hard") return `${concurrency.status} (${concurrency.reason})`;
143
+ if (concurrency.sharedAsyncCap) {
144
+ return `hard (per batch ${concurrency.limit}; background cap ${concurrency.backgroundCap}; potential children ${concurrency.potentialChildCeiling})`;
145
+ }
146
+ return `hard (per batch ${concurrency.limit}; async batches ${concurrency.asyncBatchLimit}; potential children ${concurrency.potentialChildCeiling})`;
147
+ }
148
+
141
149
  function safeOriginalDispatchId(dispatch) {
142
150
  if (typeof dispatch !== "string" || !/^[A-Za-z0-9._:/-]{1,128}$/.test(dispatch)) return null;
143
151
  return dispatch;
@@ -199,9 +207,11 @@ function inspectHermesCapabilities(text, options = {}) {
199
207
  }
200
208
  const concurrency = boundary.document.getIn(["delegation", "max_concurrent_children"]);
201
209
  const asyncBatches = boundary.document.getIn(["delegation", "max_async_children"]);
210
+ const configVersion = boundary.document.get("_config_version");
211
+ const sharedAsyncCap = configVersion >= 33;
202
212
  const spawnDepth = boundary.document.getIn(["delegation", "max_spawn_depth"]);
203
213
  const orchestratorEnabled = boundary.document.getIn(["delegation", "orchestrator_enabled"]);
204
- const effectiveAsyncBatches = Number.isInteger(asyncBatches) ? asyncBatches : 3;
214
+ const effectiveAsyncBatches = sharedAsyncCap ? 1 : Number.isInteger(asyncBatches) ? asyncBatches : 3;
205
215
  const effectiveSpawnDepth = Number.isInteger(spawnDepth) ? spawnDepth : 1;
206
216
  const flatDelegation = effectiveSpawnDepth === 1 || orchestratorEnabled === false;
207
217
  const contextLength = boundary.document.getIn(["model", "context_length"]);
@@ -234,12 +244,15 @@ function inspectHermesCapabilities(text, options = {}) {
234
244
  concurrency: concurrency === 20
235
245
  ? {
236
246
  status: "hard",
237
- reason: "effective synchronous concurrency is configured to 20",
247
+ reason: sharedAsyncCap
248
+ ? "effective concurrency and background work share the configured cap of 20"
249
+ : "effective synchronous concurrency is configured to 20",
238
250
  observedSource: "delegation.max_concurrent_children",
239
251
  limit: 20,
240
252
  scope: "per-batch",
241
- asyncBatchLimit: effectiveAsyncBatches,
242
- potentialChildCeiling: 20 * effectiveAsyncBatches,
253
+ ...(sharedAsyncCap
254
+ ? { sharedAsyncCap: true, backgroundCap: 20, potentialChildCeiling: 20 }
255
+ : { asyncBatchLimit: effectiveAsyncBatches, potentialChildCeiling: 20 * effectiveAsyncBatches }),
243
256
  }
244
257
  : {
245
258
  status: "unavailable",
@@ -379,15 +392,22 @@ function planModelConfig(text, options = {}) {
379
392
  document.setIn(["delegation", "max_spawn_depth"], 1);
380
393
  document.setIn(["delegation", "orchestrator_enabled"], false);
381
394
  const plannedText = document.toString({ lineWidth: 0 });
395
+ const beyondVerifiedReasons = [];
396
+ if (classifyHostVersion(options.hostVersion).status === "beyond-verified") {
397
+ beyondVerifiedReasons.push(`Hermes ${request.hostVersion} is beyond the verified matrix; source and runtime markers verified, model schema written`);
398
+ }
399
+ const configVersion = document.get("_config_version");
400
+ if (configVersion > VERIFIED_CONFIG_VERSION) {
401
+ beyondVerifiedReasons.push(`config schema ${configVersion} is beyond the verified ceiling ${VERIFIED_CONFIG_VERSION}`);
402
+ }
382
403
  return {
383
404
  action: "write",
384
405
  backupAllowed: true,
385
406
  capabilities: inspectHermesCapabilities(plannedText, { ...options, ...route }),
386
407
  classification,
387
- reason:
388
- classifyHostVersion(options.hostVersion).status === "beyond-verified"
389
- ? `Hermes ${request.hostVersion} is beyond the verified matrix; source and runtime markers verified, model schema written`
390
- : `verified Hermes ${request.hostVersion} model schema`,
408
+ reason: beyondVerifiedReasons.length
409
+ ? beyondVerifiedReasons.join("; ")
410
+ : `verified Hermes ${request.hostVersion} model schema`,
391
411
  request,
392
412
  sourceHash: sourceHash(String(text || "")),
393
413
  text: plannedText,
@@ -429,6 +449,7 @@ function applyModelConfigPlan(hermesHome, plan) {
429
449
  module.exports = {
430
450
  applyModelConfigPlan,
431
451
  classifyModelConfig,
452
+ formatConcurrencyCapability,
432
453
  inspectHermesCapabilities,
433
454
  planModelConfig,
434
455
  revalidateModelConfigPlan,
@@ -17,6 +17,7 @@ const MINIMUM_HOST_VERSION = "0.17.0";
17
17
  // malformed, which must still be reported as unsupported.
18
18
  const NOT_PROBED_HOST_VERSION = "__lithermes_dry_run_not_probed__";
19
19
  const CONFIG_VERSION = 30;
20
+ const VERIFIED_CONFIG_VERSION = 45;
20
21
  const CREDENTIAL_KEY = /(^|[_-])(api[_-]?key|client[_-]?secret|auth[_-]?token|(?:aws[_-]?)?access[_-]?key(?:[_-]?id)?|(?:ssh[_-]?)?private[_-]?key|token|password|passphrase|secret|credential|authorization)([_-]|$)/i;
21
22
  const MAP_PATHS = ["model", "agent", "delegation", "compression"];
22
23
  const SCALAR_PATHS = [
@@ -165,8 +166,9 @@ function parseBoundary(text, options = {}) {
165
166
  return { error: "malformed host config" };
166
167
  }
167
168
  const credentialKey = findCredentialRiskKey(document);
168
- if (document.get("_config_version") !== CONFIG_VERSION) {
169
- return { error: `unknown host config schema; expected version ${CONFIG_VERSION}` };
169
+ const configVersion = document.get("_config_version");
170
+ if (!Number.isInteger(configVersion) || configVersion < CONFIG_VERSION) {
171
+ return { error: `unknown host config schema; expected integer version >= ${CONFIG_VERSION}` };
170
172
  }
171
173
  for (const key of MAP_PATHS) {
172
174
  const node = document.get(key, true);
@@ -208,6 +210,7 @@ module.exports = {
208
210
  NOT_PROBED_HOST_VERSION,
209
211
  OPENAI_PROVIDER,
210
212
  RESPONSES_MODE,
213
+ VERIFIED_CONFIG_VERSION,
211
214
  classifyHostVersion,
212
215
  exactHostVersion,
213
216
  parseBoundary,