lithermes-ai 0.6.0 → 0.8.1

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
@@ -57,7 +57,8 @@ Restart any running Hermes CLI or Hermes gateway process. Then open Hermes and t
57
57
  - Interactive install spinner keeps terminal installs lively while redirected or scripted installs stay plain; use `npx lithermes-ai install --yes --no-spinner` for quiet terminal installs.
58
58
  - `start-work`: open or dry-run a LitHermes plan inside Hermes.
59
59
  - LitHermes workflow skill set: `ai-slop-remover`, `comment-checker`,
60
- `debugging`, `deep-interview`, `frontend-ui-ux`, `lsp`, `programming`, `refactor`,
60
+ `debugging`, `deep-interview`, `frontend-ui-ux`, `git-master`, `init-deep`,
61
+ `lsp`, `programming`, `refactor`,
61
62
  `remove-ai-slops`, `review-work`, `rules`, `start-work`, `lit-plan`,
62
63
  `litgoal`, and `litwork` are installed as `lithermes:*` skills.
63
64
  - The full plugin payload — the `pre_llm_call` / `subagent_stop` hooks, every
package/README_Ko-KR.md CHANGED
@@ -57,7 +57,8 @@ npx lithermes-ai install --yes
57
57
  - interactive install spinner가 terminal 설치는 더 생동감 있게 보여주고, redirect/script 설치는 기존처럼 plain output을 유지합니다. 조용한 terminal 설치가 필요하면 `npx lithermes-ai install --yes --no-spinner`를 사용합니다.
58
58
  - `start-work`: LitHermes plan을 Hermes 작업으로 엽니다.
59
59
  - LitHermes workflow skill set: `ai-slop-remover`, `comment-checker`,
60
- `debugging`, `deep-interview`, `frontend-ui-ux`, `lsp`, `programming`, `refactor`,
60
+ `debugging`, `deep-interview`, `frontend-ui-ux`, `git-master`, `init-deep`,
61
+ `lsp`, `programming`, `refactor`,
61
62
  `remove-ai-slops`, `review-work`, `rules`, `start-work`, `lit-plan`,
62
63
  `litgoal`, `litwork`가 `lithermes:*` skill로 함께 설치됩니다.
63
64
  - 전체 plugin payload — `pre_llm_call` / `subagent_stop`
@@ -15,7 +15,8 @@ first-class Hermes skills:
15
15
  - Explicit skills are available as:
16
16
  `lithermes:ai-slop-remover`, `lithermes:comment-checker`,
17
17
  `lithermes:debugging`, `lithermes:deep-interview`,
18
- `lithermes:frontend-ui-ux`, `lithermes:lsp`,
18
+ `lithermes:frontend-ui-ux`, `lithermes:git-master`,
19
+ `lithermes:init-deep`, `lithermes:lsp`,
19
20
  `lithermes:programming`, `lithermes:refactor`,
20
21
  `lithermes:remove-ai-slops`, `lithermes:review-work`,
21
22
  `lithermes:rules`, `lithermes:start-work`, `lithermes:lit-plan`,
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import functools
3
4
  from pathlib import Path
4
5
  from typing import Any
5
6
 
@@ -30,6 +31,14 @@ PORTED_SKILLS = [
30
31
  "frontend-ui-ux",
31
32
  "Apply the LitHermes frontend UI/UX review discipline.",
32
33
  ),
