hypomnema 1.0.1 → 1.2.0
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.ko.md +12 -5
- package/README.md +12 -5
- package/commands/audit.md +46 -0
- package/commands/crystallize.md +113 -23
- package/commands/feedback.md +40 -26
- package/commands/ingest.md +31 -9
- package/commands/upgrade.md +2 -2
- package/docs/ARCHITECTURE.md +83 -9
- package/docs/CONTRIBUTING.md +2 -2
- package/hooks/hooks.json +39 -1
- package/hooks/hypo-auto-commit.mjs +23 -4
- package/hooks/hypo-auto-minimal-crystallize.mjs +145 -0
- package/hooks/hypo-auto-stage.mjs +9 -5
- package/hooks/hypo-compact-guard.mjs +33 -24
- package/hooks/hypo-cwd-change.mjs +107 -24
- package/hooks/hypo-file-watch.mjs +23 -10
- package/hooks/hypo-first-prompt.mjs +37 -23
- package/hooks/hypo-hot-rebuild.mjs +31 -8
- package/hooks/hypo-lookup.mjs +171 -65
- package/hooks/hypo-personal-check.mjs +207 -112
- package/hooks/hypo-pre-commit.mjs +46 -0
- package/hooks/hypo-session-end.mjs +58 -0
- package/hooks/hypo-session-record.mjs +60 -0
- package/hooks/hypo-session-start.mjs +312 -44
- package/hooks/hypo-shared.mjs +880 -28
- package/hooks/hypo-web-fetch-ingest.mjs +121 -0
- package/hooks/version-check-fetch.mjs +74 -0
- package/hooks/version-check.mjs +184 -0
- package/package.json +17 -3
- package/scripts/crystallize.mjs +623 -18
- package/scripts/doctor.mjs +739 -46
- package/scripts/feedback-sync.mjs +974 -0
- package/scripts/feedback.mjs +253 -44
- package/scripts/graph.mjs +35 -22
- package/scripts/ingest.mjs +89 -16
- package/scripts/init.mjs +442 -114
- package/scripts/lib/design-history-stale.mjs +83 -0
- package/scripts/lib/extensions.mjs +749 -0
- package/scripts/lib/frontmatter.mjs +5 -1
- package/scripts/lib/hypo-ignore.mjs +12 -10
- package/scripts/lib/pkg-json.mjs +23 -5
- package/scripts/lib/project-create.mjs +225 -0
- package/scripts/lib/schema-vocab.mjs +96 -0
- package/scripts/lint.mjs +238 -31
- package/scripts/query.mjs +26 -10
- package/scripts/resume.mjs +11 -5
- package/scripts/session-audit.mjs +277 -0
- package/scripts/smoke-pack.mjs +224 -0
- package/scripts/stats.mjs +24 -10
- package/scripts/uninstall.mjs +369 -48
- package/scripts/upgrade.mjs +766 -195
- package/scripts/verify.mjs +24 -14
- package/scripts/weekly-report.mjs +211 -0
- package/skills/crystallize/SKILL.md +24 -7
- package/skills/graph/SKILL.md +4 -0
- package/skills/ingest/SKILL.md +29 -5
- package/skills/lint/SKILL.md +4 -0
- package/skills/query/SKILL.md +4 -0
- package/skills/verify/SKILL.md +4 -0
- package/templates/.hypoignore +19 -2
- package/templates/Home.md +2 -0
- package/templates/SCHEMA.md +61 -6
- package/templates/extensions/agents/.gitkeep +0 -0
- package/templates/extensions/commands/.gitkeep +0 -0
- package/templates/extensions/hooks/.gitkeep +0 -0
- package/templates/extensions/skills/.gitkeep +0 -0
- package/templates/gitignore +5 -0
- package/templates/hot.md +2 -0
- package/templates/hypo-config.md +1 -1
- package/templates/hypo-guide.md +63 -1
- package/templates/hypo-help.md +1 -1
- package/templates/pages/observability/_index.md +77 -0
- package/templates/projects/_template/index.md +2 -2
- package/templates/projects/_template/prd.md +1 -1
package/README.ko.md
CHANGED
|
@@ -10,17 +10,19 @@
|
|
|
10
10
|
[](https://www.npmjs.com/package/hypomnema)
|
|
11
11
|
[](https://nodejs.org)
|
|
12
12
|
[](https://opensource.org/licenses/MIT)
|
|
13
|
-
[](https://github.com/sk-lim19f/Hypomnema/actions/workflows/ci.yml)
|
|
14
14
|
[](https://github.com/sk-lim19f/Hypomnema/stargazers)
|
|
15
15
|
|
|
16
16
|
**Claude Code를 위한 LLM 네이티브 개인 위키. 복리로 성장하는 지식.**
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
_Claude가 노트하게 만드세요 — 그리고 그게 실제로 일어나는지 측정하세요._
|
|
19
19
|
|
|
20
20
|
[빠른 시작](#빠른-시작) • [다른 시스템과의 비교](#다른-시스템과의-비교) • [설계 결정](#설계-결정) • [기능](#기능) • [아키텍처](docs/ARCHITECTURE.md) • [기여](docs/CONTRIBUTING.md)
|
|
21
21
|
|
|
22
22
|
> Andrej Karpathy의 "LLM 네이티브 위키" 스케치에서 영감을 받아, 10개월간의 개인 운영 경험으로 다듬어진 도구입니다. 캡처 → 합성 → 검색 → 세션 재개로 이어지는 전체 라이프사이클을 Claude Code 명령어와 라이프사이클 훅으로 제공합니다.
|
|
23
23
|
|
|
24
|
+
> **현재 상태 vs. v2 비전.** v1.0.1(현재)은 트리거 모델을 정직하게 밝힙니다: 대부분의 위키 동작 — 인제스트, 쿼리, 세션 클로즈 — 은 **명시적 `/hypo:*` 커맨드**로 시작되며, 일부 훅이 자동 staging·세션 상태 주입·룩업 신호를 처리합니다. v2 thesis는 *완전 자율* — Claude가 요청 없이 위키를 읽고·쓰고·합성하는 상태입니다. **v1.1.0**은 그 램프의 첫 단계로, 자율을 주장하는 대신 **observability 점수**를 출력해 세션당 위키가 실제로 얼마나 쓰였는지(ingest 수, query 수, session-close 비율, citation 비율)를 측정·공개합니다. v2 구현 이전에 자율 vs. 수동 비율을 사용자가 직접 확인할 수 있게 하기 위함입니다.
|
|
25
|
+
|
|
24
26
|
---
|
|
25
27
|
|
|
26
28
|
## 빠른 시작
|
|
@@ -105,6 +107,7 @@ Hypomnema ───► 합성 · 마크다운 · git · 훅 · 로컬
|
|
|
105
107
|
| **포맷** | 평문 마크다운 + frontmatter | 마크다운 | 독자 포맷 | 벡터 스토어 | 독자 포맷 | HTML |
|
|
106
108
|
| **백엔드** | 로컬 파일 + git | 로컬 파일 | SaaS | 서비스 / DB | SaaS | 서비스 |
|
|
107
109
|
| **행동 튜닝** | `/hypo:feedback` → 영구 규칙 | 없음 | 없음 | 없음 | 일부 | 없음 |
|
|
110
|
+
| **자율 동작(auto-behavior)** | 현재는 명시적 `/hypo:*` 트리거 기반; **v1.1에서 observability 점수 도입**, v2 목표 = 완전 자율 | 없음 | 없음 | 없음 | 블랙박스 | 없음 |
|
|
108
111
|
| **셋업 비용** | 명령 1개 | 설치 1번 | 가입 | 파이프라인 구축 | 가입 | 레포 연결 |
|
|
109
112
|
| **락인** | 0 (마크다운 + git) | 낮음 | 높음 | 중간 | 높음 | 중간 |
|
|
110
113
|
|
|
@@ -177,7 +180,7 @@ v1.0에서는 `personal / shared / public` 3-mode를 만들었습니다. 현실
|
|
|
177
180
|
|---|---|---|
|
|
178
181
|
| `/hypo:ingest` | 원본을 `sources/`에 보관하고 Claude가 `pages/`에 구조화된 페이지를 합성. 셸 헬퍼(`scripts/ingest.mjs`)는 read-only — 아직 ingest되지 않은 소스를 *목록만* 출력 | 보관할 가치가 있는 글을 읽었을 때 |
|
|
179
182
|
| `/hypo:query` | BM25 검색 + LLM 합성 + `[[wikilink]]` 인용 | 자기 노트에 근거한 답변이 필요할 때 |
|
|
180
|
-
| `/hypo:crystallize` |
|
|
183
|
+
| `/hypo:crystallize` | session-close 체크리스트(steps 1~6) + 요청 시 초안 합성(steps 7~11) | 비자명한 세션 종료 시 |
|
|
181
184
|
| `/hypo:resume` | 활성 프로젝트의 가장 최근 세션 상태 로드 | 일시 중단된 프로젝트로 돌아올 때 |
|
|
182
185
|
| `/hypo:feedback` | AI 행동 교정 기록, 영구 규칙으로 승격 가능 | Claude가 잘못 하거나 정확히 잘 했을 때 |
|
|
183
186
|
| `/hypo:verify` | `verify_by` frontmatter 페이지 감사 | 시간 제약 지식이 노후화됐을 가능성이 있을 때 |
|
|
@@ -193,7 +196,7 @@ v1.0에서는 `personal / shared / public` 3-mode를 만들었습니다. 현실
|
|
|
193
196
|
| `hypo-lookup.mjs` | `UserPromptSubmit` | BM25 top-3 HIT 주입 / MISS → 가까운 슬러그 신호 |
|
|
194
197
|
| `hypo-compact-guard.mjs` | `UserPromptSubmit` | `/compact` 감지 → session-close 체크리스트 강제 |
|
|
195
198
|
| `hypo-cwd-change.mjs` | `CwdChanged` | cwd에 매칭되는 프로젝트 `hot.md` 주입 |
|
|
196
|
-
| `hypo-file-watch.mjs` | `FileChanged` | 위키 파일 변경 알림 |
|
|
199
|
+
| `hypo-file-watch.mjs` | `FileChanged` | 위키 파일 변경 알림 (`.hypoignore` 준수 — 매칭 경로는 LLM 컨텍스트로 재주입되지 않음) |
|
|
197
200
|
| `hypo-auto-stage.mjs` | `PostToolUse(Write/Edit)` | 위키 파일 자동 stage |
|
|
198
201
|
| `hypo-auto-commit.mjs` | `Stop` | 자동 commit + pull + push |
|
|
199
202
|
| `hypo-hot-rebuild.mjs` | `Stop` | `hot.md` 재생성 |
|
|
@@ -295,6 +298,10 @@ Claude가 잘못하거나 정확히 맞았을 때마다 `/hypo:feedback`을 실
|
|
|
295
298
|
|
|
296
299
|
`.hypoignore`는 훅이 무시할 경로를 정의합니다 (기본: `*.pdf`, `*.zip`, `*.pem`, `*.env` 등). 직접 편집하면 됩니다 — privacy mode 플래그는 없습니다. 단일 파일, 단일 진실 소스.
|
|
297
300
|
|
|
301
|
+
> **Provider 전송 디스클레이머.** Hypomnema 훅은 위키 콘텐츠를 Claude Code의 `additionalContext`로 emit하며, 이는 프롬프트의 일부로 Claude 모델 provider에 전송됩니다. `.hypoignore`는 모든 콘텐츠 주입 훅(`hypo-file-watch`, `hypo-session-start`, `hypo-cwd-change`, `hypo-lookup`) 및 `ingest`에서 강제되지만, `.hypoignore`에 매칭되지 *않는* 파일은 전송 대상입니다. (`hypo-auto-stage`/`hypo-auto-commit`은 git staging 훅이며 주입 지점이 아니지만, staging 판단에도 `.hypoignore`를 준수합니다.) 위키에 비밀을 두지 말고, `HYPO_DIR` 아래 민감 콘텐츠를 저장하기 전 `.hypoignore` 패턴을 검토하세요.
|
|
302
|
+
|
|
303
|
+
> **git sync 범위.** Hypomnema는 `~/hypomnema/` 위키 자체만 git sync합니다. Claude Code 설정(`~/.claude/`)은 의도적으로 Hypomnema가 **관리하지 않습니다** — agent·skill·settings의 기기 간 동기화는 [chezmoi](https://www.chezmoi.io/) 같은 별도 dotfiles 매니저 사용을 권장합니다.
|
|
304
|
+
|
|
298
305
|
### `/hypo:*` 커맨드는 어디서 오는가?
|
|
299
306
|
|
|
300
307
|
| 설치 경로 | 슬래시 커맨드 위치 |
|
|
@@ -315,7 +322,7 @@ Claude가 잘못하거나 정확히 맞았을 때마다 `/hypo:feedback`을 실
|
|
|
315
322
|
|
|
316
323
|
## 상태
|
|
317
324
|
|
|
318
|
-
- **테스트:**
|
|
325
|
+
- **테스트:** `npm test` 참조 — lane이 ship될 때마다 카운트가 변하므로 러너가 단일 진실 공급원
|
|
319
326
|
- **CI:** 7개 독립 job (test matrix, lint, init/upgrade snapshots, replay, hypo-absent, uninstall-smoke)
|
|
320
327
|
- **릴리스:** `v*` 태그 push 시 `npm publish --provenance` 자동 실행
|
|
321
328
|
|
package/README.md
CHANGED
|
@@ -10,17 +10,19 @@ English | [한국어](README.ko.md)
|
|
|
10
10
|
[](https://www.npmjs.com/package/hypomnema)
|
|
11
11
|
[](https://nodejs.org)
|
|
12
12
|
[](https://opensource.org/licenses/MIT)
|
|
13
|
-
[](https://github.com/sk-lim19f/Hypomnema/actions/workflows/ci.yml)
|
|
14
14
|
[](https://github.com/sk-lim19f/Hypomnema/stargazers)
|
|
15
15
|
|
|
16
16
|
**LLM-native personal wiki for Claude Code. Knowledge that compounds.**
|
|
17
17
|
|
|
18
|
-
|
|
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
22
|
> Inspired by Andrej Karpathy's "LLM-native wiki" sketch and shaped by ten months of personal use, Hypomnema ships the full lifecycle — capture, synthesis, retrieval, session-resume — as Claude Code commands and lifecycle hooks.
|
|
23
23
|
|
|
24
|
+
> **Current state vs. v2 vision.** v1.0.1 (today) is honest about its trigger model: most wiki behavior — ingest, query, session-close — fires on **explicit `/hypo:*` commands**, with a handful of hooks providing auto-staging, session-state injection, and lookup signals. The v2 thesis is *fully autonomous* — Claude reading, writing, and synthesizing the wiki without being asked. **v1.1.0** is the first step on that ramp: instead of claiming auto-behavior, it ships an **observability score** that measures how often the wiki is actually used per session (ingest count, query count, session-close rate, citation rate) so you can see the auto-vs-manual ratio with your own eyes before the v2 work lands.
|
|
25
|
+
|
|
24
26
|
---
|
|
25
27
|
|
|
26
28
|
## Quick Start
|
|
@@ -105,6 +107,7 @@ Hypomnema ───► synthesis · markdown · git · hooks · local
|
|
|
105
107
|
| **Format** | Plain markdown + frontmatter | Markdown | Proprietary | Vector store | Proprietary | HTML |
|
|
106
108
|
| **Backend** | Local file + git | Local file | SaaS | Service / DB | SaaS | Service |
|
|
107
109
|
| **Behavior tuning** | `/hypo:feedback` → permanent rules | None | None | None | Sometimes | None |
|
|
110
|
+
| **Auto-behavior** | Explicit `/hypo:*` triggers today; **v1.1 ships an observability score**, v2 target = fully autonomous | None | None | None | Black box | None |
|
|
108
111
|
| **Setup cost** | One command | One install | Sign-up | Pipeline build | Sign-up | Repo connect |
|
|
109
112
|
| **Lock-in** | Zero (markdown + git) | Low | High | Medium | High | Medium |
|
|
110
113
|
|
|
@@ -177,7 +180,7 @@ Eight commands cover the full capture → retrieval → consolidation cycle.
|
|
|
177
180
|
|---|---|---|
|
|
178
181
|
| `/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 |
|
|
179
182
|
| `/hypo:query` | BM25 retrieval + LLM synthesis with `[[wikilink]]` citations | When you need an answer grounded in your own notes |
|
|
180
|
-
| `/hypo:crystallize` |
|
|
183
|
+
| `/hypo:crystallize` | Runs the session-close checklist (steps 1~6) and, on request, synthesizes drafts (steps 7~11) | End of a non-trivial session |
|
|
181
184
|
| `/hypo:resume` | Loads the most recent session state for an active project | Coming back to a paused project |
|
|
182
185
|
| `/hypo:feedback` | Records an AI behavior correction; eligible for promotion to permanent rules | Right when Claude does something wrong (or exactly right) |
|
|
183
186
|
| `/hypo:verify` | Audits pages with `verify_by` frontmatter | When time-bound knowledge might have aged out |
|
|
@@ -193,7 +196,7 @@ Eight commands cover the full capture → retrieval → consolidation cycle.
|
|
|
193
196
|
| `hypo-lookup.mjs` | `UserPromptSubmit` | BM25 top-3 HIT inject / MISS → closest-slug signal |
|
|
194
197
|
| `hypo-compact-guard.mjs` | `UserPromptSubmit` | Detect `/compact` → enforce session-close checklist |
|
|
195
198
|
| `hypo-cwd-change.mjs` | `CwdChanged` | Inject the matching project's `hot.md` |
|
|
196
|
-
| `hypo-file-watch.mjs` | `FileChanged` | Notify on wiki-file changes |
|
|
199
|
+
| `hypo-file-watch.mjs` | `FileChanged` | Notify on wiki-file changes (honors `.hypoignore` — matched paths are never re-emitted into LLM context) |
|
|
197
200
|
| `hypo-auto-stage.mjs` | `PostToolUse(Write/Edit)` | Auto-stage wiki-file edits |
|
|
198
201
|
| `hypo-auto-commit.mjs` | `Stop` | Auto commit + pull + push |
|
|
199
202
|
| `hypo-hot-rebuild.mjs` | `Stop` | Rebuild `hot.md` |
|
|
@@ -295,6 +298,10 @@ Place a `hypo-config.md` at the wiki root to make it portable across machines wi
|
|
|
295
298
|
|
|
296
299
|
`.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.
|
|
297
300
|
|
|
301
|
+
> **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`.
|
|
302
|
+
|
|
303
|
+
> **Scope of git sync.** Hypomnema git-syncs only the `~/hypomnema/` wiki itself. Your Claude Code configuration (`~/.claude/`) is intentionally **not** managed by Hypomnema — for cross-machine sync of agents, skills, and settings, the recommended pattern is a separate dotfiles manager such as [chezmoi](https://www.chezmoi.io/).
|
|
304
|
+
|
|
298
305
|
### Where do `/hypo:*` commands live?
|
|
299
306
|
|
|
300
307
|
| Install path | Slash commands served from |
|
|
@@ -315,7 +322,7 @@ No external services. No API keys. No vector databases.
|
|
|
315
322
|
|
|
316
323
|
## Status
|
|
317
324
|
|
|
318
|
-
- **Tests:**
|
|
325
|
+
- **Tests:** see `npm test` — exact totals shift as lanes ship, so the runner is the source of truth
|
|
319
326
|
- **CI:** 7 independent jobs (test matrix, lint, init/upgrade snapshots, replay, hypo-absent, uninstall-smoke)
|
|
320
327
|
- **Release:** `npm publish --provenance` on `v*` tag push
|
|
321
328
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Run the observability audit on recent sessions and (optionally) write the weekly report
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
You are running `/hypo:audit`. Inspect recent Claude Code sessions to see how much of the wiki's value motion is actually happening (search, ingest, citation, feedback), then either show the result inline or write a weekly observability page.
|
|
6
|
+
|
|
7
|
+
## What this shows
|
|
8
|
+
|
|
9
|
+
- Per-session metrics — search count, ingest count, URL mentions, feedback count
|
|
10
|
+
- Classification — `normal` / `search-0` / `search-many` / `ingest-missed` / `staleness-skip`
|
|
11
|
+
- Optional weekly aggregation with an autonomy score (heuristic v0)
|
|
12
|
+
|
|
13
|
+
Definition: [[pages/observability/_index]].
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Step 1 — Locate package root
|
|
18
|
+
|
|
19
|
+
Locate the Hypomnema package root (the directory containing this file's parent `commands/`).
|
|
20
|
+
|
|
21
|
+
If the user specified a Hypomnema directory, pass it as `--hypo-dir="<path>"`. Otherwise omit the flag.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Step 2 — Decide the mode
|
|
26
|
+
|
|
27
|
+
- **Per-session view (default)** — show recent sessions with metrics + classification:
|
|
28
|
+
```bash
|
|
29
|
+
node <package-root>/scripts/session-audit.mjs [--hypo-dir="<path>"] [--limit=20]
|
|
30
|
+
```
|
|
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
|
+
```bash
|
|
33
|
+
node <package-root>/scripts/weekly-report.mjs [--hypo-dir="<path>"] [--week=YYYY-Www] --write
|
|
34
|
+
```
|
|
35
|
+
- **JSON for tooling** — append `--json` to either script.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Step 3 — Report results
|
|
40
|
+
|
|
41
|
+
Show the output verbatim. Then add a brief interpretation:
|
|
42
|
+
|
|
43
|
+
- If `staleness-skip` dominates: "Most sessions audited are older than 30 days — score reflects backlog, not current behavior."
|
|
44
|
+
- If `search-0` count is high: "Sessions ran without consulting the wiki — consider whether `/hypo:query` was the right reflex."
|
|
45
|
+
- If `ingest-missed` is non-zero: "Sessions discussed URLs but no `/hypo:ingest` ran — those captures got lost."
|
|
46
|
+
- Otherwise: "Audit window looks healthy; weekly report committed to the wiki for trend tracking."
|
package/commands/crystallize.md
CHANGED
|
@@ -4,47 +4,125 @@ description: Crystallize draft notes into stable knowledge — also the session-
|
|
|
4
4
|
|
|
5
5
|
You are running `/hypo:crystallize`. This command serves two purposes:
|
|
6
6
|
|
|
7
|
-
1. **Session close** — if invoked at the end of a session, run the session-close
|
|
7
|
+
1. **Session close** — if invoked at the end of a session, run the session-close mechanical-apply path
|
|
8
8
|
2. **Knowledge synthesis** — consolidate draft or scattered wiki pages into stable, well-linked pages
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
## Step 1 — Detect context
|
|
13
13
|
|
|
14
|
-
If the user invoked `/hypo:crystallize` to close a session (phrases like "세션 종료", "오늘 작업 마무리", "session close", or "wrap up"), run Steps 2–
|
|
14
|
+
If the user invoked `/hypo:crystallize` to close a session (phrases like "세션 종료", "오늘 작업 마무리", "session close", or "wrap up"), run Steps 2–4 (session-close mechanical apply + recovery) **before** the synthesis scan. Otherwise skip to Step 5.
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
-
## Step 2 —
|
|
18
|
+
## Step 2 — Compose the session-close payload
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
The session-close path is **payload-driven** (fix #38). Instead of writing the 5 mandatory files one-by-one, you compose a single JSON payload that describes the full session-close state, then hand it to `crystallize.mjs --apply-session-close`, which performs idempotent atomic writes and gates the result with lint.
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
Payload shape (5 required + 1 conditional, per Spec §5.2.7 / §8.3 + ADR 0029):
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"project": "<project-name>",
|
|
27
|
+
"date": "YYYY-MM-DD",
|
|
28
|
+
"sessionState": { "content": "<full body of projects/<name>/session-state.md>" },
|
|
29
|
+
"projectHot": { "content": "<full body of projects/<name>/hot.md>" },
|
|
30
|
+
"rootHot": { "content": "<full body of <hypo-root>/hot.md>" },
|
|
31
|
+
"sessionLog": { "entry": "<entry to append to projects/<name>/session-log/YYYY-MM.md>" },
|
|
32
|
+
"log": { "entry": "<entry to append to <hypo-root>/log.md>" },
|
|
33
|
+
"openQuestions": { "content": "<full body of pages/open-questions.md>" }
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
> **Important:** the JSON above is a literal template — do not add `//` or `#` comments when materializing it. `readPayload()` runs `JSON.parse`, which rejects comments and would fail the apply before any write.
|
|
38
|
+
|
|
39
|
+
Field rules:
|
|
40
|
+
|
|
41
|
+
- `project` — optional. Falls back to the active project from root `hot.md` pointer table.
|
|
42
|
+
- `date` — optional. Defaults to today (local). Must be `YYYY-MM-DD` if supplied.
|
|
43
|
+
- `openQuestions` — optional. Include only when `pages/open-questions.md` exists and changed this session.
|
|
44
|
+
- All other top-level fields are required.
|
|
45
|
+
|
|
46
|
+
Notes:
|
|
47
|
+
|
|
48
|
+
- `sessionState` / `projectHot` / `rootHot` / `openQuestions` are **overwrite** (full-file content). `sessionLog` / `log` are **append** (entry-level idempotency — exact-entry dedup, safe to re-run).
|
|
49
|
+
- Frontmatter `updated:` is NOT auto-fixed. If your payload's `updated:` is stale, the post-apply verification gate will fail with `stage='post-apply-verification'` and you must fix the payload and retry.
|
|
50
|
+
- Write the payload to a temp path, e.g. `/tmp/hypo-session-close-<YYYY-MM-DD>.json`.
|
|
51
|
+
|
|
52
|
+
Content guidance for each slot:
|
|
53
|
+
|
|
54
|
+
1. **sessionState** — next tasks list for the upcoming session (what to tackle first next time).
|
|
55
|
+
2. **projectHot** — session snapshot under 500 words: what changed and decisions made. Do **not** put next-step tasks here; those belong in `sessionState`.
|
|
56
|
+
3. **rootHot** — active-projects pointer table with this project's `Last Session` date set to today.
|
|
57
|
+
4. **sessionLog** — one session entry to append to `projects/<name>/session-log/YYYY-MM.md`.
|
|
58
|
+
5. **log** — one `session` entry to append to `<hypo-root>/log.md`.
|
|
59
|
+
6. **openQuestions** (conditional) — only if `pages/open-questions.md` exists and questions were raised or resolved this session.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Step 3 — Apply the payload
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
node <package-root>/scripts/crystallize.mjs \
|
|
67
|
+
--apply-session-close \
|
|
68
|
+
--payload=/tmp/hypo-session-close-<YYYY-MM-DD>.json \
|
|
69
|
+
--session-id=<current-session-id> \
|
|
70
|
+
--hypo-dir="<path>" \
|
|
71
|
+
--json
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**`--session-id` (fix #27 PR-C):** pass the current session's id whenever you
|
|
75
|
+
know it — most importantly when this close was triggered by a `[WIKI_AUTOCLOSE]`
|
|
76
|
+
Stop-hook block (the block reason prints the exact `--session-id` to use). On a
|
|
77
|
+
verified close (`ok: true` + clean git tree), it writes the per-session marker
|
|
78
|
+
`HYPO_DIR/.cache/session-closed-<id>.marker`. That marker is what tells the
|
|
79
|
+
Stop-chain Layer 3 hook (`hypo-auto-minimal-crystallize`) the session is closed,
|
|
80
|
+
so it stops re-prompting. Omit it only when running crystallize purely for
|
|
81
|
+
synthesis (no session-close intent) — the marker is then simply not written.
|
|
82
|
+
|
|
83
|
+
**Behavior (fix #39 option D + fix #40 lint gates):**
|
|
84
|
+
|
|
85
|
+
| Invocation | Behavior |
|
|
86
|
+
|---|---|
|
|
87
|
+
| `--apply-session-close` (no `--payload`) | **Probe mode** — exits 0 with "오늘 이미 close 완료로 보임" if all 5 files are fresh today; exits 1 with "payload is required" otherwise. Cheap "already complete?" check. |
|
|
88
|
+
| `--apply-session-close --payload=<path>` | **Always-apply** — payload presence = explicit close intent. Per-field idempotent writes (no-op when bytes match), then strict verification + lint gate. Safe to re-run. |
|
|
89
|
+
| `--apply-session-close --payload=<path> --session-id=<id>` | Same as above, **plus** writes the per-session closed marker on success (clean git required). The Stop-chain Layer 3 path. |
|
|
90
|
+
| `--apply-session-close --force` | Skips the probe early-exit. `--payload` still required for any actual apply work. |
|
|
91
|
+
|
|
92
|
+
**Two lint gates run automatically (fix #40):**
|
|
93
|
+
|
|
94
|
+
1. **Preflight** — `lint.mjs --json` runs **before** any payload bytes are written. Errors in files this payload will overwrite (sessionState / projectHot / rootHot / openQuestions) are filtered (they're about to be replaced anyway). Errors in any other file → exit 1 with `stage='preflight-lint'`, no apply occurs.
|
|
95
|
+
2. **Post-apply** — lint re-runs after the writes. Catches payloads that introduce a broken wikilink or malformed body. Surfaces as `stage='post-apply-lint'` (or `'post-apply-verification+lint'` if the freshness gate also fails).
|
|
28
96
|
|
|
29
97
|
---
|
|
30
98
|
|
|
31
|
-
## Step
|
|
99
|
+
## Step 4 — Stage-based recovery
|
|
100
|
+
|
|
101
|
+
The result JSON includes a `stage` field when `ok: false`. Branch on it:
|
|
32
102
|
|
|
33
|
-
|
|
103
|
+
| `stage` | What broke | How to recover |
|
|
104
|
+
|---|---|---|
|
|
105
|
+
| `preflight-lint` | A non-payload file in the wiki has a blocking lint error. | Fix the lint error in that file (separate from session-close), then re-run. No payload bytes were written. |
|
|
106
|
+
| `post-apply-verification` | A mandatory file's `updated:` frontmatter is stale (≠ today) after apply. | Edit the payload's stale `content` (or supply correct `date`), then re-run. Writes are idempotent — re-applying a corrected payload is safe. |
|
|
107
|
+
| `post-apply-lint` | The payload itself introduced a lint blocker (broken wikilink, bad frontmatter). | Fix the offending content in the payload, then re-run. |
|
|
108
|
+
| `post-apply-verification+lint` | Both above. | Fix both; re-run. |
|
|
34
109
|
|
|
35
|
-
|
|
36
|
-
|
|
110
|
+
Once `ok: true`, report:
|
|
111
|
+
|
|
112
|
+
- ✓ session-state.md applied
|
|
113
|
+
- ✓ hot.md (project + root) applied
|
|
37
114
|
- ✓ session-log entry appended
|
|
38
|
-
- ✓ open-questions
|
|
39
|
-
- ✓ log.md
|
|
115
|
+
- ✓ open-questions applied (or skipped if unchanged)
|
|
116
|
+
- ✓ log.md entry appended
|
|
117
|
+
- ✓ post-apply lint clean
|
|
40
118
|
|
|
41
119
|
Then ask: "Session closed. Would you like to also run knowledge synthesis now, or stop here?"
|
|
42
120
|
|
|
43
|
-
If the user says stop, end here. Otherwise continue to Step
|
|
121
|
+
If the user says stop, end here. Otherwise continue to Step 5.
|
|
44
122
|
|
|
45
123
|
---
|
|
46
124
|
|
|
47
|
-
## Step
|
|
125
|
+
## Step 5 — Surface synthesis candidates
|
|
48
126
|
|
|
49
127
|
Locate the Hypomnema package root (the directory containing this file's parent `commands/`).
|
|
50
128
|
|
|
@@ -56,7 +134,7 @@ Show the output to the user. If no candidates are found, tell them Hypomnema loo
|
|
|
56
134
|
|
|
57
135
|
---
|
|
58
136
|
|
|
59
|
-
## Step
|
|
137
|
+
## Step 6 — Choose what to crystallize
|
|
60
138
|
|
|
61
139
|
If candidates exist, ask:
|
|
62
140
|
|
|
@@ -67,7 +145,7 @@ If candidates exist, ask:
|
|
|
67
145
|
|
|
68
146
|
---
|
|
69
147
|
|
|
70
|
-
## Step
|
|
148
|
+
## Step 6a — Tag cluster synthesis
|
|
71
149
|
|
|
72
150
|
For a tag cluster:
|
|
73
151
|
|
|
@@ -89,7 +167,7 @@ For a tag cluster:
|
|
|
89
167
|
|
|
90
168
|
---
|
|
91
169
|
|
|
92
|
-
## Step
|
|
170
|
+
## Step 6b — Draft upgrade
|
|
93
171
|
|
|
94
172
|
For a draft page:
|
|
95
173
|
|
|
@@ -100,7 +178,7 @@ For a draft page:
|
|
|
100
178
|
|
|
101
179
|
---
|
|
102
180
|
|
|
103
|
-
## Step
|
|
181
|
+
## Step 6c — Cross-link unlinked pages
|
|
104
182
|
|
|
105
183
|
For unlinked pages:
|
|
106
184
|
|
|
@@ -111,6 +189,18 @@ For unlinked pages:
|
|
|
111
189
|
|
|
112
190
|
---
|
|
113
191
|
|
|
114
|
-
## Step
|
|
192
|
+
## Step 7 — Report
|
|
115
193
|
|
|
116
194
|
Show what was created or modified, and offer to run `/hypo:lint` to verify all new links resolve.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Appendix — Legacy `--check-session-close`
|
|
199
|
+
|
|
200
|
+
`--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:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
node <package-root>/scripts/crystallize.mjs --check-session-close [--hypo-dir="<path>"]
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
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".)
|
package/commands/feedback.md
CHANGED
|
@@ -2,23 +2,34 @@
|
|
|
2
2
|
description: Record an AI behavior correction or preference into the wiki
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
You are running `/hypo:feedback`. Capture a behavior correction or preference into `pages/feedback/` for
|
|
5
|
+
You are running `/hypo:feedback`. Capture a behavior correction or preference into `pages/feedback/` — the **single source of truth** for learned behaviors (ADR 0031 / fix #37).
|
|
6
6
|
|
|
7
7
|
## What this does
|
|
8
8
|
|
|
9
|
-
- Creates or updates `pages/feedback/<topic>.md` with a dated entry
|
|
9
|
+
- Creates or updates `pages/feedback/<topic>.md` with a dated entry and full classification frontmatter
|
|
10
10
|
- Appends a reference to `log.md`
|
|
11
|
-
-
|
|
11
|
+
- **Automatically refreshes the projection** into `MEMORY.md` and the user's CLAUDE.md `<learned_behaviors>` via `feedback-sync --write`
|
|
12
|
+
|
|
13
|
+
> ⚠️ Do **not** hand-edit MEMORY.md or CLAUDE.md `<learned_behaviors>` for feedback. Those are one-way projections derived from the wiki page. Edit the wiki page; the projection follows.
|
|
12
14
|
|
|
13
15
|
---
|
|
14
16
|
|
|
15
17
|
## Step 1 — Gather feedback details
|
|
16
18
|
|
|
17
|
-
If the user did not provide them, ask:
|
|
19
|
+
If the user did not provide them, ask. The classification fields are required so the page can project correctly:
|
|
20
|
+
|
|
21
|
+
1. **Topic** (slug): "What topic does this feedback apply to? (e.g. `response-length`, `commit-style`)"
|
|
22
|
+
2. **Rule** (entry): "State the rule or correction in one or two sentences."
|
|
23
|
+
3. **Reason**: "What incident or reasoning prompted this?"
|
|
24
|
+
4. **Scope**: "Does this apply globally (all projects) or to this project only?" → `global` | `project:<project-id>` (project-id must exact-match the resolved id; see Step 3 note)
|
|
25
|
+
5. **Tier**: "Is this a hard rule (L1) or a softer preference (L2)?" → `L1` | `L2`
|
|
26
|
+
6. **Targets**: "Where should this project?" → `project-memory` (MEMORY.md) and/or `claude-learned` (global CLAUDE.md). Default `project-memory`.
|
|
27
|
+
7. **Priority** (1–5, higher sorts first; default 3).
|
|
28
|
+
8. **Sensitivity**: `public` (default) or `sanitized` (redacted secrets/paths). `private` is not allowed — the wiki is git-pushed.
|
|
18
29
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
30
|
+
If **claude-learned** is among the targets, the page must be `scope: global` + `tier: L1`, and you must also collect:
|
|
31
|
+
- **Global summary**: a one-line summary for the CLAUDE.md learned-behaviors entry.
|
|
32
|
+
- Confirm **promote to global** (the page is only projected to CLAUDE.md when promoted).
|
|
22
33
|
|
|
23
34
|
---
|
|
24
35
|
|
|
@@ -30,38 +41,41 @@ To check for an existing topic, locate the Hypomnema package root and run:
|
|
|
30
41
|
node <package-root>/scripts/feedback.mjs --list [--hypo-dir="<path>"]
|
|
31
42
|
```
|
|
32
43
|
|
|
33
|
-
If a matching topic exists,
|
|
44
|
+
If a matching topic exists, appending adds a dated entry and bumps `updated:` (classification frontmatter is preserved).
|
|
34
45
|
|
|
35
46
|
---
|
|
36
47
|
|
|
37
|
-
## Step 3 — Write the feedback
|
|
38
|
-
|
|
39
|
-
Compose the entry text. Format:
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
**Rule**: <one-line rule>
|
|
43
|
-
|
|
44
|
-
**Why**: <reason or incident>
|
|
45
|
-
|
|
46
|
-
**How to apply**: <when this kicks in>
|
|
47
|
-
```
|
|
48
|
+
## Step 3 — Write the feedback page
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
Run with `--dry-run` first to preview the generated page, then without it to write. Pass every collected field:
|
|
50
51
|
|
|
51
52
|
```bash
|
|
52
53
|
node <package-root>/scripts/feedback.mjs \
|
|
53
54
|
--topic="<slug>" \
|
|
54
|
-
--entry="<
|
|
55
|
+
--entry="<one-line rule>" \
|
|
56
|
+
--scope="global|project:<project-id>" \
|
|
57
|
+
--tier="L1|L2" \
|
|
58
|
+
--targets="project-memory[,claude-learned]" \
|
|
59
|
+
--priority=<1-5> \
|
|
60
|
+
--sensitivity="public|sanitized" \
|
|
61
|
+
--memory-summary="<one-line MEMORY.md summary>" \
|
|
62
|
+
--reason="<why this rule exists>" \
|
|
63
|
+
[--global-summary="<one-line CLAUDE.md summary>" --promote-to-global] \
|
|
64
|
+
[--source="session:<date>"] \
|
|
55
65
|
[--hypo-dir="<path>"] \
|
|
56
66
|
[--dry-run]
|
|
57
67
|
```
|
|
58
68
|
|
|
59
|
-
|
|
69
|
+
When `--targets` includes `claude-learned`, `--global-summary` and `--promote-to-global` are required (and `--scope=global --tier=L1`).
|
|
70
|
+
|
|
71
|
+
> **`scope: project:<project-id>` 주의 (v1.2.0).** `<project-id>`는 `feedback-sync`가 resolve한 project-id와 정확히 일치해야 한다 (default: cwd의 `/`,`.` → `-` 치환; `--project-id=<id>` 로 override). 일치하지 않으면 그 페이지는 해당 project의 MEMORY로 projection되지 **않는다** (silent skip — lint error 아님). 다만 현재 lint scope regex(`^project:[a-z0-9][a-z0-9-]*$`)는 cwd-derived id 형식(`-Users-...`)을 거부하므로, **`project:*` scope를 사용하려면 slug-safe id로 `--project-id=<slug>`를 override해서 wiki 디렉터리도 그 id에 맞추는 운영 패턴이 필요하다**. resolved-id ↔ slug 정합화는 v1.3.0 트랙에서 다룸.
|
|
72
|
+
|
|
73
|
+
On a real (non-dry-run) write, the script automatically runs `feedback-sync --write` to refresh MEMORY.md / CLAUDE.md. If that post-step reports drift it prints a one-line warning — the page is still saved; reconcile with `hypomnema feedback-sync --check`.
|
|
60
74
|
|
|
61
75
|
---
|
|
62
76
|
|
|
63
|
-
## Step 4 — Confirm
|
|
77
|
+
## Step 4 — Confirm
|
|
64
78
|
|
|
65
|
-
After writing:
|
|
66
|
-
-
|
|
67
|
-
- If
|
|
79
|
+
After writing, tell the user:
|
|
80
|
+
- "Saved to `pages/feedback/<topic>.md` and refreshed the MEMORY/CLAUDE projection."
|
|
81
|
+
- If the projection post-step warned (over-cap, conflict, unresolved project-id), surface that and suggest `hypomnema feedback-sync --check`.
|
package/commands/ingest.md
CHANGED
|
@@ -21,13 +21,33 @@ Ask the user:
|
|
|
21
21
|
2. **Slug**: "What slug should this source have? (e.g. `openai-swarm-paper`, `team-retro-2026-04`)"
|
|
22
22
|
- Default: derive from title or filename
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
Do **not** fetch the URL or read the file yet — the privacy guard in Step 2 must run first.
|
|
25
25
|
|
|
26
26
|
---
|
|
27
27
|
|
|
28
|
-
## Step 2 —
|
|
28
|
+
## Step 2 — Privacy guard (`.hypoignore`)
|
|
29
29
|
|
|
30
|
-
Locate the Hypomnema package root
|
|
30
|
+
Refuse to ingest secrets (`.env`, SSH keys, credentials) before they ever reach `sources/`. Locate the Hypomnema package root and run the guard for **both** the input path and the destination path:
|
|
31
|
+
|
|
32
|
+
1. **If the source is a file path**, check it (use an absolute path):
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
node <package-root>/scripts/ingest.mjs [--hypo-dir="<path>"] --check="<absolute-input-path>"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
2. **Always** check the destination `sources/<slug>.<ext>`:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
node <package-root>/scripts/ingest.mjs [--hypo-dir="<path>"] --check="sources/<slug>.<ext>"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
If either command exits non-zero, **stop**: surface the `Refused: ...` message to the user and do not fetch, read, or save the source. The slug check matters because a user could rename a `.env` to an innocuous slug — the destination must still be blocked.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Step 3 — Check for orphaned sources
|
|
49
|
+
|
|
50
|
+
Run the ingest helper to surface existing orphaned sources:
|
|
31
51
|
|
|
32
52
|
```bash
|
|
33
53
|
node <package-root>/scripts/ingest.mjs [--hypo-dir="<path>"]
|
|
@@ -35,9 +55,11 @@ node <package-root>/scripts/ingest.mjs [--hypo-dir="<path>"]
|
|
|
35
55
|
|
|
36
56
|
If there are orphaned sources already in `sources/`, ask: "There are N unprocessed sources — do you want to ingest one of those instead?"
|
|
37
57
|
|
|
58
|
+
Once the guard has passed: if a URL is provided, fetch the content; if a file path is provided, read it.
|
|
59
|
+
|
|
38
60
|
---
|
|
39
61
|
|
|
40
|
-
## Step
|
|
62
|
+
## Step 4 — Save raw source
|
|
41
63
|
|
|
42
64
|
Save the raw content to `sources/<slug>.<ext>` (use `.md` for text, `.txt` for plain text, `.pdf` or original extension for documents).
|
|
43
65
|
|
|
@@ -45,13 +67,13 @@ Do **not** modify or summarize in the sources file — save it as-is.
|
|
|
45
67
|
|
|
46
68
|
---
|
|
47
69
|
|
|
48
|
-
## Step
|
|
70
|
+
## Step 5 — Synthesize
|
|
49
71
|
|
|
50
72
|
Read and synthesize the source:
|
|
51
73
|
|
|
52
74
|
1. **Check index.md** — does a page on this topic already exist?
|
|
53
75
|
- If yes: update the existing page (merge new information, mark `updated:` today)
|
|
54
|
-
- If no: create a new page in `pages/` with `type: source-summary` and `
|
|
76
|
+
- If no: create a new page in `pages/` with `type: source-summary` and `sources: [<slug>]`
|
|
55
77
|
|
|
56
78
|
2. **Frontmatter** for new pages:
|
|
57
79
|
```yaml
|
|
@@ -60,7 +82,7 @@ Read and synthesize the source:
|
|
|
60
82
|
type: source-summary
|
|
61
83
|
updated: YYYY-MM-DD
|
|
62
84
|
tags: [<relevant tags>]
|
|
63
|
-
|
|
85
|
+
sources: [<slug>]
|
|
64
86
|
confidence: high | medium | low
|
|
65
87
|
evidence_strength: direct
|
|
66
88
|
---
|
|
@@ -70,14 +92,14 @@ Read and synthesize the source:
|
|
|
70
92
|
|
|
71
93
|
---
|
|
72
94
|
|
|
73
|
-
## Step
|
|
95
|
+
## Step 6 — Update index.md and log.md
|
|
74
96
|
|
|
75
97
|
- Append a line to `index.md`: `- [[pages/<slug>]] — <one-line description>`
|
|
76
98
|
- Append to `log.md`: `- YYYY-MM-DD ingest: [[pages/<slug>]] from sources/<slug>.<ext>`
|
|
77
99
|
|
|
78
100
|
---
|
|
79
101
|
|
|
80
|
-
## Step
|
|
102
|
+
## Step 7 — Report
|
|
81
103
|
|
|
82
104
|
Show:
|
|
83
105
|
- ✓ Saved source: `sources/<slug>.<ext>`
|
package/commands/upgrade.md
CHANGED
|
@@ -28,7 +28,7 @@ node <package-root>/scripts/upgrade.mjs [--hypo-dir="<path>"]
|
|
|
28
28
|
|
|
29
29
|
Show the output verbatim.
|
|
30
30
|
|
|
31
|
-
> **Note**:
|
|
31
|
+
> **Note**: A major SCHEMA bump is only **detected** in this step. The informational `MIGRATION-vX.Y.md` file is written later by `--apply` (Step 4) and only on a major bump. `SCHEMA.md` is never auto-overwritten.
|
|
32
32
|
|
|
33
33
|
---
|
|
34
34
|
|
|
@@ -38,7 +38,7 @@ Show the output verbatim.
|
|
|
38
38
|
- `⚠` — minor update available (stale hook or missing settings entry)
|
|
39
39
|
- `✗` — major version bump or missing hook files (action required)
|
|
40
40
|
|
|
41
|
-
For a **major SCHEMA bump**:
|
|
41
|
+
For a **major SCHEMA bump**: warn the user that `--apply` will additionally write a `MIGRATION-vX.Y.md` informational file in their Hypomnema root and that they must manually merge the SCHEMA diff after applying.
|
|
42
42
|
|
|
43
43
|
---
|
|
44
44
|
|