hypomnema 1.4.0 → 1.4.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
@@ -13,33 +13,34 @@ English | [한국어](README.ko.md)
13
13
  [![CI](https://github.com/sk-lim19f/Hypomnema/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/sk-lim19f/Hypomnema/actions/workflows/ci.yml)
14
14
  [![GitHub stars](https://img.shields.io/github/stars/sk-lim19f/Hypomnema?style=flat&color=yellow)](https://github.com/sk-lim19f/Hypomnema/stargazers)
15
15
 
16
- **LLM-native personal wiki for Claude Code. Knowledge that compounds.**
16
+ LLM-native personal wiki for Claude Code. Knowledge that compounds.
17
17
 
18
- _Make Claude take notes and measure whether it actually does._
18
+ _Make Claude take notes, and measure whether it actually does._
19
19
 
20
20
  [Quick Start](#quick-start) • [How It Compares](#how-it-compares) • [Design Decisions](#design-decisions) • [Features](#features) • [Architecture](docs/ARCHITECTURE.md) • [Contributing](docs/CONTRIBUTING.md)
21
21
 
22
- > Inspired by Andrej Karpathy's "LLM-native wiki" sketch and shaped by ten months of personal AI-workflow experiments plus one month of Hypomnema dogfooding before the v1.2.0 public release, Hypomnema ships the full lifecycle capture, synthesis, retrieval, session-resume as Claude Code commands and lifecycle hooks.
22
+ Inspired by Andrej Karpathy's "LLM-native wiki" sketch, shaped by ten months of personal AI-workflow experiments and a month of dogfooding before the public release. Hypomnema ships the full lifecycle, from capturing a source to synthesizing, retrieving, and resuming a paused session, as Claude Code commands and lifecycle hooks.
23
23
 
24
- > **Quick decoder for terms used below.** *frontmatter* = the YAML block at the top of a markdown file; *wikilink* = a `[[page-slug]]` cross-reference; *ADR* = "Architecture Decision Record", a short markdown page that records *why* a design choice was made; *projection* = a one-way derive (`pages/feedback/*.md` → `MEMORY.md` / `<learned_behaviors>`); *hook* = a script that Claude Code runs automatically on lifecycle events; *hot.md* / *session-state.md* = the per-project cache files that hold "what just happened" and "what's next" so a paused project resumes in one read. Full glossary lives under [Term decoder](#term-decoder).
24
+ New to the terms below? Keep the [Term decoder](#term-decoder) open in another tab. It defines frontmatter, wikilink, projection, hook, `hot.md`, and `session-state.md`, one line each.
25
25
 
26
- > **Current state vs. v2 vision.** v1.4.0 (current release) is honest about its trigger model: most wiki behavior — ingest, query, session-close — still fires on **explicit `/hypo:*` commands**, but the auto-behavior surface is growing. The v2 thesis is *fully autonomous* — Claude reading, writing, and synthesizing the wiki without being asked. **v1.1.0** shipped the **observability score** that measures how often the wiki is actually used per session (ingest / query / session-close / citation rates). **v1.2.0** adds four load-bearing autonomous lanes on top:
27
- > - **feedback-as-SoT with one-way projections** — `pages/feedback/` becomes the single source-of-truth (SoT) for behavior corrections; the wiki one-way derives `MEMORY.md` and the `<learned_behaviors>` block inside `~/.claude/CLAUDE.md`, so you edit one place and the projections refresh on their own.
28
- > - **extensions companion sync** anything you drop under `~/hypomnema/extensions/{agents,commands,hooks,skills}/` is mirrored into `~/.claude/` automatically; the optional `--codex` flag additionally mirrors `hooks` and `commands` into `~/.codex/` (agents/skills are Claude-only and skipped on the Codex target by design).
29
- > - **auto-project creation on cwd match** — when you `cd` into a git repo with a project marker (`package.json`, `Cargo.toml`, etc.) and no matching wiki project exists, Hypomnema offers to scaffold one for you.
30
- > - **Stop-chain auto-minimal-crystallize + `/clear` recovery** non-trivial sessions get an automatic "save a minimal session-close note?" prompt; `/clear` after a forgotten close is detected and recovered cleanly.
31
- >
32
- > The schema (`SCHEMA.md`) bumps to 2.0 — the `feedback` page type now requires 9 mandatory frontmatter fields. `hypomnema upgrade --apply` writes `MIGRATION-v2.0.md` into the wiki root with a step-by-step backfill checklist. Your own `SCHEMA.md` is **never overwritten** by upgrade we call this policy *Option C*: the upgrade only tells you what changed, and you apply the diff yourself.
33
- >
34
- > **v1.3.0** refines this layer rather than expanding autonomy: the session-close flow gains four *advisory* reflections (they suggest, never auto-act), `hypomnema lint --strict` promotes selected warnings to errors for release gates, and install hardens with **stale-sibling detection** — an older `hypomnema` on `$PATH` can no longer silently downgrade your active hooks.
26
+ ### Where automation stands today
27
+
28
+ The current release is v1.4.1. Wiki work (ingest, query, session-close) still runs on explicit `/hypo:*` commands. The v2 goal is full autonomy: Claude reading, writing, and synthesizing the wiki without being asked, which is the direction this is heading. v1.1.0 shipped the observability score that measures how often the wiki is actually used per session. v1.2.0 added four autonomous lanes on top:
29
+
30
+ - Edit feedback in one place and the rest follows. `pages/feedback/` is the single source of truth for behavior corrections, and Hypomnema derives `MEMORY.md` and the `<learned_behaviors>` block inside `~/.claude/CLAUDE.md` from it automatically.
31
+ - Extensions sync alongside. Anything under `~/hypomnema/extensions/{agents,commands,hooks,skills}/` is mirrored into `~/.claude/` automatically. The `--codex` flag also mirrors `hooks` and `commands` into `~/.codex/`; `agents` and `skills` are Claude-only and skipped on purpose.
32
+ - Auto-project creation. When you `cd` into a git repo with a project marker (`package.json`, `Cargo.toml`, etc.) and no matching wiki project exists, Hypomnema offers to scaffold one.
33
+ - Session-close cleanup and `/clear` recovery. After a non-trivial session, a "save a minimal session-close note?" prompt appears automatically; a `/clear` after a forgotten close is detected and recovered at the next session start.
34
+
35
+ What changed per version lives in the [CHANGELOG](CHANGELOG.md). One policy worth knowing up front: `hypomnema upgrade --apply` never overwrites a `SCHEMA.md` you have edited. When the schema bumps, upgrade writes a migration report into the wiki root and leaves the actual changes for you to apply (the policy the code calls _Option C_).
35
36
 
36
37
  ---
37
38
 
38
39
  ## Quick Start
39
40
 
40
- Hypomnema ships **two install paths**. Pick one both end up with the same wiki, hooks, and `/hypo:*` slash commands.
41
+ There are two install paths. Either one ends up with the same wiki, hooks, and `/hypo:*` slash commands.
41
42
 
42
- ### Path A Claude Code plugin (recommended)
43
+ ### Path A: Claude Code plugin (recommended)
43
44
 
44
45
  Inside Claude Code:
45
46
 
@@ -51,7 +52,7 @@ Inside Claude Code:
51
52
 
52
53
  The plugin install registers `/hypo:*` commands from the package's `commands/` directory; `/hypo:init` then scaffolds the wiki and merges hooks into `~/.claude/settings.json`.
53
54
 
54
- ### Path B npm CLI
55
+ ### Path B: npm CLI
55
56
 
56
57
  In your shell:
57
58
 
@@ -60,7 +61,7 @@ npm install -g hypomnema
60
61
  hypomnema
61
62
  ```
62
63
 
63
- `hypomnema` (or `hypomnema --help` for flags) scaffolds the wiki, installs hooks, **and** copies the slash command files to `~/.claude/commands/hypo/` so `/hypo:*` works inside Claude Code afterwards. Subsequent `hypomnema upgrade` runs use per-file SHA tracking to avoid clobbering anything you have hand-edited.
64
+ `hypomnema` (or `hypomnema --help` for flags) scaffolds the wiki and installs hooks. It also copies the slash command files to `~/.claude/commands/hypo/`, so `/hypo:*` works inside Claude Code afterwards. Later `hypomnema upgrade` runs use per-file SHA tracking, so anything you hand-edited stays put.
64
65
 
65
66
  > Either path: restart Claude Code (or open a new session) after the first run so the new hooks and slash commands are picked up.
66
67
 
@@ -72,25 +73,25 @@ hypomnema
72
73
  /hypo:feedback "always include test commands when explaining a fix"
73
74
  ```
74
75
 
75
- Hooks handle the rest auto-staging, auto-commit/push, session-state injection, lookup signals.
76
+ Hooks handle the rest: auto-staging, auto-commit/push, session-state injection, and lookup signals.
76
77
 
77
- > **Sync across machines:** the wiki is already a git repo. Add a remote, push once, and the `Stop` hook will keep every machine in sync afterwards.
78
+ > Sync across machines: the wiki is already a git repo. Add a remote, push once, and the `Stop` hook keeps every machine in sync afterwards.
78
79
 
79
80
  ---
80
81
 
81
82
  ## Why Hypomnema
82
83
 
83
- Personal knowledge tools fall into five buckets, and each one breaks at a different place:
84
+ Personal knowledge tools fall into five buckets. Each breaks at a different place.
84
85
 
85
86
  | | Pain | Why it doesn't compound |
86
87
  |---|---|---|
87
- | **Note vaults** (markdown-based, local-first) | Manual capture, manual linking, manual rereading | Each note stays independent; no synthesis |
88
- | **Cloud knowledge platforms** (page/database hybrids) | Fast capture, slow retrieval | Search is keyword-first; LLM has no native access |
89
- | **RAG / vector-search stacks** | Pipelines, embeddings, chunking | Returns chunks, not synthesized knowledge; chunks multiply forever |
90
- | **AI-native notebooks** (proprietary "second brain" apps) | Feels magical at first | Closed format, no git, retrieval logic is opaque, vendor lock-in |
91
- | **Code-only wikis** (auto-generated from a repo) | Zero manual effort | Limited to code; can't capture decisions, research, AI behavior corrections |
88
+ | Note vaults (markdown-based, local-first) | Manual capture, manual linking, manual rereading | Each note stays independent; no synthesis |
89
+ | Cloud knowledge platforms (page/database hybrids) | Fast capture, slow retrieval | Search is keyword-first; LLM has no native access |
90
+ | RAG / vector-search stacks | Pipelines, embeddings, chunking | Returns chunks, not synthesized knowledge; chunks multiply forever |
91
+ | AI-native notebooks (proprietary "second brain" apps) | Feels magical at first | Closed format, no git, opaque retrieval logic, vendor lock-in |
92
+ | Code-only wikis (auto-generated from a repo) | Zero manual effort | Limited to code; can't capture decisions, research, AI behavior corrections |
92
93
 
93
- Hypomnema lives in the gap between them: **structured synthesis on top of plain markdown, driven by Claude Code's lifecycle, version-controlled by git, and local-first by default.**
94
+ Hypomnema lives in the gap between them: structured synthesis on top of plain markdown, driven by Claude Code's lifecycle, version-controlled by git, local-first by default.
94
95
 
95
96
  ```
96
97
  Note vaults ───► store everything, synthesize nothing
@@ -106,106 +107,105 @@ Hypomnema ───► synthesis · markdown · git · hooks · local
106
107
 
107
108
  ## How It Compares
108
109
 
109
- | | **Hypomnema** | Note vault | Cloud platform | RAG / vector DB | AI notebook | Code wiki |
110
+ | | Hypomnema | Note vault | Cloud platform | RAG / vector DB | AI notebook | Code wiki |
110
111
  |---|---|---|---|---|---|---|
111
- | **Capture effort** | Paste a URL → done | Manual typing | Manual typing | Upload + embed pipeline | Paste / chat | Auto from repo |
112
- | **Storage unit** | Synthesized **page** | Note | Page / block | Vector chunk | Opaque memory | Code symbol |
113
- | **Knowledge growth** | New sources **update** existing pages | Each note stays independent | Each page stays independent | Chunks multiply forever | Black box | Fixed by repo |
114
- | **Retrieval** | LLM synthesizes a grounded answer | Full-text / backlinks | Keyword search | Nearest-neighbour chunks | Opaque | Code search |
115
- | **Session continuity** | Auto-resume via `hot.md` + `session-state.md` | None | None | None | Sometimes | None |
116
- | **Workflow integration** | Native to Claude Code | Separate app | Separate app / browser tab | Separate service | Separate app | Separate site |
117
- | **Format** | Plain markdown + frontmatter | Markdown | Proprietary | Vector store | Proprietary | HTML |
118
- | **Backend** | Local file + git | Local file | SaaS | Service / DB | SaaS | Service |
119
- | **Behavior tuning** | `/hypo:feedback` permanent rules | None | None | None | Sometimes | None |
120
- | **Auto-behavior** | Explicit `/hypo:*` triggers + **v1.1 observability score** + **v1.2 feedback-as-SoT projection / extensions companion sync / auto-project / Stop-chain auto-minimal-crystallize**; v2 target = fully autonomous | None | None | None | Black box | None |
121
- | **Setup cost** | One command | One install | Sign-up | Pipeline build | Sign-up | Repo connect |
122
- | **Lock-in** | Zero (markdown + git) | Low | High | Medium | High | Medium |
112
+ | Capture effort | Paste a URL → done | Manual typing | Manual typing | Upload + embed pipeline | Paste / chat | Auto from repo |
113
+ | Storage unit | Synthesized page | Note | Page / block | Vector chunk | Opaque memory | Code symbol |
114
+ | Knowledge growth | New sources update existing pages | Each note stays independent | Each page stays independent | Chunks multiply forever | Black box | Fixed by repo |
115
+ | Retrieval | LLM synthesizes a grounded answer | Full-text / backlinks | Keyword search | Nearest-neighbour chunks | Opaque | Code search |
116
+ | Session continuity | Auto-resume via `hot.md` + `session-state.md` | None | None | None | Sometimes | None |
117
+ | Workflow integration | Native to Claude Code | Separate app | Separate app / browser tab | Separate service | Separate app | Separate site |
118
+ | Format | Plain markdown + frontmatter | Markdown | Proprietary | Vector store | Proprietary | HTML |
119
+ | Behavior tuning | `/hypo:feedback` permanent rules | None | None | None | Sometimes | None |
120
+ | Auto-behavior | `/hypo:*` triggers + observability score (v1.1) + four autonomous lanes (v1.2); v2 target = fully autonomous | None | None | None | Black box | None |
121
+ | Setup cost | One command | One install | Sign-up | Pipeline build | Sign-up | Repo connect |
122
+ | Lock-in | Zero (markdown + git) | Low | High | Medium | High | Medium |
123
123
 
124
124
  ### What this trade-off buys you
125
125
 
126
- - **Synthesis, not storage.** You don't end up with a graveyard of half-read articles. Each `/hypo:ingest` produces a structured page; subsequent ingests on the same topic *update* that page.
127
- - **Compounding density.** A wiki with 100 sources should not have 100 disconnected pages. After three months of real use, page count grows sub-linearly while cross-links grow super-linearly.
128
- - **Zero context switch.** You're already in Claude Code. The wiki is one slash command away not another tab, another app, another login.
129
- - **Future-proof storage.** Plain markdown + git means: you can read it in 20 years, you can grep it offline, you can move providers anytime, and AI assistants you haven't met yet will still understand it.
126
+ - Synthesis over storage. You don't end up with a graveyard of half-read articles. Each `/hypo:ingest` produces a structured page, and the next ingest on the same topic updates that page instead of adding a new one.
127
+ - Compounding density. A wiki with 100 sources should not be 100 disconnected pages. After a few months of real use, page count grows sub-linearly while cross-links grow faster.
128
+ - No context switch. You're already in Claude Code. The wiki is one slash command away, with no extra tab, app, or login.
129
+ - Future-proof storage. Plain markdown + git will still be readable in 20 years, greps offline, moves to another tool anytime, and stays usable by AI assistants that don't exist yet, with no conversion needed.
130
130
 
131
131
  ---
132
132
 
133
133
  ## Term decoder
134
134
 
135
- Hypomnema borrows vocabulary from a few worlds. These are the recurring terms used in the rest of the README keep this table open in another tab while you skim.
135
+ These are the recurring terms used in the rest of the README. Keep this table open in another tab while you skim.
136
136
 
137
137
  | Term | Meaning in Hypomnema |
138
138
  |---|---|
139
- | **frontmatter** | The YAML block at the top of a markdown page `title`, `type`, `tags`, etc. |
140
- | **wikilink** | A `[[page-slug]]` cross-reference between pages; resolved at lint time |
141
- | **ADR** | "Architecture Decision Record" a short markdown page recording *why* a non-obvious design choice was made |
142
- | **schema** | The type taxonomy + required-field rules in `SCHEMA.md` what makes a page valid |
143
- | **lint** | A read-only validator (`hypomnema lint`) that checks frontmatter, wikilinks, and schema |
144
- | **projection** | A one-way automatic derivation `pages/feedback/*.md` → `MEMORY.md` and CLAUDE.md `<learned_behaviors>` |
145
- | **SoT** ("source of truth") | The single file you edit; projections derive from it, never the other way around |
146
- | **hook** | A script Claude Code runs automatically on a lifecycle event (e.g. `SessionStart`, `Stop`) |
147
- | **lifecycle event** | A point Claude Code surfaces to plugins: session opens, prompt submitted, tool used, compact requested, session ends, etc. |
148
- | **`hot.md`** | Per-project cache: "what just happened" (most recent session highlights) |
149
- | **`session-state.md`** | Per-project cache: "what's next" (the resume payload for the next session) |
150
- | **`.hypoignore`** | Glob patterns that exclude paths from every content-injection hook and from `ingest` |
151
- | **observability score** | A per-session metric (ingest / query / session-close / citation rates) that measures whether the wiki is actually being used |
152
- | **manifest** | A small JSON the install scripts write to track exactly which files were installed and at what SHA |
153
- | **`additionalContext`** | The Claude Code hook field that injects extra context into the prompt what content-injection hooks emit into |
154
- | **byte-equal** | A file that comes out of `--apply` bit-for-bit identical to before the strongest "we did not touch this" guarantee |
155
- | **BM25** | A classic full-text ranking algorithm; powers the `/hypo:query` MISS-resistant lookup |
156
- | **Option C** | The policy that `hypomnema upgrade --apply` never overwrites your `SCHEMA.md` it only writes a migration report you apply by hand |
157
-
158
- If a term you hit later in the README is missing here, that is a documentation bug please open an issue.
139
+ | frontmatter | The YAML block at the top of a markdown page: `title`, `type`, `tags`, etc. |
140
+ | wikilink | A `[[page-slug]]` cross-reference between pages; resolved at lint time |
141
+ | ADR | "Architecture Decision Record": a short markdown page recording _why_ a non-obvious design choice was made |
142
+ | schema | The type taxonomy and required-field rules in `SCHEMA.md`: what makes a page valid |
143
+ | lint | A read-only validator (`hypomnema lint`) that checks frontmatter, wikilinks, and schema |
144
+ | projection | A one-way automatic derivation: `pages/feedback/*.md` → `MEMORY.md` and CLAUDE.md `<learned_behaviors>` |
145
+ | SoT ("source of truth") | The single file you edit; projections derive from it, never the other way around |
146
+ | hook | A script Claude Code runs automatically on a lifecycle event (e.g. `SessionStart`, `Stop`) |
147
+ | lifecycle event | A point Claude Code surfaces to plugins: session opens, prompt submitted, tool used, compact requested, session ends, etc. |
148
+ | `hot.md` | Per-project cache: "what just happened" (most recent session highlights) |
149
+ | `session-state.md` | Per-project cache: "what's next" (the resume payload for the next session) |
150
+ | `.hypoignore` | Glob patterns that exclude paths from every content-injection hook and from `ingest` |
151
+ | observability score | A per-session metric (ingest / query / session-close / citation rates) that measures whether the wiki is actually being used |
152
+ | manifest | A small JSON the install scripts write to track exactly which files were installed and at what SHA |
153
+ | `additionalContext` | The Claude Code hook field that injects extra context into the prompt: where content-injection hooks emit |
154
+ | byte-equal | A file that comes out of `--apply` bit-for-bit identical to before: the strongest "we did not touch this" guarantee |
155
+ | BM25 | A classic full-text ranking algorithm; powers the `/hypo:query` MISS-resistant lookup |
156
+ | Option C | The policy that `hypomnema upgrade --apply` never overwrites your `SCHEMA.md`: it only writes a migration report you apply by hand |
157
+
158
+ If a term you hit later in the README is missing here, that is a documentation bug. Please open an issue.
159
159
 
160
160
  ---
161
161
 
162
162
  ## Design Decisions
163
163
 
164
- Why each choice looks the way it does:
164
+ Why each choice looks the way it does.
165
165
 
166
- ### 1. Why **synthesis** instead of RAG over chunks
166
+ ### 1. Why synthesis instead of RAG over chunks
167
167
 
168
- RAG is excellent for *unfamiliar* corpora give it a million-page legal archive and it will find relevant fragments. For *personal* knowledge, the failure mode is the opposite:
168
+ RAG is excellent for _unfamiliar_ corpora: give it a million-page legal archive and it will find relevant fragments. For _personal_ knowledge, the failure mode is the opposite.
169
169
 
170
- - The corpus is small but **highly redundant** (3 articles on the same topic).
171
- - The user wants a **point of view**, not a passage.
170
+ - The corpus is small but highly redundant (3 articles on the same topic).
171
+ - The user wants a point of view, not a passage.
172
172
  - Chunk count grows linearly with capture, even when knowledge doesn't.
173
173
 
174
- Hypomnema treats the page not the chunk as the unit of knowledge. New sources reconcile against the page. The result reads like a wiki article, because that's what it is.
174
+ Hypomnema treats the page, not the chunk, as the unit of knowledge. A new source updates the relevant page if one exists and creates a new one if not. The result reads like a wiki article, because that's what it is.
175
175
 
176
- ### 2. Why **markdown + git** instead of a proprietary store
176
+ ### 2. Why markdown + git instead of a proprietary store
177
177
 
178
- A personal knowledge base must outlive any single tool. Markdown survives. Git survives. Both are LLM-native (every model can read them). Both run offline. Both have 30 years of tooling behind them. We deliberately picked the boring stack because the interesting part is *what Claude does with it*.
178
+ A personal knowledge base has to outlive any single tool. Markdown survives. Git survives. Both are LLM-native (every model can read them), both run offline, and both have 30 years of tooling behind them. We picked the boring stack on purpose, because the interesting part is _what Claude does with it_.
179
179
 
180
- ### 3. Why **lifecycle hooks** instead of manual commands
180
+ ### 3. Why lifecycle hooks instead of manual commands
181
181
 
182
- Friction is the silent killer of personal knowledge systems. If saving a thought requires three clicks, you stop. Hypomnema piggybacks on events Claude Code already emits:
182
+ Friction kills personal knowledge systems. If saving a thought takes three clicks, you stop saving thoughts. Hypomnema piggybacks on events Claude Code already emits.
183
183
 
184
- | Event | What you'd otherwise do manually |
184
+ | Event | What you'd otherwise do by hand |
185
185
  |---|---|
186
- | `SessionStart` | "Where did I leave off?" read `hot.md` / `session-state.md` |
187
- | `UserPromptSubmit` | "Do I already know this?" BM25 lookup, top-3 inject |
188
- | `PreCompact` | "Did I forget to write a session log?" checklist guard |
186
+ | `SessionStart` | "Where did I leave off?" reading `hot.md` / `session-state.md` |
187
+ | `UserPromptSubmit` | "Do I already know this?" a BM25 lookup, top-3 inject |
188
+ | `PreCompact` | "Did I close the session?" the checklist guard |
189
189
  | `PostToolUse` (Write/Edit) | `git add` |
190
190
  | `Stop` | `git pull --rebase && git commit && git push` |
191
191
 
192
- Once installed, you stop *managing* the wiki. It just accumulates.
192
+ Once installed, you stop _managing_ the wiki. It just accumulates.
193
193
 
194
- ### 4. Why a **`hot.md` cache** for resume
194
+ ### 4. Why a `hot.md` cache for resume
195
195
 
196
- The most expensive operation in a paused project isn't doing the work it's **rebuilding context**. Reading `session-log/` from scratch costs minutes and tokens; reading a one-page `hot.md` costs neither. So we cache the most recent state explicitly, rebuild it on `Stop`, and inject it on `SessionStart`. Resume is O(1).
196
+ The most expensive part of a paused project isn't redoing the work, it's rebuilding context. Reading `session-log/` from scratch costs minutes and tokens; reading a one-page `hot.md` costs neither. So we cache the most recent state explicitly, rebuild it on `Stop`, and inject it on `SessionStart`. Resume is O(1).
197
197
 
198
- ### 5. Why a **feedback → behavior** pipeline
198
+ ### 5. Why a feedback → behavior pipeline
199
199
 
200
- Most AI tools accept corrections *for the current conversation*. They never persist. Hypomnema funnels every `/hypo:feedback` into `pages/feedback/`, and durable rules are promoted into `CLAUDE.md`'s `<learned_behaviors>` block where they survive every future session, on every machine that pulls the wiki.
200
+ Most AI tools take corrections _for the current conversation only_. They never persist. Hypomnema funnels every `/hypo:feedback` into `pages/feedback/`, and durable rules are promoted into the `<learned_behaviors>` block in `CLAUDE.md`, where they survive every future session, on every machine that pulls the wiki.
201
201
 
202
- ### 6. Why **no API keys, no vector DB, no service**
202
+ ### 6. Why no API keys, no vector DB, no service
203
203
 
204
- Every external dependency is a future-failure mode: it breaks, it's bought, it's deprecated, it leaks credentials. Hypomnema is a Node.js script + markdown files + git. That is the entire stack. The only "AI" piece is Claude itself, which you're running anyway.
204
+ Every external dependency is a future failure: it breaks, gets bought, gets deprecated, or leaks credentials. Hypomnema is a Node.js script + markdown files + git. That's the whole stack. The only "AI" piece is Claude itself, which you're running anyway.
205
205
 
206
- ### 7. Why **`.hypoignore`** instead of a privacy mode flag
206
+ ### 7. Why `.hypoignore` instead of a privacy mode flag
207
207
 
208
- We tried a `personal / shared / public` mode matrix in v1.0. It didn't survive contact with reality every privacy decision was a per-path question, and a single file (`.hypoignore`) handles per-path decisions natively. v1.1 deletes the mode concept entirely. One file, one source of truth.
208
+ v1.0 had a `personal / shared / public` mode matrix. It didn't survive contact with reality: every privacy decision turned out to be a per-path question, and a single file (`.hypoignore`) handles per-path decisions natively. v1.1 deleted the mode concept entirely. One file, one source of truth.
209
209
 
210
210
  ---
211
211
 
@@ -213,18 +213,18 @@ We tried a `personal / shared / public` mode matrix in v1.0. It didn't survive c
213
213
 
214
214
  ### Synthesis primitives
215
215
 
216
- Eight commands cover the full capture → retrieval → consolidation cycle.
216
+ Nine commands cover the full capture → retrieval → consolidation cycle.
217
217
 
218
218
  | Command | What it does | When to reach for it |
219
219
  |---|---|---|
220
- | `/hypo:ingest` | Saves the raw source under `sources/`; Claude synthesizes a structured page under `pages/`. The shell helper (`scripts/ingest.mjs`) is read-only it only *lists* pending sources so you know what still needs ingesting | Anytime you read something worth keeping |
220
+ | `/hypo:ingest` | Saves the raw source under `sources/`; Claude synthesizes a structured page under `pages/`. The shell helper (`scripts/ingest.mjs`) is read-only and only _lists_ pending sources | Anytime you read something worth keeping |
221
221
  | `/hypo:query` | BM25 retrieval + LLM synthesis with `[[wikilink]]` citations | When you need an answer grounded in your own notes |
222
222
  | `/hypo:crystallize` | Runs the session-close checklist (steps 1~6) and, on request, synthesizes drafts (steps 7~11) | End of a non-trivial session |
223
223
  | `/hypo:resume` | Loads the most recent session state for an active project | Coming back to a paused project |
224
- | `/hypo:feedback` | Records an AI behavior correction; eligible for promotion to permanent rules | Right when Claude does something wrong (or exactly right) |
224
+ | `/hypo:feedback` | Records an AI behavior correction; eligible for promotion to permanent rules | When Claude gets something wrong, or gets it exactly right |
225
225
  | `/hypo:verify` | Audits pages with `verify_by` frontmatter | When time-bound knowledge might have aged out |
226
226
  | `/hypo:lint` | Validates frontmatter, wikilinks, schema | Before commits, in CI |
227
- | `/hypo:graph` | Generates a wikilink dependency graph | When you want to see structural growth |
227
+ | `/hypo:graph` | Generates a wikilink dependency graph | When you want to see how the structure grew |
228
228
  | `/hypo:rename` | Renames a page or directory and rewrites inbound `[[wikilinks]]` | When a page or project folder needs a new name |
229
229
 
230
230
  ### Lifecycle hooks (14)
@@ -236,7 +236,7 @@ Eight commands cover the full capture → retrieval → consolidation cycle.
236
236
  | `hypo-lookup.mjs` | `UserPromptSubmit` | BM25 top-3 HIT inject / MISS → closest-slug signal |
237
237
  | `hypo-compact-guard.mjs` | `UserPromptSubmit` | Detect `/compact` → enforce session-close checklist |
238
238
  | `hypo-cwd-change.mjs` | `CwdChanged` | Inject the matching project's `hot.md` |
239
- | `hypo-file-watch.mjs` | `FileChanged` | Notify on wiki-file changes (honors `.hypoignore` matched paths are never re-emitted into LLM context) |
239
+ | `hypo-file-watch.mjs` | `FileChanged` | Notify on wiki-file changes (honors `.hypoignore`; matched paths are never re-emitted into LLM context) |
240
240
  | `hypo-auto-stage.mjs` | `PostToolUse(Write/Edit)` | Auto-stage wiki-file edits |
241
241
  | `hypo-auto-commit.mjs` | `Stop` | Auto commit + pull + push |
242
242
  | `hypo-hot-rebuild.mjs` | `Stop` | Rebuild `hot.md` |
@@ -248,9 +248,7 @@ Eight commands cover the full capture → retrieval → consolidation cycle.
248
248
 
249
249
  All hooks resolve the wiki root via `HYPO_DIR` env → `hypo-config.md` scan → `~/hypomnema` default, and share `hypo-shared.mjs` (declared via `hooks.json`'s `shared` field).
250
250
 
251
- Additionally, the `SessionStart` hook performs a non-blocking background check against npm and the Claude Code plugin marketplace and prints an "Update available!" banner the next time a newer Hypomnema version has been published. Opt out with `HYPO_NO_UPDATE_CHECK=1`, `NO_UPDATE_NOTIFIER=1`, or by running under `CI=true`.
252
-
253
- For fix-level v1.3 detail beyond the lanes above (session-close lint scoped to touched files so `/compact` is no longer blocked by unrelated debt, the `feedback` scope validator accepting cwd-derived project ids, and the stable lint warning IDs `W1`/`W2`/`W4` that `--strict` promotes to errors while `W3`, auto-repaired by `--fix`, stays a warning), see [`CHANGELOG.md`](CHANGELOG.md). **v1.3.1** is a fixes-only patch: update-notifier banners now actually reach the user via the top-level `systemMessage` channel instead of an invisible stderr write, `/hypo:upgrade` no longer double-registers core hooks for plugin or dual (manual + plugin) installs, and session-close no longer false-blocks a completed close when two projects share the latest date. **v1.3.2** adds a first-class log-only session-close path, so a non-project (tooling or wiki-only) session closes cleanly without being forced onto an unrelated project, plus a `rename` helper that rewrites the eligible inbound wikilinks when you rename a page (ambiguous or append-only references are reported, not rewritten). It also tightens the session-close gate (every project with activity today is gated, the per-session marker and `/compact` share one gate, and the derivable root `log.md` entry auto-derives) and the linter (`--json` no longer truncates on a pipe, and vault-convention wikilinks resolve instead of being false-flagged). **v1.3.3** hardens the session-close gate against accidental triggers: the model can no longer mark a session closed without a real user close signal, reading close-related text no longer false-blocks the turn, `--apply-session-close` commits its payload and writes the marker in one step on a close that carries a user close signal, and routine tracker bookkeeping no longer cross-blocks an unrelated project's `/compact`. It also extends `rename` to move a whole directory subtree (with a `/hypo:rename` command and a merge/renumber collision report when a destination already exists). **v1.3.4** is a fixes-only patch for wiki hygiene: `init` no longer drops a duplicate stock page next to a known hand-authored equivalent (when it sees `wiki-automation.md` or `wiki-help.md` it keeps that page and skips the stock `hypo-*` one, with a loud merge notice), and regenerable report output at the vault root (the upgrade `MIGRATION-v*.md` report, plus the reserved `GRAPH_REPORT.md` name) is excluded from the catalog scans while staying fully committable. **v1.4.0** adds an optional `failure_type` classification to feedback pages (one of eight values, surfaced as per-type counts by `hypomnema stats`) so recurring mistake types become visible — the `SCHEMA` moves to 2.1 as an additive, optional field that leaves any page not using it untouched (a page that already carried a hand-written free-text `failure_type` must be relabeled to one of the eight values). It also makes an auto-commit that hits a merge conflict abort cleanly instead of leaving a half-merged vault, stops `lint` from silently green-passing invalid YAML frontmatter (an unquoted `: ` value or a duplicate top-level key), and prevents a nested mapping key from shadowing the page `type`. Under the hood the release pipeline now also gates the Claude Code plugin channel (version consistency, a network-free plugin smoke check, and a README-version floor) and a shared `lib/wikilink.mjs` resolver consolidates the page-walking logic across `lint`, `rename`, `graph`, and `crystallize`.
251
+ The `SessionStart` hook also runs a non-blocking background check against npm and the Claude Code plugin marketplace, and prints an "Update available!" banner the next time a newer version has been published. Opt out with `HYPO_NO_UPDATE_CHECK=1`, `NO_UPDATE_NOTIFIER=1`, or by running under `CI=true`.
254
252
 
255
253
  ### Setup & maintenance
256
254
 
@@ -265,32 +263,32 @@ For fix-level v1.3 detail beyond the lanes above (session-close lint scoped to t
265
263
 
266
264
  ### Claude Agent Skills
267
265
 
268
- The synthesis-heavy commands (`ingest`, `query`, `crystallize`, `lint`, `verify`, `graph`) are also exposed as **Claude Agent Skills** in `skills/<name>/SKILL.md`, so they auto-trigger when the conversation matches their description no slash command required.
266
+ The synthesis-heavy commands (`ingest`, `query`, `crystallize`, `lint`, `verify`, `graph`) are also exposed as Claude Agent Skills in `skills/<name>/SKILL.md`, so they auto-trigger when the conversation matches their description, with no slash command required.
269
267
 
270
268
  ---
271
269
 
272
270
  ## Scenarios
273
271
 
274
- **A Learning a new technology.**
272
+ A. Learning a new technology.
275
273
  You're reading Kubernetes docs and blog posts. Drop each URL into `/hypo:ingest`. By the third article, Claude is updating your existing `kubernetes-networking.md` rather than creating another page. A week later, `/hypo:query "how does pod CIDR allocation work?"` returns a synthesized answer citing your own notes.
276
274
 
277
- **B Tracking engineering decisions.**
278
- Before merging a significant change, run `/hypo:ingest` on the design doc or PR description. Claude creates an ADR-style page with context, tradeoffs, and the decision. Future `[[wikilink]]` references pull the rationale directly into any prompt that asks about it.
275
+ B. Tracking engineering decisions.
276
+ Before merging a significant change, run `/hypo:ingest` on the design doc or PR description. Claude writes an ADR-style page with context, tradeoffs, and the decision. Future `[[wikilink]]` references pull the rationale directly into any prompt that asks about it.
279
277
 
280
- **C Research accumulation.**
281
- You're working through papers on a topic over several weeks. Each `/hypo:ingest` synthesizes the paper and cross-links it. At any point, `/hypo:query` returns a literature-review-style summary grounded in your own notes.
278
+ C. Research accumulation.
279
+ You work through papers on a topic over several weeks. Each `/hypo:ingest` synthesizes the paper and cross-links it. At any point, `/hypo:query` returns a literature-review-style summary grounded in your own notes.
282
280
 
283
- **D Tuning AI behavior.**
284
- Run `/hypo:feedback` whenever Claude does something wrong or exactly right. The correction is stored in `pages/feedback/` and injected at session start, so the same mistake doesn't happen twice across sessions, not just within one conversation.
281
+ D. Tuning AI behavior.
282
+ Run `/hypo:feedback` whenever Claude gets something wrong, or gets it exactly right. The correction is stored in `pages/feedback/` and injected at session start, so the same mistake doesn't happen twice. It carries across sessions, not just within one conversation.
285
283
 
286
- **E Resuming a paused project.**
287
- You put a project down for three weeks. At the next session start, `hypo-session-start.mjs` reads `projects/<name>/session-state.md` and injects "next tasks" and recent decisions directly into context. You're back up to speed before you type the first prompt.
284
+ E. Resuming a paused project.
285
+ You put a project down for three weeks. At the next session start, `hypo-session-start.mjs` reads `projects/<name>/session-state.md` and injects "next tasks" and recent decisions into context. You're back up to speed before you type the first prompt.
288
286
 
289
287
  ---
290
288
 
291
289
  ## What goes in your wiki
292
290
 
293
- **Store here:**
291
+ Store here:
294
292
 
295
293
  - Synthesized knowledge from external sources (docs, papers, talks)
296
294
  - Architecture decisions and their rationale
@@ -298,13 +296,13 @@ You put a project down for three weeks. At the next session start, `hypo-session
298
296
  - Project context that doesn't belong in git (stakeholder constraints, open questions, background)
299
297
  - Research findings and cross-source comparisons
300
298
 
301
- **Do not store here:**
299
+ Do not store here:
302
300
 
303
- - Raw source material that goes in `sources/` automatically, unedited
304
- - Credentials, tokens, or secrets use `.hypoignore` to exclude sensitive paths
305
- - Transient task lists for the current session use the conversation's task list
306
- - Code patterns derivable from the repo itself `git log` and `grep` are already authoritative
307
- - Information with a canonical owner elsewhere (Jira, Confluence, API docs) ingest a *synthesis*, not a mirror
301
+ - Raw source material: it goes in `sources/` automatically, unedited
302
+ - Credentials, tokens, or secrets: use `.hypoignore` to exclude sensitive paths
303
+ - Transient task lists for the current session: use the conversation's task list
304
+ - Code patterns derivable from the repo itself: `git log` and `grep` are already authoritative
305
+ - Information with a canonical owner elsewhere (Jira, Confluence, API docs): ingest a _synthesis_, not a mirror
308
306
 
309
307
  ---
310
308
 
@@ -345,11 +343,11 @@ The wiki path is resolved in this order (see `scripts/lib/hypo-root.mjs`):
345
343
 
346
344
  Place a `hypo-config.md` at the wiki root to make it portable across machines without setting environment variables.
347
345
 
348
- `.hypoignore` controls which paths the hooks ignore (default: `*.pdf`, `*.zip`, `*.pem`, `*.env`, …). Edit it directly there is no privacy mode flag; one file, one source of truth.
346
+ `.hypoignore` controls which paths the hooks ignore (default: `*.pdf`, `*.zip`, `*.pem`, `*.env`, …). Edit it directly; there is no privacy mode flag. One file, one source of truth.
349
347
 
350
- > **Provider transmission disclaimer.** Hypomnema hooks emit wiki content into Claude Code's `additionalContext`, which is transmitted to the Claude model provider as part of the prompt. `.hypoignore` is enforced at every content-injection hook (`hypo-file-watch`, `hypo-session-start`, `hypo-cwd-change`, `hypo-lookup`) and at `ingest`, but any file *not* matched by `.hypoignore` is fair game for transmission. (`hypo-auto-stage` and `hypo-auto-commit` are git-staging hooks, not injection points, and also honor `.hypoignore` for their staging decisions.) Keep secrets out of the wiki, and review `.hypoignore` patterns before storing anything sensitive under `HYPO_DIR`.
348
+ > Provider transmission disclaimer: Hypomnema hooks emit wiki content into Claude Code's `additionalContext`, which is transmitted to the Claude model provider as part of the prompt. `.hypoignore` is enforced at every content-injection hook (`hypo-file-watch`, `hypo-session-start`, `hypo-cwd-change`, `hypo-lookup`) and at `ingest`, but any file _not_ matched by `.hypoignore` is fair game for transmission. (`hypo-auto-stage` and `hypo-auto-commit` are git-staging hooks, not injection points, and also honor `.hypoignore` for their staging decisions.) Keep secrets out of the wiki, and review `.hypoignore` patterns before storing anything sensitive under `HYPO_DIR`.
351
349
 
352
- > **Scope of git sync.** Hypomnema git-syncs only the `~/hypomnema/` wiki itself. `init` / `upgrade` actively install and SHA-track a defined surface inside `~/.claude/` Hypomnema's own hooks (`~/.claude/hooks/`), slash commands (`~/.claude/commands/hypo/`), and `settings.json` registrations plus, via v1.2.0 **extensions companion sync**, any `agents/` · `commands/` · `hooks/` · `skills/` you ship inside `~/hypomnema/extensions/` (and with `--codex`, the `hooks` + `commands` subset into `~/.codex/`). Anything *outside* that defined surface in `~/.claude/` is intentionally **not** managed by Hypomnema for general cross-machine sync of Claude Code configuration (other agents/skills not staged via the wiki, machine-specific `settings.local.json`, etc.), the recommended pattern is still a separate dotfiles manager such as [chezmoi](https://www.chezmoi.io/).
350
+ > Scope of git sync: Hypomnema git-syncs only the `~/hypomnema/` wiki itself. `init` / `upgrade` do install and SHA-track a defined surface inside `~/.claude/` (Hypomnema's own hooks at `~/.claude/hooks/`, slash commands at `~/.claude/commands/hypo/`, and `settings.json` registrations), plus, via v1.2.0 extensions companion sync, any `agents/` · `commands/` · `hooks/` · `skills/` you ship inside `~/hypomnema/extensions/` (and with `--codex`, the `hooks` + `commands` subset into `~/.codex/`). Anything _outside_ that defined surface in `~/.claude/` is intentionally not managed by Hypomnema. For general cross-machine sync of Claude Code config (other agents/skills not staged via the wiki, machine-specific `settings.local.json`, etc.), use a separate dotfiles manager such as [chezmoi](https://www.chezmoi.io/).
353
351
 
354
352
  ### Where do `/hypo:*` commands live?
355
353
 
@@ -362,8 +360,8 @@ Place a `hypo-config.md` at the wiki root to make it portable across machines wi
362
360
 
363
361
  ## Requirements
364
362
 
365
- - **Node.js ≥ 18** (tested on 18 / 20 / 22)
366
- - **Claude Code CLI**
363
+ - Node.js ≥ 18 (tested on 18 / 20 / 22)
364
+ - Claude Code CLI
367
365
 
368
366
  No external services. No API keys. No vector databases.
369
367
 
@@ -371,17 +369,17 @@ No external services. No API keys. No vector databases.
371
369
 
372
370
  ## Status
373
371
 
374
- - **Tests:** see `npm test` exact totals shift as lanes ship, so the runner is the source of truth
375
- - **CI:** 7 independent jobs (test matrix, lint, init/upgrade snapshots, replay, hypo-absent, uninstall-smoke)
376
- - **Release:** `npm publish --provenance` on `v*` tag push
372
+ - Tests: see `npm test`. Exact totals shift as lanes ship, so the runner is the source of truth
373
+ - CI: 7 independent jobs (test matrix, lint, init/upgrade snapshots, replay, hypo-absent, uninstall-smoke)
374
+ - Release: `npm publish --provenance` on `v*` tag push
377
375
 
378
376
  ---
379
377
 
380
378
  ## Docs
381
379
 
382
- - [ARCHITECTURE.md](docs/ARCHITECTURE.md) internals, component map, data flows
383
- - [CONTRIBUTING.md](docs/CONTRIBUTING.md) development setup, conventions, PR process
384
- - [CHANGELOG.md](CHANGELOG.md) release history
380
+ - [ARCHITECTURE.md](docs/ARCHITECTURE.md): internals, component map, data flows
381
+ - [CONTRIBUTING.md](docs/CONTRIBUTING.md): development setup, conventions, PR process
382
+ - [CHANGELOG.md](CHANGELOG.md): release history
385
383
 
386
384
  ---
387
385
 
package/commands/audit.md CHANGED
@@ -14,9 +14,9 @@ Definition: [[pages/observability/_index]].
14
14
 
15
15
  ---
16
16
 
17
- ## Step 1 — Locate package root
17
+ ## Step 1 — Run script
18
18
 
19
- Locate the Hypomnema package root (the directory containing this file's parent `commands/`).
19
+ The script path below resolves via `${CLAUDE_PLUGIN_ROOT}`, which the plugin harness expands to this package's absolute path before you see it, so run it as written. If it appears unexpanded (a literal `${CLAUDE_PLUGIN_ROOT}`), read the package root from the `hypo@hypomnema` installPath in `~/.claude/plugins/installed_plugins.json` rather than guessing from the cache layout.
20
20
 
21
21
  If the user specified a Hypomnema directory, pass it as `--hypo-dir="<path>"`. Otherwise omit the flag.
22
22
 
@@ -26,11 +26,11 @@ If the user specified a Hypomnema directory, pass it as `--hypo-dir="<path>"`. O
26
26
 
27
27
  - **Per-session view (default)** — show recent sessions with metrics + classification:
28
28
  ```bash
29
- node <package-root>/scripts/session-audit.mjs [--hypo-dir="<path>"] [--limit=20]
29
+ node ${CLAUDE_PLUGIN_ROOT}/scripts/session-audit.mjs [--hypo-dir="<path>"] [--limit=20]
30
30
  ```
31
31
  - **Weekly report (when the user asks for "weekly", "score", or names a week)** — write the report to `journal/weekly/<YYYY-Www>.md` (spec §6.4 SoT):
32
32
  ```bash
33
- node <package-root>/scripts/weekly-report.mjs [--hypo-dir="<path>"] [--week=YYYY-Www] --write
33
+ node ${CLAUDE_PLUGIN_ROOT}/scripts/weekly-report.mjs [--hypo-dir="<path>"] [--week=YYYY-Www] --write
34
34
  ```
35
35
  - **JSON for tooling** — append `--json` to either script.
36
36
 
@@ -75,8 +75,10 @@ Content guidance for each slot:
75
75
 
76
76
  ## Step 3 — Apply the payload
77
77
 
78
+ The script paths in this command resolve via `${CLAUDE_PLUGIN_ROOT}`, which the plugin harness expands to this package's absolute path before you see it, so run them as written. If one appears unexpanded (a literal `${CLAUDE_PLUGIN_ROOT}`), read the package root from the `hypo@hypomnema` installPath in `~/.claude/plugins/installed_plugins.json` rather than guessing from the cache layout.
79
+
78
80
  ```bash
79
- node <package-root>/scripts/crystallize.mjs \
81
+ node ${CLAUDE_PLUGIN_ROOT}/scripts/crystallize.mjs \
80
82
  --apply-session-close \
81
83
  --payload=/tmp/hypo-session-close-<YYYY-MM-DD>.json \
82
84
  --session-id=<current-session-id> \
@@ -93,6 +95,14 @@ Stop-chain Layer 3 hook (`hypo-auto-minimal-crystallize`) the session is closed,
93
95
  so it stops re-prompting. Omit it only when running crystallize purely for
94
96
  synthesis (no session-close intent) — the marker is then simply not written.
95
97
 
98
+ > **Source rule for `--session-id`:** use only the main conversation's session id
99
+ > (the id shown in the `[WIKI_AUTOCLOSE]` block reason, or `$CLAUDE_SESSION_ID`).
100
+ > Do NOT extract it from a background task output path or Agent thread (e.g.,
101
+ > `/tmp/.../<uuid>/tasks/...`). A UUID from such a path is a background task id,
102
+ > not the main conversation id. Passing it causes `markerSkipReason:
103
+ > "transcript-unresolved"` or `"no-user-close-signal"` and leaves the Stop-chain
104
+ > open, even though `ok: true`.
105
+
96
106
  **Behavior (option D + lint gates):**
97
107
 
98
108
  | Invocation | Behavior |
@@ -132,8 +142,11 @@ Once `ok: true`, report:
132
142
  - ✓ open-questions applied (or skipped if unchanged)
133
143
  - ✓ log.md entry appended
134
144
  - ✓ post-apply lint clean
145
+ - **marker written?** (required check): if `markerWritten: true`, report "session-close marker written"; if `markerWritten: false`, report "session-close marker NOT written (reason: `<markerSkipReason>`)" and do NOT declare the session "closed" or "complete". A missing marker means the Stop-chain is still open. Instruct the user to re-run with the correct main-conversation `--session-id`.
146
+
147
+ If `markerWritten: true` (or `--session-id` was not passed): ask: "Session closed. Would you like to also run knowledge synthesis now, or stop here?"
135
148
 
136
- Then ask: "Session closed. Would you like to also run knowledge synthesis now, or stop here?"
149
+ If `markerWritten: false`: do NOT say "session closed." Say instead: "Files applied and verified (ok: true), but the session-close marker was not written (reason: `<markerSkipReason>`). The Stop-chain is still active. To fully close: re-run with the correct main-conversation `--session-id`."
137
150
 
138
151
  If the user says stop, end here. Otherwise continue to Step 5.
139
152
 
@@ -141,10 +154,10 @@ If the user says stop, end here. Otherwise continue to Step 5.
141
154
 
142
155
  ## Step 5 — Surface synthesis candidates
143
156
 
144
- Locate the Hypomnema package root (the directory containing this file's parent `commands/`).
157
+ The script path below resolves via `${CLAUDE_PLUGIN_ROOT}`, which the plugin harness expands to this package's absolute path before you see it, so run it as written. If it appears unexpanded (a literal `${CLAUDE_PLUGIN_ROOT}`), read the package root from the `hypo@hypomnema` installPath in `~/.claude/plugins/installed_plugins.json` rather than guessing from the cache layout.
145
158
 
146
159
  ```bash
147
- node <package-root>/scripts/crystallize.mjs [--hypo-dir="<path>"] [--min-group=2]
160
+ node ${CLAUDE_PLUGIN_ROOT}/scripts/crystallize.mjs [--hypo-dir="<path>"] [--min-group=2]
148
161
  ```
149
162
 
150
163
  Show the output to the user. If no candidates are found, tell them Hypomnema looks well-connected and no crystallization is needed.
@@ -217,7 +230,7 @@ Show what was created or modified, and offer to run `/hypo:lint` to verify all n
217
230
  `--check-session-close` (read-only strict gate, same check PreCompact runs) is still supported as a probe-only verification. Use it when you only want to verify that today's session-close is complete without applying anything:
218
231
 
219
232
  ```bash
220
- node <package-root>/scripts/crystallize.mjs --check-session-close [--hypo-dir="<path>"]
233
+ node ${CLAUDE_PLUGIN_ROOT}/scripts/crystallize.mjs --check-session-close [--hypo-dir="<path>"]
221
234
  ```
222
235
 
223
236
  It reports any file as `missing` or `stale`. For an actual close, prefer `--apply-session-close --payload=<path>` (Step 3) — it bundles freshness + lint into one gate and is the documented dogfood path. (`parseArgs` only accepts the `--payload=<path>` spelling; a space-separated `--payload <path>` is silently ignored and triggers "payload is required".)
@@ -16,9 +16,9 @@ You are running `/hypo:doctor`. Verify the health of the current Hypomnema wiki
16
16
 
17
17
  ---
18
18
 
19
- ## Step 1 — Locate package root and resolve Hypomnema directory
19
+ ## Step 1 — Resolve Hypomnema directory
20
20
 
21
- Locate the Hypomnema package root (the directory containing this file's parent `commands/`).
21
+ The script path below resolves via `${CLAUDE_PLUGIN_ROOT}`, which the plugin harness expands to this package's absolute path before you see it, so run it as written. If it appears unexpanded (a literal `${CLAUDE_PLUGIN_ROOT}`), read the package root from the `hypo@hypomnema` installPath in `~/.claude/plugins/installed_plugins.json` rather than guessing from the cache layout.
22
22
 
23
23
  If the user specified a Hypomnema directory, pass it as `--hypo-dir="<path>"`. Otherwise omit the flag and the script resolves the Hypomnema root automatically: `HYPO_DIR` env → `hypo-config.md` scan → `~/hypomnema` default.
24
24
 
@@ -27,7 +27,7 @@ If the user specified a Hypomnema directory, pass it as `--hypo-dir="<path>"`. O
27
27
  ## Step 2 — Run the doctor script
28
28
 
29
29
  ```bash
30
- node <package-root>/scripts/doctor.mjs [--hypo-dir="<path>"] [--json]
30
+ node ${CLAUDE_PLUGIN_ROOT}/scripts/doctor.mjs [--hypo-dir="<path>"] [--json]
31
31
  ```
32
32
 
33
33
  - `--hypo-dir=<path>` — override Hypomnema root (takes precedence over `HYPO_DIR` env and auto-scan)
@@ -36,10 +36,12 @@ If **claude-learned** is among the targets, the page must be `scope: global` + `
36
36
 
37
37
  ## Step 2 — List existing feedback (optional)
38
38
 
39
- To check for an existing topic, locate the Hypomnema package root and run:
39
+ The script path below resolves via `${CLAUDE_PLUGIN_ROOT}`, which the plugin harness expands to this package's absolute path before you see it, so run it as written. If it appears unexpanded (a literal `${CLAUDE_PLUGIN_ROOT}`), read the package root from the `hypo@hypomnema` installPath in `~/.claude/plugins/installed_plugins.json` rather than guessing from the cache layout.
40
+
41
+ To check for an existing topic, run:
40
42
 
41
43
  ```bash
42
- node <package-root>/scripts/feedback.mjs --list [--hypo-dir="<path>"]
44
+ node ${CLAUDE_PLUGIN_ROOT}/scripts/feedback.mjs --list [--hypo-dir="<path>"]
43
45
  ```
44
46
 
45
47
  If a matching topic exists, appending adds a dated entry and bumps `updated:` (classification frontmatter is preserved).
@@ -51,7 +53,7 @@ If a matching topic exists, appending adds a dated entry and bumps `updated:` (c
51
53
  Run with `--dry-run` first to preview the generated page, then without it to write. Pass every collected field:
52
54
 
53
55
  ```bash
54
- node <package-root>/scripts/feedback.mjs \
56
+ node ${CLAUDE_PLUGIN_ROOT}/scripts/feedback.mjs \
55
57
  --topic="<slug>" \
56
58
  --entry="<one-line rule>" \
57
59
  --scope="global|project:<project-id>" \