docs(tools): placement doctrine for Tools.md, plus the pointer rot the old model left behind - #1707
Open
anikinsasha wants to merge 5 commits into
Open
Conversation
…ng them alive The Deprecated Skills list in Tools.md retires six skill names. Five of them (Images, VideoTranscript, VoiceNarration, YouTube, Sensitive) no longer resolve to anything in the tree, so the rows are archaeology — and the stale pointers still aimed at those skills made them look live: LIFEOS/TOOLS/AddBg.ts:7,13 -> 'Part of the Images skill' + @see skills/Images/SKILL.md LIFEOS/TOOLS/RemoveBg.ts:7 -> 'Part of the Images skill' LIFEOS/TOOLS/GetTranscript.ts -> bun ~/.claude/skills/Videotranscript/Tools/GetTranscript.ts (x4) LIFEOS/TOOLS/YouTubeApi.ts:13 -> bun ~/.claude/skills/YouTube/Tools/YouTubeApi.ts skills/Art/Workflows/{Mermaid,Visualize,Visualize,Essay}.md -> 'use the Images skill' Each pointer now names the tool that actually ships. The four Art lines already carried the correct 'bun ~/.claude/LIFEOS/TOOLS/RemoveBg.ts' command directly underneath; only the label was stale. ExtractTranscript keeps its row: both targets ship (extract-transcript.py and ExtractTranscript.ts), so the name still resolves and the row does real work. The section now states that rule so the next retirement is decidable. Verified: the five retired names have zero remaining occurrences under LifeOS/install/.
The Inference-max Fable-carrier mechanism (subprocess spawn, modelUsage read-back, verifyExecutedModel, the downgrade log) was written out three times: RouterSystem.md § 3 Select the model, Tools.md § Inference.ts, and the Architecture Router row. Three copies drift independently, and two of them already disagreed on how the check works. RouterSystem.md keeps the mechanism — it sits inside the select-model stage, which is where the behavior belongs. The other two become pointers. Worth naming: RouterSystem.md opens with a RETIRED banner, but that banner retires the classify and route-effort stages. Select-model survived, so the paragraph the pointers aim at is live text inside a doc labeled history. The Tools.md pointer says so, otherwise the banner reads as 'ignore this'.
The old section said: put a .ts or .py file directly in LIFEOS/TOOLS, 'keep the directory flat - NO subdirectories', document it here. Five directory tools ship under LIFEOS/TOOLS/ today (Conveyor, ISARender, TokenXray, healthsync, llcli), so the rule contradicts the tree it governs, and it gives no guidance at all on shape: what a section should contain, how long it may run, or what does not belong in this file in the first place. The doctrine replacing it covers four things the old section did not: - Three tiers with different registration rules. Flat tools are selective here and exhaustive in the generated registry. Directory tools are exhaustive over the ADOPTED set — a directory existing on disk is not adoption, so an instance is never silently out of compliance for carrying a subsystem it has not committed to. External tools are exhaustive here because nothing else indexes them. - What is not a tool, and where it goes instead: hooks, HTTP routes, harness primitives, changelogs, local-deviation inventories, skills. These are the categories that actually accreted into tool indexes. - One entry template for all tiers, with a per-tier row list. - A ~15-non-blank-line working ceiling. The line count is the smell test; the structural bans (no archaeology, one entry per tool edited in place, at most one table) are the operative rule — a compliant entry cannot get long, and a long entry is already breaking one of them. Also folds in the flat-tool header contract, since the generated registry reads those headers, and keeps stock's 'don't create a separate skill for a CLI command' closer. Every pointer in the two tables resolves against this tree. Not in scope: enforcement. This is doctrine a human follows; --audit reports against it, nothing blocks on it.
Tools.md documents 21 tools. 134 files sit in the LIFEOS/TOOLS root. The gap is not a documentation backlog — a curated index SHOULD be selective — but without a second surface there is nowhere to look up the other 113, and 'not in Tools.md' silently reads as 'does not exist'. This splits the two jobs. Tools.md stays curated: the tools whose invocation needs more than one line. FlatTools.md is generated from each tool's own leading header and is exhaustive over the root, so absence from the curated index stops meaning absence from the system. hooks/lib/flat-tool-header.ts header parser + contract check + renderer LIFEOS/TOOLS/ToolsRegistry.ts CLI: write / --check / --stdout / --audit DOCUMENTATION/Tools/FlatTools.md generated output, committed Deterministic: no timestamps, LC-stable sort, so regeneration on an unchanged tree is a zero diff and --check works as a staleness gate. Current output over this tree: 134 tools, 32 headers short of the element contract. Those 32 are pre-existing and unchanged by this PR — the registry just makes them addressable (ToolsRegistry.ts --audit lists them by name). Notes on the parser, since headers in this tree vary: - The env-normalization preamble from danielmiessler#1404 is skipped, not read as a header. - An ASCII hyphen only separates an identity line when followed by a space, so a usage line like 'algorithm -m loop -p <ISA>' is not mistaken for one. - .sh and .py headers parse too (# comments, Python docstrings), so the registry covers the whole root rather than the .ts subset. - Class comes from what the header declares: an Install* prefix, a com.lifeos.*.plist schedule, or a 'not a CLI' / 'Consumed by:' marker. No hand-maintained lists — a tool reclassifies itself by editing its header. Paths resolve via getLifeosDir(), so plugin installs work.
SECONDARY — separately reviewable, and droppable without touching the rest
of this PR.
The placement doctrine says HTTP routes belong to the owning subsystem's doc
and Claude Code harness primitives belong to DelegationSystem.md. Two sections
in Tools.md were on the wrong side of that line, so this applies the rule to
the file that states it.
Nothing is deleted — both sections move whole:
Voice Server API (~44 lines) -> NotificationSystem.md § Long-form Narration.
/notify is a Pulse route, and NotificationSystem.md already documented the
same endpoint for notifications; the narration triggers, tuning values and
450-char segment rule join it there.
Monitor + 6 recipes (~90 lines) -> DelegationSystem.md § Async Primitives.
Monitor is a harness primitive this repo does not ship. Async Primitives
already carried the Monitor rules nearly verbatim, so only the recipe
cookbook is new content there; the duplicated rule list is dropped rather
than moved twice.
Tools.md keeps a one-line stub at each site pointing to the new home, so a
reader who goes looking where the section used to be still lands correctly.
The Research-skill cross-reference is repointed too.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tools.mdtells you how to add a tool, and the instructions no longer match the tree. It says "keep the directory flat - NO subdirectories" while five directory tools ship underLIFEOS/TOOLS/. It says "document here" for every new tool while documenting 21 of the 134 files in that root. And it says nothing about shape — how long an entry may run, or what should never have been in a tool index in the first place.This replaces that section with a placement doctrine, and fixes the pointer rot the old model left behind.
Five commits, each independently reviewable. The last two are droppable — see below.
1.
docs(tools): retire dead deprecated-skill rows and the pointers keeping them aliveThe Deprecated Skills list retires six skill names. Five of them — Images, VideoTranscript, VoiceNarration, YouTube, Sensitive — no longer resolve to anything in the tree. What kept them looking live was a set of stale pointers still aimed at the retired skills:
LIFEOS/TOOLS/AddBg.ts:7,13@see ~/.claude/skills/Images/SKILL.mdLIFEOS/TOOLS/RemoveBg.ts:7LIFEOS/TOOLS/GetTranscript.ts:7,8,11,12bun ~/.claude/skills/Videotranscript/Tools/GetTranscript.tsLIFEOS/TOOLS/YouTubeApi.ts:13bun ~/.claude/skills/YouTube/Tools/YouTubeApi.tsskills/Art/Workflows/{Mermaid,Visualize×2,Essay}.mdEach now names the tool that actually ships. The four Art lines already carried the correct
bun ~/.claude/LIFEOS/TOOLS/RemoveBg.tscommand directly underneath — only the label was stale.ExtractTranscript keeps its row: both targets ship (
extract-transcript.pyandExtractTranscript.ts), so the name still resolves and the row does real work. The section now states that as the rule — a retirement row earns its place only while the retired name still resolves somewhere — so the next one is decidable rather than a judgment call.Verified: the five retired names have zero remaining occurrences under
LifeOS/install/.2.
docs: give executed-model verification a single homeThe Inference-max Fable-carrier mechanism (subprocess spawn,
modelUsageread-back,verifyExecutedModel, the downgrade log) was written out three times —RouterSystem.md§ 3,Tools.md§ Inference.ts, and the Architecture Router row — and two of the copies already disagreed on how the check works.RouterSystem.mdkeeps the mechanism, since it sits inside the select-model stage where the behavior belongs. The other two become pointers.One thing worth flagging, because it looks wrong at a glance:
RouterSystem.mdopens with a RETIRED banner. That banner retires the classify and route-effort stages. Select-model survived, so the paragraph these pointers aim at is live text inside a doc labeled history. TheTools.mdpointer says so explicitly — otherwise the banner reads as "ignore everything here". If you would rather move that paragraph out of the retired doc entirely, say where and I will re-roll this commit.3.
docs(tools): replace Adding New Tools with a placement doctrineThe doctrine covers four things the old section did not:
It also folds in the flat-tool header contract, since the generated registry reads those headers, and keeps stock's "don't create a separate skill for a CLI command" closer.
Every pointer in both tables resolves against this tree.
Not in scope: enforcement. This is doctrine a human follows.
--auditreports against it; nothing blocks on it.4.
feat(tools): generated flat-tool registry— droppableThis is the half to cut if you want docs-only.
Tools.mddocuments 21 tools; 134 files sit in theLIFEOS/TOOLSroot. The gap is not a documentation backlog — a curated index should be selective — but with only one surface there is nowhere to look up the other 113, and "not in Tools.md" silently reads as "does not exist".So:
Tools.mdstays curated,FlatTools.mdis generated from each tool's own header and exhaustive over the root.hooks/lib/flat-tool-header.tsLIFEOS/TOOLS/ToolsRegistry.ts--check/--stdout/--auditDOCUMENTATION/Tools/FlatTools.mdDeterministic — no timestamps, stable sort — so regeneration on an unchanged tree is a zero diff and
--checkworks as a staleness gate. Paths resolve viagetLifeosDir(), so plugin installs work.Current output over this tree: 134 tools, 32 headers short of the element contract. Those 32 are pre-existing and untouched by this PR; the registry just makes them addressable by name (
ToolsRegistry.ts --audit).Parser notes, since headers in this tree vary:
#1404env-normalization preamble is skipped, not read as a header.algorithm -m loop -p <ISA>is not mistaken for one..shand.pyheaders parse too (#comments, Python docstrings), so the registry covers the whole root rather than the.tssubset.Install*prefix, acom.lifeos.*.plistschedule, anot a CLI/Consumed by:marker. No hand-maintained lists; a tool reclassifies itself by editing its header.If you want docs-only, commit 3 references the registry in six places (the § Placement doctrine intro line, the Flat-tool table row, the selective-flat paragraph, the whole § The flat-tool header subsection, and steps 2 and 5 of § Adding a tool). Say the word and I will push a variant of commit 3 with those re-rolled to point at the tool's own header instead.
5.
docs(tools): relocate the two sections that are not tools— secondary, separately reviewableThe doctrine says HTTP routes belong to the owning subsystem's doc and harness primitives belong to
DelegationSystem.md. Two sections inTools.mdwere on the wrong side of that line, so this applies the rule to the file that states it. Nothing is deleted — both move whole:NotificationSystem.md§ Long-form Narration./notifyis a Pulse route, andNotificationSystem.mdalready documented the same endpoint for notifications.DelegationSystem.md§ Async Primitives. Monitor is a Claude Code harness primitive this repo does not ship. Async Primitives already carried the Monitor rules nearly verbatim, so only the recipe cookbook is new content there; the duplicated rule list is dropped rather than moved twice.Tools.mdkeeps a one-line stub at each site pointing to the new home.Two things the doctrine surfaces that this PR does not fix
Conveyor,ISARender,TokenXray,healthsync,llcli. Under the adopted-set rule that is your call to make, not mine, and three of the five have no README or ISA to point a Depth row at, so I did not want to invent entries. Happy to add pointer sections for whichever you consider adopted.skills/CreateSkill/SKILL.md:302routes utility wrappers toLIFEOS/TOOLS.md, which does not exist (the file isLIFEOS/DOCUMENTATION/Tools/Tools.md). Same class of rot as commit 1, different owner — left alone to keep this PR's scope honest.