hypomnema 1.3.0 → 1.3.2
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 +2 -2
- package/.claude-plugin/plugin.json +2 -2
- package/README.ko.md +12 -10
- package/README.md +12 -10
- package/commands/crystallize.md +8 -8
- package/commands/feedback.md +1 -1
- package/commands/resume.md +1 -1
- package/commands/upgrade.md +2 -0
- package/docs/ARCHITECTURE.md +3 -3
- package/docs/CONTRIBUTING.md +2 -2
- package/hooks/hypo-auto-minimal-crystallize.mjs +57 -11
- package/hooks/hypo-compact-guard.mjs +1 -1
- package/hooks/hypo-cwd-change.mjs +1 -1
- package/hooks/hypo-first-prompt.mjs +2 -2
- package/hooks/hypo-hot-rebuild.mjs +14 -1
- package/hooks/hypo-personal-check.mjs +91 -179
- package/hooks/hypo-pre-commit.mjs +1 -1
- package/hooks/hypo-session-end.mjs +1 -1
- package/hooks/hypo-session-start.mjs +26 -19
- package/hooks/hypo-shared.mjs +839 -58
- package/hooks/hypo-web-fetch-ingest.mjs +2 -2
- package/hooks/version-check-fetch.mjs +2 -8
- package/hooks/version-check.mjs +18 -0
- package/package.json +3 -2
- package/scripts/check-tracker-ids.mjs +329 -0
- package/scripts/crystallize.mjs +249 -109
- package/scripts/doctor.mjs +6 -9
- package/scripts/feedback-sync.mjs +1 -1
- package/scripts/init.mjs +1 -1
- package/scripts/install-git-hooks.mjs +75 -40
- package/scripts/lib/check-tracker-ids.mjs +140 -0
- package/scripts/lib/design-history-stale.mjs +59 -14
- package/scripts/lib/extensions.mjs +4 -4
- package/scripts/lib/fix-manifest.mjs +2 -2
- package/scripts/lib/fix-status-verify.mjs +5 -4
- package/scripts/lib/plugin-detect.mjs +60 -0
- package/scripts/lib/project-create.mjs +1 -1
- package/scripts/lint.mjs +63 -8
- package/scripts/rename.mjs +373 -0
- package/scripts/resume.mjs +127 -13
- package/scripts/smoke-pack.mjs +23 -2
- package/scripts/uninstall.mjs +1 -1
- package/scripts/upgrade.mjs +266 -47
- package/skills/crystallize/SKILL.md +10 -7
- package/templates/SCHEMA.md +2 -2
- package/templates/hypo-config.md +2 -2
- package/templates/hypo-guide.md +20 -1
- package/templates/projects/_template/index.md +1 -1
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
},
|
|
9
9
|
"plugins": [
|
|
10
10
|
{
|
|
11
|
-
"name": "
|
|
11
|
+
"name": "hypo",
|
|
12
12
|
"source": "./",
|
|
13
13
|
"description": "LLM-native personal wiki — session-aware knowledge base for Claude Code",
|
|
14
|
-
"version": "1.3.
|
|
14
|
+
"version": "1.3.2",
|
|
15
15
|
"homepage": "https://github.com/sk-lim19f/Hypomnema"
|
|
16
16
|
}
|
|
17
17
|
]
|
package/README.ko.md
CHANGED
|
@@ -23,13 +23,15 @@ _Claude에게 기록을 맡기세요 — 그리고 그 기록이 실제로 쌓
|
|
|
23
23
|
|
|
24
24
|
> **아래에서 자주 쓰이는 용어 간단 정리.** *프런트매터(frontmatter)* = 마크다운 파일 맨 위의 YAML 블록. *위키링크(wikilink)* = `[[페이지-슬러그]]` 형태의 교차 참조. *ADR* = "Architecture Decision Record" — 어떤 설계 결정을 *왜* 했는지 짧게 적은 마크다운 페이지. *projection*(투영) = 한 방향 자동 파생(`pages/feedback/*.md` → `MEMORY.md` / `<learned_behaviors>`). *훅(hook)* = Claude Code가 라이프사이클 이벤트에서 자동으로 실행하는 스크립트. *hot.md* / *session-state.md* = "방금 무엇을 했는지"와 "다음에 무엇을 할지"를 담는 프로젝트별 캐시 파일 — 멈춘 프로젝트를 한 번에 이어 받을 수 있게 합니다. 전체 용어 풀이는 [용어 사전](#용어-사전) 참조.
|
|
25
25
|
|
|
26
|
-
> **현재 자동화 범위와 다음 목표.** v1.
|
|
27
|
-
> - **`feedback` 페이지를 단일 원천(source of truth)으로**
|
|
28
|
-
> - **확장 파일 동봉 동기화**
|
|
29
|
-
> - **프로젝트 자동 생성**
|
|
30
|
-
> - **세션 종료 자동 정리와 `/clear` 복구**
|
|
26
|
+
> **현재 자동화 범위와 다음 목표.** v1.3.0(현재)은 트리거 모델을 솔직하게 정리합니다. 위키 작업(자료 정리·검색·세션 마무리)은 여전히 사용자가 `/hypo:*` 명령어를 직접 입력해 시작합니다. 다만 **v1.1.0**부터 위키가 한 세션에서 얼마나 활용됐는지를 측정하는 *관측성 지표(observability score)* 가 들어갔고, **v1.2.0**은 그 위에 사용자가 시키지 않아도 자동으로 동작하는 영역 4개를 추가했습니다:
|
|
27
|
+
> - **`feedback` 페이지를 단일 원천(source of truth)으로** — `pages/feedback/`에 한 번만 적으면, 위키가 `MEMORY.md`와 `~/.claude/CLAUDE.md`의 `<learned_behaviors>` 블록을 자동으로 갱신합니다.
|
|
28
|
+
> - **확장 파일 동봉 동기화** — 위키 안의 `~/hypomnema/extensions/{agents,commands,hooks,skills}/`에 둔 파일을 자동으로 `~/.claude/`에 반영합니다. `--codex` 옵션을 추가하면 `hooks`·`commands`는 `~/.codex/`에도 반영되지만, `agents`와 `skills`는 Claude 전용이라 의도적으로 건너뜁니다.
|
|
29
|
+
> - **프로젝트 자동 생성** — 작업 디렉터리를 git 저장소(`package.json`·`Cargo.toml` 등의 프로젝트 표식이 있는 곳)로 옮겼을 때 대응하는 위키 프로젝트가 없으면, 새로 만들지 물어봅니다.
|
|
30
|
+
> - **세션 종료 자동 정리와 `/clear` 복구** — 의미 있는 세션이 끝날 때 "마무리 메모를 짧게 남길까요?"가 자동으로 뜨고, 마무리하지 않은 채 `/clear`를 입력해도 다음 세션 시작 시 이어서 정리할 수 있습니다.
|
|
31
31
|
>
|
|
32
32
|
> 스키마(`SCHEMA.md`)는 2.0으로 올라갑니다. `feedback` 페이지 타입에 9개의 필수 항목이 추가되며, `hypomnema upgrade --apply`를 실행하면 위키 루트에 `MIGRATION-v2.0.md`가 생성되어 단계별 보강 체크리스트를 제공합니다. 사용자가 직접 편집한 `SCHEMA.md`는 upgrade가 **덮어쓰지 않습니다** — 안내만 표시하고, 실제 반영은 사용자가 수동으로 결정합니다(이 정책을 코드에서는 *Option C*로 부릅니다).
|
|
33
|
+
>
|
|
34
|
+
> **v1.3.0**은 자율성을 넓히기보다 이 레이어를 다듬습니다. 세션 마무리 흐름에 *권고형* 성찰 4가지(자동 실행 없이 제안만)가 들어가고, `hypomnema lint --strict`가 선택된 경고를 에러로 승격해 릴리스 게이트로 쓸 수 있으며, 설치가 **stale-sibling 감지**로 단단해집니다 — `$PATH`에 남은 더 오래된 `hypomnema`가 더는 활성 훅을 조용히 다운그레이드하지 못합니다.
|
|
33
35
|
|
|
34
36
|
---
|
|
35
37
|
|
|
@@ -43,7 +45,7 @@ Claude Code 안에서:
|
|
|
43
45
|
|
|
44
46
|
```
|
|
45
47
|
/plugin marketplace add sk-lim19f/Hypomnema
|
|
46
|
-
/plugin install
|
|
48
|
+
/plugin install hypo@hypomnema
|
|
47
49
|
/hypo:init
|
|
48
50
|
```
|
|
49
51
|
|
|
@@ -238,16 +240,16 @@ v1.0에서는 `personal / shared / public` 3-mode를 만들었습니다. 현실
|
|
|
238
240
|
| `hypo-auto-commit.mjs` | `Stop` | 자동 commit + pull + push |
|
|
239
241
|
| `hypo-hot-rebuild.mjs` | `Stop` | `hot.md` 재생성 |
|
|
240
242
|
| `hypo-personal-check.mjs` | `PreCompact` | lint 실패 / session-close 미완 시 compact 차단 |
|
|
241
|
-
| `hypo-session-end.mjs` | `SessionEnd` | SessionEnd 마커 기록 — 다음 SessionStart가 `source=clear` 복구를 감지하기 위함
|
|
243
|
+
| `hypo-session-end.mjs` | `SessionEnd` | SessionEnd 마커 기록 — 다음 SessionStart가 `source=clear` 복구를 감지하기 위함 |
|
|
242
244
|
| `hypo-session-record.mjs` | `Stop` | observability 점수 + auto-resume 신호용 세션 메타데이터 기록 |
|
|
243
|
-
| `hypo-auto-minimal-crystallize.mjs` | `Stop` | 단순하지 않은 세션이 끝났을 때 `/hypo:crystallize --apply-session-close --minimal`을 자동 제안 (사용자가 동의하면
|
|
245
|
+
| `hypo-auto-minimal-crystallize.mjs` | `Stop` | 단순하지 않은 세션이 끝났을 때 `/hypo:crystallize --apply-session-close --minimal`을 자동 제안 (사용자가 동의하면 실행) |
|
|
244
246
|
| `hypo-web-fetch-ingest.mjs` | `PostToolUse(WebFetch/WebSearch)` | WebFetch/WebSearch 완료 후 `additionalContext`에 `/hypo:ingest` 권유 안내 주입 (privacy 보호: WebFetch URL의 query/hash/userinfo 제거) |
|
|
245
247
|
|
|
246
248
|
모든 훅은 위키 루트를 `HYPO_DIR` 환경변수 → `hypo-config.md` 스캔 → `~/hypomnema` 기본값 순으로 해결하며, `hypo-shared.mjs`(`hooks.json`의 `shared` 필드로 선언)를 공유합니다.
|
|
247
249
|
|
|
248
250
|
이와 별도로 `SessionStart` 훅은 npm 레지스트리와 Claude Code 플러그인 마켓플레이스를 백그라운드에서 확인합니다(세션 시작을 막지 않습니다). 새 버전이 게시되어 있으면 다음 세션 시작 시 "Update available!" 안내가 한 줄 표시됩니다. `HYPO_NO_UPDATE_CHECK=1`, `NO_UPDATE_NOTIFIER=1`을 지정하거나 `CI=true` 환경에서 실행하면 점검을 건너뜁니다.
|
|
249
251
|
|
|
250
|
-
위 네 가지 레인 외의 v1.
|
|
252
|
+
위 네 가지 레인 외의 v1.3 세부 수정 — 세션 마무리 lint를 건드린 파일로 스코프해 무관한 debt로 `/compact`가 막히지 않게 한 변경, `feedback` scope 검증기가 cwd 유래 project id를 수용하게 한 수정, `--strict`가 에러로 승격하는 안정적 lint 경고 ID `W1`/`W2`/`W4`(`--fix`로 자동복구되는 `W3`는 경고로 유지) — 은 [`CHANGELOG.md`](CHANGELOG.md)를 참고하세요. **v1.3.1**은 수정 전용 패치입니다: 업데이트 notifier 배너가 이제 보이지 않던 stderr 출력 대신 top-level `systemMessage` 채널로 실제 사용자에게 도달하고, `/hypo:upgrade`가 플러그인·dual(수동+플러그인) 설치에서 core 훅을 중복 등록하지 않으며, 세션 마무리가 두 프로젝트가 같은 최신 날짜를 가질 때 완료된 close를 false-block 하지 않습니다. **v1.3.2**는 비-프로젝트(툴링·위키 전용) 세션을 무관한 프로젝트에 엮지 않고 닫는 1급 log-only close 경로와, 페이지 이름을 바꿀 때 해당하는 인바운드 위키링크를 갱신하는 `rename` 헬퍼를 추가합니다(모호하거나 append-only인 참조는 갱신하지 않고 보고합니다). 또한 세션 마무리 게이트(오늘 활동한 모든 프로젝트를 게이트, 세션별 마커와 `/compact`가 하나의 게이트를 공유, 도출 가능한 루트 `log.md` 항목 자동 도출)와 linter(`--json`이 파이프에서 잘리지 않음, 볼트 관습 위키링크를 오탐 대신 정상 해석)를 수정합니다.
|
|
251
253
|
|
|
252
254
|
### 셋업 & 유지보수
|
|
253
255
|
|
|
@@ -346,7 +348,7 @@ Claude가 잘못한 순간 — 또는 반대로 정확히 잘한 순간 — `/hy
|
|
|
346
348
|
|
|
347
349
|
> **모델 사업자에게 전송되는 범위 안내.** Hypomnema 훅은 위키 본문을 Claude Code의 추가 컨텍스트(`additionalContext`)에 실어 보내며, 이 내용은 프롬프트의 일부로 Claude 모델 사업자에게 전송됩니다. 따라서 `.hypoignore`에 등록된 경로는 모든 주입 훅(`hypo-file-watch`, `hypo-session-start`, `hypo-cwd-change`, `hypo-lookup`)과 `ingest`에서 제외되지만, 등록되지 *않은* 파일은 전송 대상이 됩니다. (`hypo-auto-stage`/`hypo-auto-commit`은 git 스테이징용 훅이라 컨텍스트를 주입하지는 않지만, 스테이징 판단에도 동일하게 `.hypoignore`를 참고합니다.) 비밀 정보는 위키에 두지 마시고, `HYPO_DIR` 아래에 민감한 내용을 저장하기 전에 `.hypoignore` 패턴을 먼저 점검하시기 바랍니다.
|
|
348
350
|
|
|
349
|
-
> **git sync 범위.** Hypomnema는 `~/hypomnema/` 위키 자체만 git sync합니다. 단, `init` / `upgrade`는 `~/.claude/` 내부의 관리 대상 영역 — Hypomnema 자체 hook(`~/.claude/hooks/`), 슬래시 커맨드(`~/.claude/commands/hypo/`), `settings.json` 등록 — 을 설치·SHA 추적하며, v1.2.0 **extensions companion sync
|
|
351
|
+
> **git sync 범위.** Hypomnema는 `~/hypomnema/` 위키 자체만 git sync합니다. 단, `init` / `upgrade`는 `~/.claude/` 내부의 관리 대상 영역 — Hypomnema 자체 hook(`~/.claude/hooks/`), 슬래시 커맨드(`~/.claude/commands/hypo/`), `settings.json` 등록 — 을 설치·SHA 추적하며, v1.2.0 **extensions companion sync**에 의해 위키의 `~/hypomnema/extensions/`에 둔 `agents/`·`commands/`·`hooks/`·`skills/`도 자동 미러링합니다(`--codex` 옵션 시 `hooks`·`commands` 부분 집합만 `~/.codex/`로). 이 관리 대상 영역 *바깥*의 `~/.claude/` 콘텐츠는 의도적으로 Hypomnema가 **관리하지 않습니다** — 위키를 거치지 않는 기타 agent/skill, 머신 고유 `settings.local.json` 등 일반적인 Claude Code 설정 기기 간 동기화는 [chezmoi](https://www.chezmoi.io/) 같은 별도 dotfiles 매니저 사용을 권장합니다.
|
|
350
352
|
|
|
351
353
|
### `/hypo:*` 커맨드는 어디서 오는가?
|
|
352
354
|
|
package/README.md
CHANGED
|
@@ -23,13 +23,15 @@ _Make Claude take notes — and measure whether it actually does._
|
|
|
23
23
|
|
|
24
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).
|
|
25
25
|
|
|
26
|
-
> **Current state vs. v2 vision.** v1.
|
|
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
|
|
26
|
+
> **Current state vs. v2 vision.** v1.3.0 (today) 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
31
|
>
|
|
32
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.
|
|
33
35
|
|
|
34
36
|
---
|
|
35
37
|
|
|
@@ -43,7 +45,7 @@ Inside Claude Code:
|
|
|
43
45
|
|
|
44
46
|
```
|
|
45
47
|
/plugin marketplace add sk-lim19f/Hypomnema
|
|
46
|
-
/plugin install
|
|
48
|
+
/plugin install hypo@hypomnema
|
|
47
49
|
/hypo:init
|
|
48
50
|
```
|
|
49
51
|
|
|
@@ -238,16 +240,16 @@ Eight commands cover the full capture → retrieval → consolidation cycle.
|
|
|
238
240
|
| `hypo-auto-commit.mjs` | `Stop` | Auto commit + pull + push |
|
|
239
241
|
| `hypo-hot-rebuild.mjs` | `Stop` | Rebuild `hot.md` |
|
|
240
242
|
| `hypo-personal-check.mjs` | `PreCompact` | Block compact on lint failures or unfinished session-close |
|
|
241
|
-
| `hypo-session-end.mjs` | `SessionEnd` | Write a SessionEnd marker so SessionStart can detect `source=clear` recovery
|
|
243
|
+
| `hypo-session-end.mjs` | `SessionEnd` | Write a SessionEnd marker so SessionStart can detect `source=clear` recovery |
|
|
242
244
|
| `hypo-session-record.mjs` | `Stop` | Record session metadata for the observability score and auto-resume signaling |
|
|
243
|
-
| `hypo-auto-minimal-crystallize.mjs` | `Stop` | Offer (and on consent run) `/hypo:crystallize --apply-session-close --minimal` after non-trivial sessions
|
|
245
|
+
| `hypo-auto-minimal-crystallize.mjs` | `Stop` | Offer (and on consent run) `/hypo:crystallize --apply-session-close --minimal` after non-trivial sessions |
|
|
244
246
|
| `hypo-web-fetch-ingest.mjs` | `PostToolUse(WebFetch/WebSearch)` | Inject a `/hypo:ingest` nudge into `additionalContext` after a URL resolution (privacy-aware: redacts query/hash/userinfo) |
|
|
245
247
|
|
|
246
248
|
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).
|
|
247
249
|
|
|
248
250
|
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`.
|
|
249
251
|
|
|
250
|
-
For fix-level v1.
|
|
252
|
+
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).
|
|
251
253
|
|
|
252
254
|
### Setup & maintenance
|
|
253
255
|
|
|
@@ -346,7 +348,7 @@ Place a `hypo-config.md` at the wiki root to make it portable across machines wi
|
|
|
346
348
|
|
|
347
349
|
> **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
350
|
|
|
349
|
-
> **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
|
|
351
|
+
> **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
352
|
|
|
351
353
|
### Where do `/hypo:*` commands live?
|
|
352
354
|
|
package/commands/crystallize.md
CHANGED
|
@@ -20,8 +20,8 @@ If the user invoked `/hypo:crystallize` to close a session (phrases like "세션
|
|
|
20
20
|
Before composing the payload (Step 2), run these four reflections and surface each to the user. Every one is **advisory** (ADR 0029 identity guard) — the user confirms or declines, and none performs an automatic action, writes a file on its own, or bypasses the mandatory gate.
|
|
21
21
|
|
|
22
22
|
1. **Trivial-session check (#44)** — Was this session trivial (a single bug fix, a single-file edit, or Q&A with no durable artifact)? If so, recommend skipping session-close: *"이 세션은 trivial해 보입니다 — session-close를 건너뛸까요?"* and proceed only if the user wants a close. A trivial skip is a recommendation, **not** a bypass: it must not mark the session closed, must not run `--mark-session-closed`, and must not claim `/compact` can pass. Any real close still requires all 5 mandatory files.
|
|
23
|
-
2. **ADR-candidate check (#41)** — Did this session make an architectural or design decision (a new pattern, a tradeoff chosen, a convention established)? If yes, ask whether it warrants an ADR and, if so, capture that intent in the `sessionLog` entry you compose in Step 2. If nothing rose to ADR level, record `ADR 없음 — <one-line reason>` in that same `sessionLog` entry. **Never auto-write an ADR file** — recording the decision (or its absence) in the session-log payload is the only action here.
|
|
24
|
-
3. **design-history staleness check (#42)** —
|
|
23
|
+
2. **ADR-candidate check (#41)** — Did this session make an architectural or design decision (a new pattern, a tradeoff chosen, a convention established)? If yes, ask whether it warrants an ADR and, if so, capture that intent in the `sessionLog` entry you compose in Step 2. If nothing rose to ADR level, you may record `ADR 없음 — <one-line reason>` in that same `sessionLog` entry — but gate it on #42's bar: the marker is machine-read and W8 excludes an entry carrying `ADR 없음` (with no ADR reference) from the design-history staleness check. Write it only when the session had **no design change at all**; a sub-ADR design shift takes #42a (append) instead, since the marker would suppress the W8 nudge it needs. **Never auto-write an ADR file** — recording the decision (or its absence) in the session-log payload is the only action here.
|
|
24
|
+
3. **design-history staleness check (#42)** — Two branches, so a stale W8 never blocks a clean close: (a) if this session changed design decisions `projects/<name>/design-history.md` does not yet reflect — including sub-ADR background / tradeoff / differentiation shifts — recommend appending now (the W8 lint warning flags this mechanically; an active-project W8 hard-blocks at PreCompact — append before you commit). (b) only if the session made **no** design change does the `ADR 없음` marker (#41) exempt the entry from W8; do not touch design-history. `ADR 없음` means "no design change," a stricter bar than "no ADR-level decision." If the file does not exist, skip silently — do **not** create it just for this check. Never auto-update it.
|
|
25
25
|
4. **Ingest check (#43)** — Did this session consume trustworthy external knowledge (a fetched URL, official docs, or code you verified directly)? If so, recommend running `/hypo:ingest` to capture it under `sources/`. Proceed only on the user's confirmation.
|
|
26
26
|
|
|
27
27
|
These are judgment calls; when uncertain, surface the question rather than skip it. None of the four blocks the close or writes on its own.
|
|
@@ -30,7 +30,7 @@ These are judgment calls; when uncertain, surface the question rather than skip
|
|
|
30
30
|
|
|
31
31
|
## Step 2 — Compose the session-close payload
|
|
32
32
|
|
|
33
|
-
The session-close path is **payload-driven
|
|
33
|
+
The session-close path is **payload-driven**. 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.
|
|
34
34
|
|
|
35
35
|
Payload shape (5 required + 1 conditional, per Spec §5.2.7 / §8.3 + ADR 0029):
|
|
36
36
|
|
|
@@ -41,7 +41,7 @@ Payload shape (5 required + 1 conditional, per Spec §5.2.7 / §8.3 + ADR 0029):
|
|
|
41
41
|
"sessionState": { "content": "<full body of projects/<name>/session-state.md>" },
|
|
42
42
|
"projectHot": { "content": "<full body of projects/<name>/hot.md>" },
|
|
43
43
|
"rootHot": { "content": "<full body of <hypo-root>/hot.md>" },
|
|
44
|
-
"sessionLog": { "entry": "<entry to append to projects/<name>/session-log/YYYY-MM.md>" },
|
|
44
|
+
"sessionLog": { "entry": "<entry to append to projects/<name>/session-log/YYYY-MM-DD.md (daily shard)>" },
|
|
45
45
|
"log": { "entry": "<entry to append to <hypo-root>/log.md>" },
|
|
46
46
|
"openQuestions": { "content": "<full body of pages/open-questions.md>" }
|
|
47
47
|
}
|
|
@@ -67,7 +67,7 @@ Content guidance for each slot:
|
|
|
67
67
|
1. **sessionState** — next tasks list for the upcoming session (what to tackle first next time).
|
|
68
68
|
2. **projectHot** — session snapshot under 500 words: what changed and decisions made. Do **not** put next-step tasks here; those belong in `sessionState`.
|
|
69
69
|
3. **rootHot** — active-projects pointer table with this project's `Last Session` date set to today.
|
|
70
|
-
4. **sessionLog** — one session entry to append to `projects/<name>/session-log/YYYY-MM.md
|
|
70
|
+
4. **sessionLog** — one session entry to append to `projects/<name>/session-log/YYYY-MM-DD.md` (daily shard).
|
|
71
71
|
5. **log** — one `session` entry to append to `<hypo-root>/log.md`.
|
|
72
72
|
6. **openQuestions** (conditional) — only if `pages/open-questions.md` exists and questions were raised or resolved this session.
|
|
73
73
|
|
|
@@ -84,7 +84,7 @@ node <package-root>/scripts/crystallize.mjs \
|
|
|
84
84
|
--json
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
**`--session-id
|
|
87
|
+
**`--session-id`:** pass the current session's id whenever you
|
|
88
88
|
know it — most importantly when this close was triggered by a `[WIKI_AUTOCLOSE]`
|
|
89
89
|
Stop-hook block (the block reason prints the exact `--session-id` to use). On a
|
|
90
90
|
verified close (`ok: true` + clean git tree), it writes the per-session marker
|
|
@@ -93,7 +93,7 @@ Stop-chain Layer 3 hook (`hypo-auto-minimal-crystallize`) the session is closed,
|
|
|
93
93
|
so it stops re-prompting. Omit it only when running crystallize purely for
|
|
94
94
|
synthesis (no session-close intent) — the marker is then simply not written.
|
|
95
95
|
|
|
96
|
-
**Behavior (
|
|
96
|
+
**Behavior (option D + lint gates):**
|
|
97
97
|
|
|
98
98
|
| Invocation | Behavior |
|
|
99
99
|
|---|---|
|
|
@@ -102,7 +102,7 @@ synthesis (no session-close intent) — the marker is then simply not written.
|
|
|
102
102
|
| `--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. |
|
|
103
103
|
| `--apply-session-close --force` | Skips the probe early-exit. `--payload` still required for any actual apply work. |
|
|
104
104
|
|
|
105
|
-
**Two lint gates run automatically
|
|
105
|
+
**Two lint gates run automatically, scoped to the files this close writes:**
|
|
106
106
|
|
|
107
107
|
Both gates judge only the **payload files** (the 5 mandatory close files + `open-questions.md`). Lint debt in other projects or shared `pages/` this close did not author is reported as a non-blocking `notices[]` entry, never gated — so an unrelated broken page elsewhere cannot block your close.
|
|
108
108
|
|
package/commands/feedback.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
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/` — the **single source of truth** for learned behaviors (ADR 0031
|
|
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).
|
|
6
6
|
|
|
7
7
|
## What this does
|
|
8
8
|
|
package/commands/resume.md
CHANGED
|
@@ -20,7 +20,7 @@ If the user named a project in the command invocation, use that. Otherwise, loca
|
|
|
20
20
|
node <package-root>/scripts/resume.mjs [--hypo-dir="<path>"] [--project=<name>]
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
When `--project` is omitted, the script prefers the project whose `working_dir` contains the current directory (cwd-first); if nothing under the current directory matches, it falls back to the most recently active project from `hot.md`.
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
package/commands/upgrade.md
CHANGED
|
@@ -28,6 +28,8 @@ node <package-root>/scripts/upgrade.mjs [--hypo-dir="<path>"]
|
|
|
28
28
|
|
|
29
29
|
Show the output verbatim.
|
|
30
30
|
|
|
31
|
+
> **Plugin installs**: if the output begins with `ℹ Plugin install detected`, the core hooks, slash commands, and `settings.json` wiring are managed by the Claude Code plugin loader — **not** by `/hypo:upgrade`. Do **not** run `--apply` expecting it to update them (it intentionally skips those to avoid double-registering every hook). To upgrade the plugin itself: `/plugin marketplace update hypomnema` then `/reload-plugins`. `--apply` in plugin mode applies vault-side migrations (SCHEMA, `.hypoignore`), refreshes package metadata, and still syncs any vault extensions — but does **not** install the core hooks/commands/settings (the plugin provides those).
|
|
32
|
+
|
|
31
33
|
> **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
34
|
|
|
33
35
|
---
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -80,7 +80,7 @@ The synthesis-heavy commands (`ingest`, `query`, `crystallize`, `lint`, `verify`
|
|
|
80
80
|
|
|
81
81
|
## Agent Skills
|
|
82
82
|
|
|
83
|
-
`skills/<name>/SKILL.md` follows the Claude Agent Skills convention
|
|
83
|
+
`skills/<name>/SKILL.md` follows the Claude Agent Skills convention. When a conversation matches the skill's description, Claude auto-loads it without needing the slash command.
|
|
84
84
|
|
|
85
85
|
> v1.0 originally planned flat `skills/*.md` files; v1.1 switched to `<name>/SKILL.md` for compatibility with the official Agent Skills loader.
|
|
86
86
|
|
|
@@ -179,7 +179,7 @@ Helpers used by command scripts only. Not deployed to hooks.
|
|
|
179
179
|
│ ├── hot.md ← project-level current state
|
|
180
180
|
│ ├── session-state.md ← next tasks + last session summary
|
|
181
181
|
│ └── session-log/
|
|
182
|
-
│ └── YYYY-MM.md
|
|
182
|
+
│ └── YYYY-MM-DD.md ← append-only daily session-log shard
|
|
183
183
|
├── journal/
|
|
184
184
|
│ ├── daily/
|
|
185
185
|
│ ├── weekly/
|
|
@@ -331,7 +331,7 @@ scripts/weekly-report.mjs ← aggregated weekly autonomy score
|
|
|
331
331
|
journal/weekly/<YYYY-Www>.md ← committed report (heuristic v0, spec §6.4 SoT)
|
|
332
332
|
```
|
|
333
333
|
|
|
334
|
-
### Transcript dual-source
|
|
334
|
+
### Transcript dual-source
|
|
335
335
|
|
|
336
336
|
`session-audit.mjs` reads transcripts from two locations, in priority order:
|
|
337
337
|
|
package/docs/CONTRIBUTING.md
CHANGED
|
@@ -142,7 +142,7 @@ npm run fix:verify # Phase 1 of learned_behavior #6 — verifies fix #N status c
|
|
|
142
142
|
When a test verifies behavior tied to a numbered fix in the wiki spec, add an anchor immediately above the `suite(...)` or `test(...)` call:
|
|
143
143
|
|
|
144
144
|
```js
|
|
145
|
-
// @fix #
|
|
145
|
+
// @fix #N: replay-compact-guard-detects-slash-clear: /clear with incomplete wiki → WIKI_AUTOCLOSE
|
|
146
146
|
test('replay-compact-guard-detects-slash-clear: /clear with incomplete wiki → WIKI_AUTOCLOSE', () => { ... });
|
|
147
147
|
```
|
|
148
148
|
|
|
@@ -317,7 +317,7 @@ Major bumps must include an `upgrade.mjs` migration fixture in `tests/runner.mjs
|
|
|
317
317
|
These documents live in the maintainer's personal wiki, not in this repo:
|
|
318
318
|
|
|
319
319
|
- `~/hypomnema/projects/hypomnema/prd-v1.1.md` — current product requirements
|
|
320
|
-
- `~/hypomnema/projects/hypomnema/decisions
|
|
320
|
+
- `~/hypomnema/projects/hypomnema/decisions/*.md` — architecture decision records
|
|
321
321
|
- `~/hypomnema/projects/hypomnema/design-history.md` — narrative design history
|
|
322
322
|
- `~/hypomnema/projects/hypomnema/backlog-v1.0.md` — historical gap analysis (archived)
|
|
323
323
|
- `~/hypomnema/projects/hypomnema/test-cases-v1.0.md` — historical QA spec (archived)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* hypo-auto-minimal-crystallize.mjs — Stop hook (
|
|
3
|
+
* hypo-auto-minimal-crystallize.mjs — Stop hook (ADR 0022 Layer 3)
|
|
4
4
|
*
|
|
5
5
|
* Last hook in the Stop chain: a final-line defense that blocks `Stop` when
|
|
6
|
-
* the current session
|
|
6
|
+
* the current session did substantial work (mutation, or a high-volume
|
|
7
|
+
* read-only investigation — see step 3) but never produced a verified
|
|
7
8
|
* session-close. Forces Claude to run minimal session-close before the
|
|
8
9
|
* conversation context evaporates.
|
|
9
10
|
*
|
|
@@ -11,8 +12,10 @@
|
|
|
11
12
|
*
|
|
12
13
|
* 1. stop_hook_active === true → continue (loop guard; PoC 2026-05-14)
|
|
13
14
|
* 2. wiki absent → continue (fail-open)
|
|
14
|
-
* 3.
|
|
15
|
-
*
|
|
15
|
+
* 3. not a substantial session → continue (substantial-session gate)
|
|
16
|
+
* substantial = ≥1 mutation tool_use, OR ≥5 read-only investigation
|
|
17
|
+
* calls (Read/Grep/Glob/Bash) — 6a, so read-only review/debug sessions
|
|
18
|
+
* are also nudged to close. Pure Q&A / incidental lookups still skip.
|
|
16
19
|
* 4. no recent user close-intent → continue (close-intent gate, see below)
|
|
17
20
|
* 5. readSessionClosedMarker(session_id) valid
|
|
18
21
|
* → continue (close already verified)
|
|
@@ -43,18 +46,19 @@ import { join } from 'path';
|
|
|
43
46
|
import {
|
|
44
47
|
HYPO_DIR,
|
|
45
48
|
PKG_ROOT,
|
|
46
|
-
|
|
49
|
+
isSubstantialSession,
|
|
47
50
|
readSessionClosedMarker,
|
|
48
51
|
extractUserMessages,
|
|
49
52
|
isClosePattern,
|
|
50
53
|
isGateSkipped,
|
|
54
|
+
precompactGateStatus,
|
|
51
55
|
} from './hypo-shared.mjs';
|
|
52
56
|
|
|
53
57
|
function emitContinue() {
|
|
54
58
|
console.log(JSON.stringify({ continue: true, suppressOutput: true }));
|
|
55
59
|
}
|
|
56
60
|
|
|
57
|
-
function emitBlock(sessionId, transcriptPath) {
|
|
61
|
+
function emitBlock(sessionId, transcriptPath, gate = null) {
|
|
58
62
|
// One-line, skill-first. /hypo:crystallize is the documented session-close
|
|
59
63
|
// alias; passing --session-id there writes the per-session marker that clears
|
|
60
64
|
// this block. CLI fallback + bypass live in commands/crystallize.md, not here
|
|
@@ -64,12 +68,39 @@ function emitBlock(sessionId, transcriptPath) {
|
|
|
64
68
|
// coherence: a marker written without lint would only let Stop pass for
|
|
65
69
|
// /compact to immediately re-block on the same errors).
|
|
66
70
|
const transcriptHint = transcriptPath ? ` --transcript-path=${transcriptPath}` : '';
|
|
67
|
-
const
|
|
71
|
+
const markCmd = `crystallize --mark-session-closed --session-id=${sessionId}${transcriptHint}`;
|
|
72
|
+
// The log-only escape hatch for a non-project (wiki/tooling-only)
|
|
73
|
+
// session. Offered ONLY as an explicit alternative when a close blocker is
|
|
74
|
+
// present — never as the default recovery, so a real project session is not
|
|
75
|
+
// taught to bypass the ADR 0043 close invariant (codex design Finding 3).
|
|
76
|
+
const logOnlyCmd = `crystallize --mark-session-closed --log-only --session-id=${sessionId}${transcriptHint}`;
|
|
77
|
+
// ADR 0047: refine the message with the read-only /compact gate result.
|
|
78
|
+
// - gate green → the close is compact-ready and ONLY the marker is missing
|
|
79
|
+
// (the hand-edit close case: files Written + committed directly, bypassing
|
|
80
|
+
// the marker writer). Say so precisely + give the one command, instead of
|
|
81
|
+
// the generic "미완료" that reads as "you never closed".
|
|
82
|
+
// - gate has blockers → surface them so the user fixes the real issue first.
|
|
83
|
+
// - gate null (tooling error/unavailable) → generic message (fail-open).
|
|
84
|
+
let reason;
|
|
85
|
+
if (gate && gate.ok) {
|
|
86
|
+
reason = `[WIKI_AUTOCLOSE] close gate green — only the session-closed marker is missing. Run \`${markCmd}\` to finish (session_id=${sessionId}).`;
|
|
87
|
+
} else if (gate && gate.blockers && gate.blockers.length > 0) {
|
|
88
|
+
const blockers = gate.blockers.map((b) => b.reason).join('; ');
|
|
89
|
+
reason = `[WIKI_AUTOCLOSE] session-close incomplete — resolve: ${blockers}. Then run \`${markCmd}\` (session_id=${sessionId}).`;
|
|
90
|
+
// Only when a project-close blocker is what's holding the session: a
|
|
91
|
+
// non-project session has nothing to close, so offer log-only as the way out
|
|
92
|
+
// (Claude decides whether this session is project-scoped — no auto-attribution).
|
|
93
|
+
if (gate.blockers.some((b) => b.type === 'close')) {
|
|
94
|
+
reason += ` If this was a non-project (wiki/tooling-only) session with no project to close, run \`${logOnlyCmd}\` instead (log-only close, no project attribution).`;
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
reason = `[WIKI_AUTOCLOSE] session-close 미완료 — /hypo:crystallize 실행으로 마무리 (session_id=${sessionId}${transcriptHint}).`;
|
|
98
|
+
}
|
|
68
99
|
console.log(
|
|
69
100
|
JSON.stringify({
|
|
70
101
|
decision: 'block',
|
|
71
102
|
reason,
|
|
72
|
-
stopReason: 'session-close incomplete (
|
|
103
|
+
stopReason: 'session-close incomplete (ADR 0022 Layer 3)',
|
|
73
104
|
}),
|
|
74
105
|
);
|
|
75
106
|
}
|
|
@@ -112,8 +143,10 @@ process.stdin.on('end', () => {
|
|
|
112
143
|
const sessionId = payload.session_id || payload.sessionId || null;
|
|
113
144
|
const transcriptPath = payload.transcript_path || payload.transcriptPath || null;
|
|
114
145
|
|
|
115
|
-
// 3. substantial-session gate.
|
|
116
|
-
|
|
146
|
+
// 3. substantial-session gate. Pure Q&A / incidental-lookup sessions skip
|
|
147
|
+
// the block; mutating sessions AND high-volume read-only investigations
|
|
148
|
+
// (6a) pass through to the close-intent gate.
|
|
149
|
+
if (!isSubstantialSession(transcriptPath)) {
|
|
117
150
|
emitContinue();
|
|
118
151
|
return;
|
|
119
152
|
}
|
|
@@ -141,7 +174,20 @@ process.stdin.on('end', () => {
|
|
|
141
174
|
return;
|
|
142
175
|
}
|
|
143
176
|
|
|
144
|
-
|
|
177
|
+
// ADR 0047: read-only /compact gate (same precompactGateStatus the real
|
|
178
|
+
// PreCompact hook uses) sharpens the block message — distinguishes "close
|
|
179
|
+
// is compact-ready, only the marker is missing" from "there are real
|
|
180
|
+
// blockers". The hook NEVER writes the marker here (file-header invariant);
|
|
181
|
+
// this is read-only. Any error → null → emitBlock falls back to the generic
|
|
182
|
+
// message (fail-open).
|
|
183
|
+
let gate = null;
|
|
184
|
+
try {
|
|
185
|
+
gate = precompactGateStatus(HYPO_DIR, transcriptPath ? { transcriptPath } : {});
|
|
186
|
+
} catch {
|
|
187
|
+
gate = null;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
emitBlock(sessionId, transcriptPath, gate);
|
|
145
191
|
} catch (err) {
|
|
146
192
|
// Fail-open on any unexpected error.
|
|
147
193
|
process.stderr.write(`[hypo-auto-minimal-crystallize] error: ${err?.message ?? String(err)}\n`);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* hypo-compact-guard.mjs — UserPromptSubmit hook
|
|
4
4
|
*
|
|
5
|
-
* Scope: detects "/compact" or "/clear" typed in chat only (ADR 0022 Layer 2
|
|
5
|
+
* Scope: detects "/compact" or "/clear" typed in chat only (ADR 0022 Layer 2).
|
|
6
6
|
* The CLI built-in /compact does NOT fire UserPromptSubmit — use personal-wiki-check.mjs
|
|
7
7
|
* (PreCompact hook) as the hard gate for that path. /clear has no PreCompact event, so
|
|
8
8
|
* this hook is the only chat-side gate that can prompt session-close before context wipe.
|
|
@@ -137,7 +137,7 @@ process.stdin.on('end', () => {
|
|
|
137
137
|
return;
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
// MISS: cwd matches no project.
|
|
140
|
+
// MISS: cwd matches no project. ADR 0023 — offer to create one
|
|
141
141
|
// when the trigger conditions hold. Same nudge-only model as session-start.
|
|
142
142
|
let suggestPrefix = '';
|
|
143
143
|
if (shouldSuggestProjectCreation(newCwd, HYPO_DIR)) {
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* hypo-first-prompt.mjs — UserPromptSubmit hook
|
|
4
4
|
*
|
|
5
5
|
* Consumes the marker written by hypo-session-start.mjs (source omitted /
|
|
6
|
-
* 'session-start') or hypo-cwd-change.mjs (source 'cwd-change'
|
|
6
|
+
* 'session-start') or hypo-cwd-change.mjs (source 'cwd-change').
|
|
7
7
|
* On the FIRST user prompt after the marker is written, FORCES a one-line
|
|
8
|
-
* resume summary into the reply (
|
|
8
|
+
* resume summary into the reply (the old "answer only if related"
|
|
9
9
|
* conditional is removed; the line is injected unconditionally).
|
|
10
10
|
*
|
|
11
11
|
* hot.md / session-state.md content is NOT re-injected here — the upstream
|
|
@@ -12,7 +12,12 @@
|
|
|
12
12
|
|
|
13
13
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
14
14
|
import { join } from 'path';
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
HYPO_DIR,
|
|
17
|
+
computeSessionGrowth,
|
|
18
|
+
formatGrowthMetrics,
|
|
19
|
+
deriveRootLogEntries,
|
|
20
|
+
} from './hypo-shared.mjs';
|
|
16
21
|
|
|
17
22
|
const HOT_PATH = join(HYPO_DIR, 'hot.md');
|
|
18
23
|
const GROWTH_CACHE = join(HYPO_DIR, '.cache', 'last-session-growth.json');
|
|
@@ -107,6 +112,14 @@ try {
|
|
|
107
112
|
} catch (err) {
|
|
108
113
|
process.stderr.write(`[hypo-hot-rebuild] error: ${err?.message ?? String(err)}\n`);
|
|
109
114
|
}
|
|
115
|
+
// Auto-derive the root log.md session entry from each project's session-log
|
|
116
|
+
// heading (runs AFTER rebuild() so root hot.md is already fresh and isn't itself
|
|
117
|
+
// counted as the project's open gate problem). Best-effort: own try/catch.
|
|
118
|
+
try {
|
|
119
|
+
deriveRootLogEntries(HYPO_DIR);
|
|
120
|
+
} catch (err) {
|
|
121
|
+
process.stderr.write(`[hypo-hot-rebuild] log-derive error: ${err?.message ?? String(err)}\n`);
|
|
122
|
+
}
|
|
110
123
|
try {
|
|
111
124
|
emitGrowth();
|
|
112
125
|
} catch (err) {
|