34
+ (
35
+ "git-master",
36
+ "Run the LitHermes git-history specialist for commits, rebases, blame, and bisect.",
37
+ ),
38
+ (
39
+ "init-deep",
40
+ "Generate a hierarchical AGENTS.md knowledge base with the LitHermes onboarding workflow.",
41
+ ),
33
42
  (
34
43
  "lsp",
35
44
  "Use Hermes' native LSP diagnostics with LitHermes LSP guidance.",
@@ -107,6 +116,16 @@ def _handle_lithermes_cli(args) -> int:
107
116
  return 1
108
117
 
109
118
 
119
+ def _ignited(handler):
120
+ """Wrap a slash-command handler so its display prints the LITBURN banner."""
121
+
122
+ @functools.wraps(handler)
123
+ def wrapped(user_args):
124
+ return core.ignite(handler(user_args))
125
+
126
+ return wrapped
127
+
128
+
110
129
  def register(ctx) -> None:
111
130
  base = Path(__file__).resolve().parent
112
131
 
@@ -114,6 +133,9 @@ def register(ctx) -> None:
114
133
  ctx.register_hook("pre_llm_call", _pre_llm_call)
115
134
  # Record each delegate_task child (review lanes, reviewer gate) to the ledger.
116
135
  ctx.register_hook("subagent_stop", core.subagent_stop)
136
+ # Force the LITBURN banner onto a bare-`lit` keyword turn's response (that
137
+ # path has no deterministic display channel; slash commands print it directly).
138
+ ctx.register_hook("transform_llm_output", core.transform_llm_output)
117
139
 
118
140
  # Model-facing litgoal tools (durable criteria/evidence/checkpoint/steering/gate).
119
141
  litgoal_tools.register_tools(ctx)
@@ -128,55 +150,55 @@ def register(ctx) -> None:
128
150
 
129
151
  ctx.register_command(
130
152
  "lit-plan",
131
- core.command_lit_plan,
153
+ _ignited(core.command_lit_plan),
132
154
  description="Create a durable Litwork implementation plan",
133
155
  args_hint='"what to build"',
134
156
  )
135
157
  ctx.register_command(
136
158
  "litwork-plan",
137
- core.command_lit_plan,
159
+ _ignited(core.command_lit_plan),
138
160
  description="Alias for /lit-plan",
139
161
  args_hint='"what to build"',
140
162
  )
141
163
  ctx.register_command(
142
164
  "lit",
143
- core.command_lit,
165
+ _ignited(core.command_lit),
144
166
  description="Start an Litwork run and execute the task immediately",
145
167
  args_hint='"task" [--completion-promise TEXT] [--strategy reset|continue]',
146
168
  )
147
169
  ctx.register_command(
148
170
  "lit-loop",
149
- core.command_lit_loop,
171
+ _ignited(core.command_lit_loop),
150
172
  description="Start an Litwork run and execute the task immediately",
151
173
  args_hint='"task" [--completion-promise TEXT] [--strategy reset|continue]',
152
174
  )
153
175
  ctx.register_command(
154
176
  "litwork-loop",
155
- core.command_lit_loop,
177
+ _ignited(core.command_lit_loop),
156
178
  description="Alias for /lit-loop",
157
179
  args_hint='"task" [--completion-promise TEXT] [--strategy reset|continue]',
158
180
  )
159
181
  ctx.register_command(
160
182
  "litgoal",
161
- core.command_litgoal,
183
+ _ignited(core.command_litgoal),
162
184
  description="Open or inspect the LitHermes litgoal durable runtime",
163
185
  args_hint='["objective"] [--worktree PATH]',
164
186
  )
165
187
  ctx.register_command(
166
188
  "review-work",
167
- core.command_review_work,
189
+ _ignited(core.command_review_work),
168
190
  description="Run the LitHermes 5-lane review orchestrator on the current diff",
169
191
  args_hint="[--base REF]",
170
192
  )
171
193
  ctx.register_command(
172
194
  "start-work",
173
- core.command_start_work,
195
+ _ignited(core.command_start_work),
174
196
  description="Open or dry-run a LitHermes plan against a workspace",
175
197
  args_hint="[plan-name] [--worktree PATH] [--dry-run]",
176
198
  )
177
199
  ctx.register_command(
178
200
  "deep-interview",
179
- core.command_deep_interview,
201
+ _ignited(core.command_deep_interview),
180
202
  description="Run the LitHermes Socratic clarity gate before planning/execution",
181
203
  args_hint="[--quick|--standard|--deep] <idea>",
182
204
  )
@@ -33,9 +33,22 @@ DIRECT_LIT_PATTERN = re.compile(r"^\s*(?:lit|litwork)\b\s+(?P<task>.+?)\s*$", re
33
33
  MAX_TASK_LEN = 4000
34
34
  _SLUG_PATTERN = re.compile(r"[^a-z0-9]+")
35
35
 
36
+ # Deterministic ignite banner. Printed verbatim on every LitHermes slash-command
37
+ # display (the only user-visible plugin channel); also instructed into LIT_CONTEXT
38
+ # for the bare-`lit` keyword path (best-effort — that path only reaches the model).
39
+ LITBURN_BANNER = "🔥 LITBURN IGNITED 🔥"
40
+
41
+ # Session ids whose CURRENT turn triggered the litwork keyword path. The bare
42
+ # `lit` keyword has no deterministic display channel (pre_llm_call only reaches
43
+ # the model), so pre_llm_call flags the turn here and transform_llm_output forces
44
+ # the banner onto that turn's response before the user sees it. Consumed once.
45
+ _PENDING_IGNITE: set[str] = set()
46
+
47
+
36
48
  LIT_CONTEXT = "\n".join(
37
49
  [
38
50
  "<lithermes-litwork>",
51
+ f"FIRST, open your reply with this exact line so the user sees Litwork engage: {LITBURN_BANNER}",
39
52
  "The user invoked Litwork/LitHermes. Operate in a durable, evidence-first loop:",
40
53
  "- restate the concrete completion promise before changing files;",
41
54
  "- keep the implementation scoped to the current repository and existing Hermes patterns;",
@@ -210,9 +223,57 @@ def _extract_run_context_task(message: str) -> str:
210
223
  return _clamp_task(m.group("task")) if m else ""
211
224
 
212
225
 
226
+ # Slash-command handlers are dispatched as handler(user_args) with NO session_id,
227
+ # so they cannot bind the native /goal themselves. They instead embed this marker
228
+ # in their agent_message; pre_llm_call (which DOES receive session_id) reads it and
229
+ # performs the bind. /lit & /lit-loop bind via the run-context block; /litgoal &
230
+ # /lit-plan declare an objective and bind via this marker.
231
+ _BIND_GOAL_PATTERN = re.compile(
232
+ r"<lithermes-bind-goal>(?P<obj>.+?)</lithermes-bind-goal>", re.DOTALL
233
+ )
234
+
235
+
236
+ def _extract_bind_goal(message: str) -> str:
237
+ m = _BIND_GOAL_PATTERN.search(message)
238
+ return _clamp_task(m.group("obj")) if m else ""
239
+
240
+
241
+ def bind_goal_marker(objective: str) -> str:
242
+ """Render the bind-goal marker a command embeds so pre_llm_call binds /goal."""
243
+ objective = (objective or "").strip()
244
+ return f"<lithermes-bind-goal>{objective}</lithermes-bind-goal>" if objective else ""
245
+
246
+
247
+ def ignite(result: str | dict[str, str]) -> str | dict[str, str]:
248
+ """Prepend the LITBURN banner to a command result's user-visible display.
249
+
250
+ ``display`` is the one channel Hermes prints to the user verbatim
251
+ (cli.py _cprint), so the banner deterministically fires on every LitHermes
252
+ slash command. agent_message (model-facing) is left untouched.
253
+ """
254
+ if isinstance(result, dict):
255
+ display = result.get("display")
256
+ if display and not str(display).startswith(LITBURN_BANNER):
257
+ return {**result, "display": f"{LITBURN_BANNER}\n{display}"}
258
+ return result
259
+ if isinstance(result, str) and result.strip() and not result.startswith(LITBURN_BANNER):
260
+ return f"{LITBURN_BANNER}\n{result}"
261
+ return result
262
+
263
+
213
264
  def pre_llm_call(**kwargs: Any) -> dict[str, str] | None:
214
265
  user_message = str(kwargs.get("user_message") or "")
215
266
  session_id = str(kwargs.get("session_id") or "")
267
+ # Clear any stale ignite flag from an interrupted previous turn so it can't
268
+ # leak the banner onto this turn's response. Re-added below only if THIS turn
269
+ # is a keyword-lit turn — keeping the flag scoped to the current turn.
270
+ _PENDING_IGNITE.discard(session_id)
271
+ # /litgoal & /lit-plan declare an objective via the bind-goal marker. Bind it
272
+ # (we have session_id here) and stop — those messages are self-contained.
273
+ bind_obj = _extract_bind_goal(user_message)
274
+ if bind_obj:
275
+ bind_native_goal(session_id, bind_obj)
276
+ return None
216
277
  # The /lit command injects a run-context message. Bind the native goal from
217
278
  # it (we have session_id here), then skip re-injecting context.
218
279
  if "<lithermes-run-context>" in user_message:
@@ -240,9 +301,31 @@ def pre_llm_call(**kwargs: Any) -> dict[str, str] | None:
240
301
  session_id=session_id,
241
302
  platform=str(kwargs.get("platform") or ""),
242
303
  )
304
+ # Flag this turn so transform_llm_output forces the banner onto the response
305
+ # (the keyword path has no deterministic display channel like slash commands).
306
+ if session_id:
307
+ _PENDING_IGNITE.add(session_id)
243
308
  return {"context": LIT_CONTEXT + run_context}
244
309
 
245
310
 
311
+ def transform_llm_output(**kwargs: Any) -> str | None:
312
+ """Force the LITBURN banner onto a keyword-`lit` turn's response.
313
+
314
+ Hermes replaces the user-visible response with the first non-empty string a
315
+ transform_llm_output hook returns. Returning None leaves the text unchanged.
316
+ We only act on turns pre_llm_call flagged, consume the flag once, and dedup so
317
+ a model that already opened with the banner is not double-bannered.
318
+ """
319
+ session_id = str(kwargs.get("session_id") or "")
320
+ if session_id not in _PENDING_IGNITE:
321
+ return None
322
+ _PENDING_IGNITE.discard(session_id)
323
+ response_text = str(kwargs.get("response_text") or "")
324
+ if response_text.lstrip().startswith(LITBURN_BANNER):
325
+ return None # model already emitted it — leave unchanged
326
+ return f"{LITBURN_BANNER}\n\n{response_text}"
327
+
328
+
246
329
  def subagent_stop(**kwargs: Any) -> None:
247
330
  """Record each delegate_task child (e.g. a review lane) to the LitHermes ledger.
248
331
 
@@ -629,6 +712,7 @@ def build_plan_agent_message(brief: str, plan: Path, workspace: Path) -> str:
629
712
  "goal tools (goal_set / goal_add_criterion / goal_evidence / goal_complete) and inspect",
630
713
  "with `hermes lithermes goal status`.",
631
714
  "</lithermes-plan-context>",
715
+ bind_goal_marker(brief),
632
716
  ]
633
717
  )
634
718
 
@@ -799,6 +883,12 @@ def command_litgoal(raw_args: str) -> dict[str, str]:
799
883
  "Load the lithermes:litgoal skill for the full discipline.",
800
884
  "</lithermes-litgoal-command>",
801
885
  ]
886
+ # When an objective is given, bind the native /goal too (pre_llm_call reads
887
+ # this marker — slash handlers have no session_id). Inspect-only /litgoal
888
+ # (no objective) leaves any active goal untouched.
889
+ marker = bind_goal_marker(objective)
890
+ if marker:
891
+ agent_lines.append(marker)
802
892
  return {
803
893
  "display": f"{intro}\nState dir: {lithermes_dir(workspace) / 'litgoal'}",
804
894
  "agent_message": "\n".join(agent_lines),
@@ -1,7 +1,7 @@
1
1
  {
2
- "syncedAt": "2026-06-14T02:25:40.475Z",
2
+ "syncedAt": "2026-06-14T05:53:21.695Z",
3
3
  "source": "source-reference",
4
- "sourceHash": "09f07fa73866ccb4c0a7dc271d4d1ce45a9ac662ff911fab6f4a6d6e7db73c07",
4
+ "sourceHash": "f07cf5a5062f904d4eed678ebf24314e773ca3f92e5c2d1f95c981437e0c5a5a",
5
5
  "files": [
6
6
  {
7
7
  "path": "NOTICE.md",
@@ -9,15 +9,15 @@
9
9
  },
10
10
  {
11
11
  "path": "README.md",
12
- "sha256": "32bbef20afd99f774502c2b4cbf2e2326d40c4e4cd71108645849dddcc2608c4"
12
+ "sha256": "e0bc7d60f61a8d35df9f6287876e236e59e80e871261558701375a12cc4e4feb"
13
13
  },
14
14
  {
15
15
  "path": "__init__.py",
16
- "sha256": "e545ac92efb1a8d50c467b21b180eb41dad5e9a19379a8cbe5086956c21c3654"
16
+ "sha256": "9a0b19060eb12799bf76b15b729fcbab4388d74aac9e888b40369b809fd54669"
17
17
  },
18
18
  {
19
19
  "path": "core.py",
20
- "sha256": "c8cac49c17e573dabc59c4d5aa56402a71320f62145fabf9552e7fdb648f340a"
20
+ "sha256": "6b9d8b488d5905232d170f78943d2b5f9b9a4bde564e01a816c4fcc45098a7df"
21
21
  },
22
22
  {
23
23
  "path": "litgoal/__init__.py",
@@ -49,7 +49,7 @@
49
49
  },
50
50
  {
51
51
  "path": "plugin.yaml",
52
- "sha256": "e90d47b24dc2cb5340d9485929ba40e62b2b5d6858951992c414701f015286fe"
52
+ "sha256": "e8ab5e17a3812c1caf91d98e2fb3cf72f2c7d4a429723f0887b6eb3abd736648"
53
53
  },
54
54
  {
55
55
  "path": "skills/ai-slop-remover/SKILL.md",
@@ -143,6 +143,14 @@
143
143
  "path": "skills/frontend-ui-ux/SKILL.md",
144
144
  "sha256": "914667044f135563658ceac733a085a6bbdd71a00a5f4030f73d43444e0388f7"
145
145
  },
146
+ {
147
+ "path": "skills/git-master/SKILL.md",
148
+ "sha256": "31d59a91767423094fd84ed668c8b8c7e14d515cd17e3845d91a0ce4aa0144c8"
149
+ },
150
+ {
151
+ "path": "skills/init-deep/SKILL.md",
152
+ "sha256": "f571334ad9150fd93ef57fcc9dd85d240812649975811e63045ff2a72e84260b"
153
+ },
146
154
  {
147
155
  "path": "skills/lit-plan/SKILL.md",
148
156
  "sha256": "1f09901f9bb8f19b92add59c3613231228c8b5b7adbefae1cb3eb5cf7c3c61dc"
@@ -1,5 +1,5 @@
1
1
  name: lithermes
2
- version: 0.6.0
2
+ version: 0.8.1
3
3
  description: "Hermes-native workflow toolkit: litgoal durable runtime, 5-lane review orchestrator, Litwork commands, skills, and prompt steering."
4
4
  author: "Hermes Agent"
5
5
  kind: standalone
@@ -7,3 +7,4 @@ auto_load: true
7
7
  hooks:
8
8
  - pre_llm_call
9
9
  - subagent_stop
10
+ - transform_llm_output
@@ -0,0 +1,130 @@
1
+ ---
2
+ name: git-master
3
+ description: "MUST USE whenever a task needs a commit or git-history investigation. Covers atomic commits, staging, commit-message style, rebase, squash, fixup/autosquash, blame, bisect, reflog, git log -S/-G, and questions like who wrote this or when was this added. Do not use for ordinary code edits unless the user asks for git work."
4
+ ---
5
+
6
+ # Git Master
7
+
8
+ The LitHermes git-history specialist for Hermes. Use this skill when the user
9
+ asks you to operate on Git history or answer a Git-history question. Be exact,
10
+ conservative, and evidence-led. Read the repository state before you infer anything.
11
+
12
+ ## LitHermes publish boundary
13
+
14
+ Commit, push, force-push, and history rewrites are outward-facing or hard-to-reverse
15
+ operations. Per LitHermes discipline, do **not** commit, push, force-push, reset,
16
+ stash-pop, or rewrite history unless the user explicitly authorized that exact
17
+ operation. Investigative requests report findings and stop.
18
+
19
+ ## Mode Gate
20
+
21
+ Classify the request first:
22
+
23
+ - `COMMIT`: stage and commit local changes.
24
+ - `REBASE`: rebase, squash, fixup, autosquash, reorder, split, or otherwise rewrite branch history.
25
+ - `HISTORY`: answer when, where, who, why, or which commit changed something.
26
+ - `STATUS`: inspect branch, diff, or working-tree state without changing it.
27
+
28
+ If the request is only investigative, report findings and stop.
29
+
30
+ ## Ground Truth
31
+
32
+ Gather independent facts first (these are read-only and safe to run in parallel):
33
+
34
+ ```bash
35
+ git status --short
36
+ git diff --stat
37
+ git diff --staged --stat
38
+ git branch --show-current
39
+ git log -30 --oneline
40
+ git rev-parse --abbrev-ref @{upstream}
41
+ git merge-base HEAD origin/main
42
+ git merge-base HEAD origin/master
43
+ ```
44
+
45
+ Missing upstream or missing `main`/`master` is normal. Fall back to the best
46
+ available branch or report the missing fact. Never treat a failed lookup as proof.
47
+
48
+ ## Commit Mode
49
+
50
+ Commit only the user's requested changes. Preserve unrelated dirty work.
51
+
52
+ 1. Detect message style from recent history (`git log -30 --pretty=format:%s`). Use the
53
+ dominant local pattern, language, and casing. Do not default to Conventional
54
+ Commits unless the repo already uses them.
55
+ 2. Inspect the full diff, not only filenames. Separate unrelated user edits from the
56
+ requested commit.
57
+ 3. Build atomic groups by behavior, module, and revertability. Keep implementation and
58
+ its direct tests together.
59
+ 4. Prefer multiple commits for unrelated concerns. A single commit is acceptable only
60
+ when the changed files form one indivisible behavior or the user explicitly asks for one.
61
+ 5. Stage by path or hunk so each commit contains only its atomic group.
62
+ 6. Before each commit, verify `git diff --staged --stat` and enough staged diff to prove
63
+ the group is right.
64
+ 7. Commit with the detected style. After each commit, verify `git log -1 --oneline`.
65
+
66
+ Grouping rules:
67
+
68
+ - Split different features, modules, generated artifacts, config, docs, and test-only
69
+ changes unless they are inseparable.
70
+ - Keep generated files with the source change that produced them when omitting them
71
+ would leave the repo inconsistent.
72
+ - Never hide failing or unrelated changes inside a broad commit.
73
+ - Follow the user's git conventions (e.g. no AI/co-author attribution when the repo or
74
+ the user's rules forbid it).
75
+
76
+ Final report: list commit hashes, messages, and any remaining uncommitted files.
77
+
78
+ ## Rebase Mode
79
+
80
+ History rewriting is a shared-impact operation.
81
+
82
+ - Never rebase or rewrite `main`, `master`, `dev`, release branches, or a protected
83
+ branch unless the user explicitly named that exact operation.
84
+ - If commits may already be pushed, ask before force-pushing. Use `--force-with-lease`,
85
+ never plain `--force`.
86
+ - If the worktree is dirty, preserve it intentionally before rebasing. Do not stash-pop
87
+ over conflicts without checking what changed.
88
+ - For fixups, prefer `git commit --fixup=<hash>` then
89
+ `GIT_SEQUENCE_EDITOR=: git rebase -i --autosquash <base>`.
90
+ - For conflicts, read the conflicting files and resolve by intent. Do not choose
91
+ ours/theirs blindly.
92
+ - If a rebase goes wrong, run `git rebase --abort` first. Use reflog only after
93
+ explaining the recovery path.
94
+
95
+ After rewriting, run the relevant tests or at least the project's cheapest smoke check,
96
+ then show the new branch log from base to HEAD.
97
+
98
+ ## History Mode
99
+
100
+ Choose the Git tool by the question:
101
+
102
+ - `git log -S "text"`: when the count of an exact string changed.
103
+ - `git log -G "regex"`: when diffs touched lines matching a pattern.
104
+ - `git blame -L start,end -- file`: who last changed specific lines.
105
+ - `git log --follow -- file`: history across renames for one file.
106
+ - `git show <hash>`: inspect the commit that appears relevant.
107
+ - `git bisect`: find the first bad commit when there is a deterministic pass/fail
108
+ command and known good/bad bounds.
109
+ - `git reflog`: recover or explain recent local history movement.
110
+
111
+ Always cite the exact command evidence in the answer: commit hash, subject, file path,
112
+ and line or diff context when relevant. If the evidence is ambiguous, say what remains
113
+ unproven.
114
+
115
+ ## Safety Checks
116
+
117
+ Before any write to Git history:
118
+
119
+ - Current branch is known.
120
+ - Dirty work is accounted for.
121
+ - Upstream/pushed status is known or explicitly unknown.
122
+ - The operation matches an explicit user request and authorization.
123
+ - Recovery path is known (`rebase --abort`, reflog hash, or untouched worktree).
124
+
125
+ Before finishing:
126
+
127
+ - Run the most relevant verification available for the changed behavior or history
128
+ operation (Manual QA evidence where a behavior changed).
129
+ - Report commands that passed and any command you could not run.
130
+ - Leave the worktree state explicit.
@@ -0,0 +1,198 @@
1
+ ---
2
+ name: init-deep
3
+ description: "Initialize a hierarchical AGENTS.md knowledge base for a repository — a root AGENTS.md plus complexity-scored subdirectory files. Use when the user wants to bootstrap or refresh project knowledge for Hermes, onboard a codebase, generate AGENTS.md guidance (reading any existing CLAUDE.md for context), or map an unfamiliar repo. Adapted for Hermes: discovery and parallel generation via delegate_task children + Hermes lsp tools."
4
+ ---
5
+
6
+ # Init-Deep — hierarchical AGENTS.md generator (Hermes)
7
+
8
+ Generate hierarchical `AGENTS.md` files: a root knowledge base plus complexity-scored subdirectory
9
+ files. This is the LitHermes onboarding/knowledge-base skill, re-authored for Hermes surfaces:
10
+ read-only `delegate_task` children for discovery, Hermes' `lsp` tools for the code map, and parallel
11
+ `delegate_task` fan-out for generation. (`AGENTS.md` is the file Hermes loads natively as project
12
+ context — see the `lithermes:rules` skill.)
13
+
14
+ ## Usage
15
+
16
+ ```
17
+ init-deep # Update mode: modify existing AGENTS.md + create new where warranted
18
+ init-deep --create-new # Read existing → remove all → regenerate from scratch
19
+ init-deep --max-depth=2 # Limit directory depth (default: 3)
20
+ ```
21
+
22
+ ## Workflow (high level)
23
+
24
+ 1. **Discovery + analysis** (concurrent) — read-only `delegate_task` children + local bash structure +
25
+ `lsp` code map + read existing AGENTS.md.
26
+ 2. **Score & decide** — determine AGENTS.md locations from merged findings.
27
+ 3. **Generate** — root first, then subdirectories in parallel.
28
+ 4. **Review** — deduplicate, trim, validate.
29
+
30
+ Track all four phases explicitly and report each one `pending → in_progress → completed` as you go
31
+ (Hermes has no TodoWrite tool; keep the running state in your reply or a working note).
32
+
33
+ ## Phase 1 — Discovery + analysis (concurrent)
34
+
35
+ Mark "discovery" in_progress.
36
+
37
+ ### Fan out read-only discovery children immediately
38
+
39
+ Dispatch the discovery lanes as read-only `delegate_task` children — pass a `tasks` array so they run
40
+ concurrently and the parent blocks until all return. Each child is self-contained (goal + scope +
41
+ "read-only, return findings only"). Suggested lanes (one child each):
42
+
43
+ - **Structure** — predict standard patterns for the detected language; report deviations only.
44
+ - **Entry points** — find main/entry files; report non-standard organization.
45
+ - **Conventions** — find config files (`.eslintrc`, `pyproject.toml`, `.editorconfig`, …); report
46
+ project-specific rules.
47
+ - **Anti-patterns** — find `DO NOT` / `NEVER` / `ALWAYS` / `DEPRECATED` markers; list forbidden patterns.
48
+ - **Build/CI** — find `.github/workflows`, `Makefile`, `Taskfile`; report non-standard patterns.
49
+ - **Tests** — find test configs and structure; report unique conventions.
50
+
51
+ **Dynamic scaling** — after the bash pass below, add MORE `delegate_task` children based on project
52
+ scale (never a static count):
53
+
54
+ | Factor | Threshold | Additional children |
55
+ |--------|-----------|---------------------|
56
+ | Total files | >100 | +1 per 100 files |
57
+ | Total lines | >10k | +1 per 10k lines |
58
+ | Directory depth | ≥4 | +2 for deep exploration |
59
+ | Large files (>500 lines) | >10 files | +1 for complexity hotspots |
60
+ | Monorepo | detected | +1 per package/workspace |
61
+ | Multiple languages | >1 | +1 per language |
62
+
63
+ ```bash
64
+ total_files=$(find . -type f -not -path '*/node_modules/*' -not -path '*/.git/*' | wc -l)
65
+ total_lines=$(find . -type f \( -name "*.ts" -o -name "*.py" -o -name "*.go" \) -not -path '*/node_modules/*' -exec wc -l {} + 2>/dev/null | tail -1 | awk '{print $1}')
66
+ large_files=$(find . -type f \( -name "*.ts" -o -name "*.py" \) -not -path '*/node_modules/*' -exec wc -l {} + 2>/dev/null | awk '$1 > 500 {c++} END {print c+0}')
67
+ max_depth=$(find . -type d -not -path '*/node_modules/*' -not -path '*/.git/*' | awk -F/ '{print NF}' | sort -rn | head -1)
68
+ ```
69
+
70
+ For very broad repos, split the fan-out across several `delegate_task` batches rather than one giant
71
+ batch, but keep every child read-only.
72
+
73
+ ### Main session: concurrent local analysis
74
+
75
+ While the discovery children run, the main session does:
76
+
77
+ **1. Bash structural analysis**
78
+ ```bash
79
+ # Directory depth distribution
80
+ find . -type d -not -path '*/.*' -not -path '*/node_modules/*' -not -path '*/dist/*' -not -path '*/build/*' | awk -F/ '{print NF-1}' | sort -n | uniq -c
81
+ # Files per directory (top 30)
82
+ find . -type f -not -path '*/.*' -not -path '*/node_modules/*' | sed 's|/[^/]*$||' | sort | uniq -c | sort -rn | head -30
83
+ # Existing knowledge bases
84
+ find . -type f \( -name "AGENTS.md" -o -name "CLAUDE.md" \) -not -path '*/node_modules/*' 2>/dev/null
85
+ ```
86
+
87
+ **2. Read existing AGENTS.md** — for each file found, read it and extract key insights,
88
+ conventions, and anti-patterns into an EXISTING map. With `--create-new`, read ALL existing files
89
+ first (preserve context), THEN delete, THEN regenerate.
90
+
91
+ **3. LSP code map (if available)** — use Hermes' `lsp` tools: `lsp.status` to list configured servers,
92
+ then `lsp.symbols` for entry-point/workspace symbols (`class` / `interface` / `function`) and
93
+ `lsp.find_references` on the top exports to gauge centrality. If no server is configured, fall back to
94
+ the discovery children + plain search. (See the `lithermes:lsp` skill.)
95
+
96
+ Merge bash + LSP + existing + child findings. Mark "discovery" completed.
97
+
98
+ ## Phase 2 — Scoring & location decision
99
+
100
+ Mark "scoring" in_progress.
101
+
102
+ ### Scoring matrix
103
+
104
+ | Factor | Weight | High threshold | Source |
105
+ |--------|--------|----------------|--------|
106
+ | File count | 3× | >20 | bash |
107
+ | Subdir count | 2× | >5 | bash |
108
+ | Code ratio | 2× | >70% | bash |
109
+ | Unique patterns | 1× | has own config | child |
110
+ | Module boundary | 2× | has `index.ts`/`__init__.py` | bash |
111
+ | Symbol density | 2× | >30 symbols | LSP |
112
+ | Export count | 2× | >10 exports | LSP |
113
+ | Reference centrality | 3× | >20 refs | LSP |
114
+
115
+ ### Decision rules
116
+
117
+ | Score | Action |
118
+ |-------|--------|
119
+ | Root (`.`) | ALWAYS create |
120
+ | >15 | Create AGENTS.md |
121
+ | 8–15 | Create if it is a distinct domain |
122
+ | <8 | Skip (parent covers it) |
123
+
124
+ Mark "scoring" completed.
125
+
126
+ ## Phase 3 — Generate AGENTS.md
127
+
128
+ Mark "generate" in_progress.
129
+
130
+ **File-writing rule:** if `AGENTS.md` already exists at the target path, edit it in place; if not,
131
+ create it. NEVER overwrite an existing file — check existence first (via the discovery results or a
132
+ read).
133
+
134
+ ### Root AGENTS.md (full treatment)
135
+
136
+ ```markdown
137
+ # PROJECT KNOWLEDGE BASE
138
+ **Generated:** {TIMESTAMP} **Commit:** {SHORT_SHA} **Branch:** {BRANCH}
139
+
140
+ ## OVERVIEW
141
+ {1–2 sentences: what + core stack}
142
+
143
+ ## STRUCTURE
144
+ {tree with non-obvious purposes only}
145
+
146
+ ## WHERE TO LOOK
147
+ | Task | Location | Notes |
148
+
149
+ ## CODE MAP
150
+ {from LSP — skip if unavailable or project <10 files}
151
+
152
+ ## CONVENTIONS
153
+ {ONLY deviations from standard}
154
+
155
+ ## ANTI-PATTERNS (THIS PROJECT)
156
+ {explicitly forbidden here}
157
+
158
+ ## COMMANDS
159
+ {dev / test / build}
160
+
161
+ ## NOTES
162
+ {gotchas}
163
+ ```
164
+
165
+ Quality gate: 50–150 lines, no generic advice, no obvious info.
166
+
167
+ ### Subdirectory AGENTS.md (parallel)
168
+
169
+ Generate each non-root location in parallel — dispatch one writing `delegate_task` child per location
170
+ (batch them in one `delegate_task` call). Each child gets a `TASK:` line plus `DELIVERABLE` (the
171
+ AGENTS.md), `SCOPE` (this directory only), and `VERIFY` (30–80 lines, never repeats parent content;
172
+ sections: OVERVIEW 1 line, STRUCTURE if >5 subdirs, WHERE TO LOOK, CONVENTIONS if different,
173
+ ANTI-PATTERNS). Wait for all. Mark "generate" completed.
174
+
175
+ ## Phase 4 — Review & deduplicate
176
+
177
+ Mark "review" in_progress. For each generated file: remove generic advice, remove parent duplicates,
178
+ trim to the size limits, verify telegraphic style. Mark "review" completed.
179
+
180
+ ## Final report
181
+
182
+ ```
183
+ === init-deep complete ===
184
+ Mode: {update | create-new}
185
+ Files: [OK] ./AGENTS.md (root, {N} lines) · [OK] ./src/hooks/AGENTS.md ({N} lines)
186
+ Dirs analyzed: {N} · Created: {N} · Updated: {N}
187
+ Hierarchy: ./AGENTS.md └── src/hooks/AGENTS.md
188
+ ```
189
+
190
+ ## Anti-patterns
191
+
192
+ - **Static child count** — vary discovery `delegate_task` children by project size/depth (see the scaling table).
193
+ - **Sequential execution** — run discovery children + LSP concurrently; generate subdirectories in parallel.
194
+ - **Ignoring existing** — ALWAYS read existing AGENTS.md first, even with `--create-new`.
195
+ - **Over-documenting** — not every directory needs an AGENTS.md.
196
+ - **Redundancy** — a child file never repeats its parent.
197
+ - **Generic content** — remove anything that applies to all projects.
198
+ - **Verbose style** — telegraphic or die.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lithermes-ai",
3
- "version": "0.6.0",
3
+ "version": "0.8.1",
4
4
  "description": "npx/bunx installer for the LitHermes Hermes plugin",
5
5
  "license": "MIT",
6
6
  "repository": {