hypomnema 1.4.0 → 1.4.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 +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.ko.md +151 -153
- package/README.md +121 -123
- package/commands/audit.md +4 -4
- package/commands/crystallize.md +22 -7
- package/commands/doctor.md +3 -3
- package/commands/feedback.md +5 -3
- package/commands/graph.md +3 -3
- package/commands/ingest.md +6 -4
- package/commands/init.md +5 -3
- package/commands/lint.md +3 -3
- package/commands/query.md +3 -3
- package/commands/rename.md +4 -4
- package/commands/resume.md +4 -2
- package/commands/stats.md +3 -3
- package/commands/upgrade.md +4 -4
- package/commands/verify.md +3 -3
- package/docs/CONTRIBUTING.md +107 -16
- package/hooks/hypo-auto-minimal-crystallize.mjs +23 -11
- package/hooks/hypo-shared.mjs +96 -14
- package/package.json +6 -1
- package/scripts/check-bilingual.mjs +49 -11
- package/scripts/check-tracker-ids.mjs +60 -1
- package/scripts/crystallize.mjs +275 -39
- package/scripts/lib/changelog-classify.mjs +216 -0
- package/scripts/lib/check-bilingual.mjs +125 -22
- package/scripts/lib/check-tracker-ids.mjs +19 -0
- package/scripts/lib/project-create.mjs +23 -5
- package/scripts/lib/schema-vocab.mjs +105 -1
- package/scripts/lint.mjs +9 -1
- package/scripts/weekly-report.mjs +9 -3
- package/skills/crystallize/SKILL.md +30 -2
- package/templates/SCHEMA.md +11 -3
- package/templates/hypo-config.md +1 -1
- package/templates/hypo-guide.md +4 -1
- package/scripts/bump-version.mjs +0 -77
- package/scripts/smoke-pack.mjs +0 -261
- package/scripts/smoke-plugin.mjs +0 -194
package/commands/feedback.md
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
|
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>" \
|
package/commands/graph.md
CHANGED
|
@@ -12,9 +12,9 @@ You are running `/hypo:graph`. Generate a link dependency graph from wiki pages.
|
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
-
## Step 1 —
|
|
15
|
+
## Step 1 — Run script
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
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.
|
|
18
18
|
|
|
19
19
|
If the user specified a Hypomnema directory, pass it as `--hypo-dir="<path>"`. Otherwise omit the flag.
|
|
20
20
|
|
|
@@ -23,7 +23,7 @@ If the user specified a Hypomnema directory, pass it as `--hypo-dir="<path>"`. O
|
|
|
23
23
|
## Step 2 — Run the graph script
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
node
|
|
26
|
+
node ${CLAUDE_PLUGIN_ROOT}/scripts/graph.mjs \
|
|
27
27
|
[--hypo-dir="<path>"] \
|
|
28
28
|
[--format=json|mermaid|dot] \
|
|
29
29
|
[--min-edges=<n>]
|
package/commands/ingest.md
CHANGED
|
@@ -27,18 +27,20 @@ Do **not** fetch the URL or read the file yet — the privacy guard in Step 2 mu
|
|
|
27
27
|
|
|
28
28
|
## Step 2 — Privacy guard (`.hypoignore`)
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
The script paths below 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.
|
|
31
|
+
|
|
32
|
+
Refuse to ingest secrets (`.env`, SSH keys, credentials) before they ever reach `sources/`. Run the guard for **both** the input path and the destination path:
|
|
31
33
|
|
|
32
34
|
1. **If the source is a file path**, check it (use an absolute path):
|
|
33
35
|
|
|
34
36
|
```bash
|
|
35
|
-
node
|
|
37
|
+
node ${CLAUDE_PLUGIN_ROOT}/scripts/ingest.mjs [--hypo-dir="<path>"] --check="<absolute-input-path>"
|
|
36
38
|
```
|
|
37
39
|
|
|
38
40
|
2. **Always** check the destination `sources/<slug>.<ext>`:
|
|
39
41
|
|
|
40
42
|
```bash
|
|
41
|
-
node
|
|
43
|
+
node ${CLAUDE_PLUGIN_ROOT}/scripts/ingest.mjs [--hypo-dir="<path>"] --check="sources/<slug>.<ext>"
|
|
42
44
|
```
|
|
43
45
|
|
|
44
46
|
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.
|
|
@@ -50,7 +52,7 @@ If either command exits non-zero, **stop**: surface the `Refused: ...` message t
|
|
|
50
52
|
Run the ingest helper to surface existing orphaned sources:
|
|
51
53
|
|
|
52
54
|
```bash
|
|
53
|
-
node
|
|
55
|
+
node ${CLAUDE_PLUGIN_ROOT}/scripts/ingest.mjs [--hypo-dir="<path>"]
|
|
54
56
|
```
|
|
55
57
|
|
|
56
58
|
If there are orphaned sources already in `sources/`, ask: "There are N unprocessed sources — do you want to ingest one of those instead?"
|
package/commands/init.md
CHANGED
|
@@ -43,10 +43,12 @@ Ask the following questions **one at a time**. Use the default if the user press
|
|
|
43
43
|
|
|
44
44
|
## Step 2a — From Remote (skip wizard) {#step-2a}
|
|
45
45
|
|
|
46
|
+
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.
|
|
47
|
+
|
|
46
48
|
If the user provided `--from-remote <url>`, run:
|
|
47
49
|
|
|
48
50
|
```bash
|
|
49
|
-
node
|
|
51
|
+
node ${CLAUDE_PLUGIN_ROOT}/scripts/init.mjs \
|
|
50
52
|
--from-remote="<url>" \
|
|
51
53
|
--hypo-dir="<hypo-dir>" \
|
|
52
54
|
[--no-hooks] \
|
|
@@ -62,11 +64,11 @@ node <package-root>/scripts/init.mjs \
|
|
|
62
64
|
|
|
63
65
|
## Step 2 — Run the init script (new wiki)
|
|
64
66
|
|
|
65
|
-
|
|
67
|
+
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.
|
|
66
68
|
Then run:
|
|
67
69
|
|
|
68
70
|
```bash
|
|
69
|
-
node
|
|
71
|
+
node ${CLAUDE_PLUGIN_ROOT}/scripts/init.mjs \
|
|
70
72
|
--hypo-dir="<hypo-dir>" \
|
|
71
73
|
[--no-hooks] \
|
|
72
74
|
[--codex] \
|
package/commands/lint.md
CHANGED
|
@@ -14,9 +14,9 @@ You are running `/hypo:lint`. Validate all wiki pages for frontmatter correctnes
|
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
-
## Step 1 —
|
|
17
|
+
## Step 1 — Run script
|
|
18
18
|
|
|
19
|
-
|
|
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 and the script resolves the Hypomnema root automatically via `HYPO_DIR` → `hypo-config.md` scan → `~/hypomnema`.
|
|
22
22
|
|
|
@@ -25,7 +25,7 @@ If the user specified a Hypomnema directory, pass it as `--hypo-dir="<path>"`. O
|
|
|
25
25
|
## Step 2 — Run lint
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
node
|
|
28
|
+
node ${CLAUDE_PLUGIN_ROOT}/scripts/lint.mjs [--hypo-dir="<path>"] [--json] [--fix]
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
Options:
|
package/commands/query.md
CHANGED
|
@@ -18,14 +18,14 @@ Ask the user what they want to know if it was not provided in the command invoca
|
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
-
## Step 2 —
|
|
21
|
+
## Step 2 — Search
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
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.
|
|
24
24
|
|
|
25
25
|
Run full-text search:
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
node
|
|
28
|
+
node ${CLAUDE_PLUGIN_ROOT}/scripts/query.mjs \
|
|
29
29
|
--q="<query terms>" \
|
|
30
30
|
[--hypo-dir="<path>"] \
|
|
31
31
|
[--limit=10]
|
package/commands/rename.md
CHANGED
|
@@ -14,9 +14,9 @@ You are running `/hypo:rename`. Move a page or directory and content-aware rewri
|
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
-
## Step 1 —
|
|
17
|
+
## Step 1 — Run script
|
|
18
18
|
|
|
19
|
-
|
|
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
|
|
|
@@ -27,7 +27,7 @@ If the user specified a Hypomnema directory, pass it as `--hypo-dir="<path>"`. O
|
|
|
27
27
|
Always run the dry-run (no `--apply`) before writing anything:
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
node
|
|
30
|
+
node ${CLAUDE_PLUGIN_ROOT}/scripts/rename.mjs \
|
|
31
31
|
[--hypo-dir="<path>"] \
|
|
32
32
|
--from=<slug|rel|dir> \
|
|
33
33
|
--to=<slug|rel|dir> \
|
|
@@ -61,7 +61,7 @@ If the result is `ok: false`:
|
|
|
61
61
|
Once the user confirms the dry-run looks right, re-run with `--apply`:
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
|
-
node
|
|
64
|
+
node ${CLAUDE_PLUGIN_ROOT}/scripts/rename.mjs \
|
|
65
65
|
[--hypo-dir="<path>"] \
|
|
66
66
|
--from=<slug|rel|dir> \
|
|
67
67
|
--to=<slug|rel|dir> \
|
package/commands/resume.md
CHANGED
|
@@ -14,12 +14,14 @@ You are running `/hypo:resume`. Load the session state for an active project and
|
|
|
14
14
|
|
|
15
15
|
## Step 1 — Resolve project
|
|
16
16
|
|
|
17
|
-
If the user named a project in the command invocation, use that. Otherwise,
|
|
17
|
+
If the user named a project in the command invocation, use that. Otherwise, run:
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
node
|
|
20
|
+
node ${CLAUDE_PLUGIN_ROOT}/scripts/resume.mjs [--hypo-dir="<path>"] [--project=<name>]
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
The plugin harness expands `${CLAUDE_PLUGIN_ROOT}` to this package's absolute path before you see it, so run the command 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.
|
|
24
|
+
|
|
23
25
|
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
26
|
|
|
25
27
|
---
|
package/commands/stats.md
CHANGED
|
@@ -13,9 +13,9 @@ You are running `/hypo:stats`. Display a summary of wiki health and activity.
|
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
-
## Step 1 —
|
|
16
|
+
## Step 1 — Run script
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
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.
|
|
19
19
|
|
|
20
20
|
If the user specified a Hypomnema directory, pass it as `--hypo-dir="<path>"`. Otherwise omit the flag.
|
|
21
21
|
|
|
@@ -24,7 +24,7 @@ If the user specified a Hypomnema directory, pass it as `--hypo-dir="<path>"`. O
|
|
|
24
24
|
## Step 2 — Run the stats script
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
node
|
|
27
|
+
node ${CLAUDE_PLUGIN_ROOT}/scripts/stats.mjs [--hypo-dir="<path>"] [--json]
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
---
|
package/commands/upgrade.md
CHANGED
|
@@ -12,9 +12,9 @@ You are running `/hypo:upgrade`. Check if the installed Hypomnema wiki is out of
|
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
-
## Step 1 —
|
|
15
|
+
## Step 1 — Run script
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
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.
|
|
18
18
|
|
|
19
19
|
If the user specified a Hypomnema directory, pass it as `--hypo-dir="<path>"`. Otherwise omit the flag.
|
|
20
20
|
|
|
@@ -23,7 +23,7 @@ If the user specified a Hypomnema directory, pass it as `--hypo-dir="<path>"`. O
|
|
|
23
23
|
## Step 2 — Run upgrade check
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
node
|
|
26
|
+
node ${CLAUDE_PLUGIN_ROOT}/scripts/upgrade.mjs [--hypo-dir="<path>"]
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
Show the output verbatim.
|
|
@@ -54,7 +54,7 @@ If there is anything to update, ask the user:
|
|
|
54
54
|
|
|
55
55
|
- If **yes** → run with `--apply`:
|
|
56
56
|
```bash
|
|
57
|
-
node
|
|
57
|
+
node ${CLAUDE_PLUGIN_ROOT}/scripts/upgrade.mjs [--hypo-dir="<path>"] --apply
|
|
58
58
|
```
|
|
59
59
|
- If **no** → tell the user they can apply later by running `/hypo:upgrade` again.
|
|
60
60
|
|
package/commands/verify.md
CHANGED
|
@@ -11,12 +11,12 @@ You are running `/hypo:verify`. Audit wiki pages for overdue or missing `verify_
|
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
-
## Step 1 —
|
|
14
|
+
## Step 1 — Run
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
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.
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
node
|
|
19
|
+
node ${CLAUDE_PLUGIN_ROOT}/scripts/verify.mjs [--hypo-dir="<path>"] [--file=<path>]
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
Options:
|
package/docs/CONTRIBUTING.md
CHANGED
|
@@ -217,12 +217,92 @@ Before opening:
|
|
|
217
217
|
4. If you changed a template or `init` flow, a fresh `init` produces the expected vault structure.
|
|
218
218
|
5. README / ARCHITECTURE / docs are updated to match.
|
|
219
219
|
|
|
220
|
-
Open the PR against `main`.
|
|
220
|
+
Open the PR against `main`. The body is **bilingual**: write the full description twice, once under a `# English` heading and once under a `# 한국어` heading, each carrying the same sections. The `## Changelog` and `## Checklist` blocks are language-neutral, so they appear once, after both language blocks. Do **not** add any tool-attribution footer (no "Generated with ..." line) to the body.
|
|
221
221
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
- **
|
|
225
|
-
- **
|
|
222
|
+
Each language block includes:
|
|
223
|
+
|
|
224
|
+
- **What changed** / **변경 내용**: short summary
|
|
225
|
+
- **Why** / **이유**: the user-visible motivation
|
|
226
|
+
- **How** / **방법**: approach notes that aren't obvious from the diff
|
|
227
|
+
- **Manual verification** / **수동 검증**: anything the test suite cannot cover
|
|
228
|
+
- **Migration notes** / **마이그레이션 노트**: if upgrading existing installs needs special handling (else "None")
|
|
229
|
+
|
|
230
|
+
After both blocks, language-neutral:
|
|
231
|
+
|
|
232
|
+
- **Changelog**: one English line plus one Korean line if the change is user-visible (see CHANGELOG conventions below)
|
|
233
|
+
- **Checklist**: the boxes from the PR template
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## CHANGELOG conventions
|
|
238
|
+
|
|
239
|
+
`CHANGELOG.md` is the source of truth for release history. It follows a fixed section model, and contributors feed it through the `## Changelog` block in the PR template rather than editing `CHANGELOG.md` directly. The release collector and the maintainer assemble the final entries at release time.
|
|
240
|
+
|
|
241
|
+
### PR title vs. merge commit
|
|
242
|
+
|
|
243
|
+
- **PR title**: Conventional Commits plus a scope, e.g. `feat(feedback): add failure_type enum`. The type drives the CHANGELOG section (see the classification table below).
|
|
244
|
+
- **Merge commit**: the squash-merge subject carries the PR number (`#123`). That is where `#N` comes from, not the PR title. The two conventions stay separate.
|
|
245
|
+
- Internal tracker ids (`FEAT-`, `IMPR-`, `ISSUE-`, `PRAC-`) may appear in your local notes and in source or workflow comments (an internal reference, like an ADR anchor), but never on the published changelog and release surface: not in the CHANGELOG body, not in the PR `## Changelog` block, not in a tag annotation, not in a GitHub Release. The only identifier that ships in those is the PR number `#N`. `check-tracker-ids --tag` gates the tag body; the migration keeps the CHANGELOG body clean.
|
|
246
|
+
|
|
247
|
+
### The `## Changelog` block
|
|
248
|
+
|
|
249
|
+
If a change is user-visible, fill the `## Changelog` block in the PR body with one English line and one Korean line:
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
## Changelog
|
|
253
|
+
|
|
254
|
+
- EN: Feedback pages accept an optional `failure_type` so recurring mistakes are visible.
|
|
255
|
+
- KO: 피드백 페이지에 선택적 `failure_type`를 달아 반복되는 실수를 집계로 볼 수 있습니다.
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
- Reference the PR by number only (`#123`). No internal tracker ids on this surface.
|
|
259
|
+
- No em dashes; use a colon, comma, or parentheses.
|
|
260
|
+
- Internal-only changes (a refactor with no user-visible effect, test-only, CI plumbing) write `None` and skip the lines.
|
|
261
|
+
|
|
262
|
+
### Section model
|
|
263
|
+
|
|
264
|
+
Each version block in `CHANGELOG.md` is ordered, top to bottom:
|
|
265
|
+
|
|
266
|
+
1. Optional `> [!IMPORTANT]` migration or breaking callout.
|
|
267
|
+
2. `### New Features`, `### Bug Fixes`, `### Chores`: present only when that version has a user-relevant entry of that kind. An empty section is omitted. Keep each entry to one compact line; split or trim anything that runs to multiple sentences. Describe only what a user sees: purely internal work (release tooling, contributor docs, a refactor with no user-visible effect) gets no prose entry and lives in the `### Changelog` index alone.
|
|
268
|
+
3. `### Changelog`: the PR-link index plus contributors. Always present. Language-neutral. It lists every merged PR, internal ones included.
|
|
269
|
+
|
|
270
|
+
At and after the v1.2.0 cutoff, each non-empty gated section (`New Features`, `Bug Fixes`, `Chores`) splits its content into `#### English` then `#### 한국어`, in that order:
|
|
271
|
+
|
|
272
|
+
```
|
|
273
|
+
### New Features
|
|
274
|
+
#### English
|
|
275
|
+
- Feedback pages accept an optional `failure_type`. (#141)
|
|
276
|
+
#### 한국어
|
|
277
|
+
- 피드백 페이지가 선택적 `failure_type`를 받습니다. (#141)
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Versions below the v1.2.0 cutoff (1.0.0, 1.0.1, 1.1.0) are English-only: the English body sits directly under the section header with no `####` sub-blocks. Korean is not back-filled for those releases.
|
|
281
|
+
|
|
282
|
+
The `### Changelog` index is language-neutral, one merged PR per line:
|
|
283
|
+
|
|
284
|
+
```
|
|
285
|
+
### Changelog
|
|
286
|
+
- #141 feedback failure_type classification
|
|
287
|
+
- #140 invalid-YAML lint guard
|
|
288
|
+
Contributors: @handle
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Each line is `- #N <short title>`, no em dash. The `Contributors:` line lists that version's PR authors, de-duplicated; the release collector fills the handles from the GitHub API.
|
|
292
|
+
|
|
293
|
+
A `### Known Issues` or `### Notes` block, when a version has one, is a trailing note (a caveat, not a change). It is not one of the gated sections, so it carries no `####` sub-blocks even at or after the cutoff; bilingual text there is recommended, not enforced.
|
|
294
|
+
|
|
295
|
+
### Classification
|
|
296
|
+
|
|
297
|
+
The section is decided by change kind, with the Conventional Commit type as the default and content as the override:
|
|
298
|
+
|
|
299
|
+
| Input | Section |
|
|
300
|
+
|---|---|
|
|
301
|
+
| `feat:` / `FEAT-` | New Features |
|
|
302
|
+
| `fix:` / `ISSUE-` | Bug Fixes |
|
|
303
|
+
| `chore:` / `refactor:` / `docs:` / `ci:` / `perf:` / `IMPR-` / `PRAC-` | Chores |
|
|
304
|
+
|
|
305
|
+
Chores is defined by kind, not by visibility: improvements (`IMPR`), refactors, and release or internal cleanup all land in Chores even when user-visible. The external changelog highlights only New Features and Bug Fixes; everything else is a Chore.
|
|
226
306
|
|
|
227
307
|
---
|
|
228
308
|
|
|
@@ -239,14 +319,16 @@ itself). The sequence below is that same checklist, and is the authoritative
|
|
|
239
319
|
in-repo reference; follow it whether or not you have the `/ship` convenience
|
|
240
320
|
command.
|
|
241
321
|
|
|
242
|
-
Every Hypomnema release must carry
|
|
322
|
+
Every Hypomnema release must carry Korean alongside the English body
|
|
243
323
|
in **both** the CHANGELOG section AND the git tag annotation. The release
|
|
244
|
-
workflow enforces this with `scripts/check-bilingual.mjs`; lightweight
|
|
245
|
-
a missing
|
|
324
|
+
workflow enforces this with `scripts/check-bilingual.mjs`; a lightweight tag, or
|
|
325
|
+
a gated CHANGELOG section missing its `#### 한국어` sub-block, will block `npm publish`. It also requires the
|
|
246
326
|
release version to appear in **both** `README.md` and `README.ko.md`
|
|
247
327
|
(`scripts/check-readme-version.mjs`) — the floor that stops the README reconcile
|
|
248
328
|
from being dropped.
|
|
249
329
|
|
|
330
|
+
Prerequisite: the changelog collector in step 2 reads merged-PR data through the GitHub CLI, so have `gh` installed and authenticated (`gh auth status`) before you start. It is a maintainer-only release script and is not shipped to npm.
|
|
331
|
+
|
|
250
332
|
```bash
|
|
251
333
|
# 1. Bump the version across package.json, plugin.json, marketplace.json,
|
|
252
334
|
# and templates/hypo-config.md. Takes a concrete semver (not patch/minor/major).
|
|
@@ -256,8 +338,14 @@ node scripts/bump-version.mjs <new-semver> # e.g. 1.2.2 or 1.3.0-rc.1
|
|
|
256
338
|
# version-consistency gate stay green (the lock carries the version twice).
|
|
257
339
|
npm install --package-lock-only
|
|
258
340
|
|
|
259
|
-
# 2.
|
|
260
|
-
#
|
|
341
|
+
# 2. Draft the new CHANGELOG.md section from the merged PRs' `## Changelog`
|
|
342
|
+
# blocks (see CHANGELOG conventions above). The collector prints a draft for
|
|
343
|
+
# the range since the last tag; paste it, then finalize the wording by hand,
|
|
344
|
+
# dropping any entry that is not user-relevant. --strict fails if any PR lacks
|
|
345
|
+
# a usable block.
|
|
346
|
+
node scripts/collect-changelog.mjs --strict # maintainer-only; not shipped to npm
|
|
347
|
+
# Each gated section (New Features / Bug Fixes / Chores) MUST carry both a
|
|
348
|
+
# "#### English" and a "#### 한국어" sub-block; check:bilingual enforces it.
|
|
261
349
|
$EDITOR CHANGELOG.md
|
|
262
350
|
|
|
263
351
|
# 3. Reconcile BOTH READMEs — add a v<version> sentence to the rolling version
|
|
@@ -269,7 +357,7 @@ $EDITOR README.md README.ko.md
|
|
|
269
357
|
npm test # unit suite
|
|
270
358
|
npm run lint # vault linter
|
|
271
359
|
npm run check:versions # all version-carrying files (incl. package-lock) agree
|
|
272
|
-
npm run check:bilingual # CHANGELOG section has
|
|
360
|
+
npm run check:bilingual # each gated CHANGELOG section has #### English + #### 한국어
|
|
273
361
|
npm run check:readme # v<version> present in BOTH READMEs
|
|
274
362
|
npm run smoke:plugin # plugin manifest + hooks/commands/skills load-valid
|
|
275
363
|
npm run smoke-pack # packed tarball installs and resolves
|
|
@@ -281,17 +369,19 @@ git add package.json package-lock.json .claude-plugin/ templates/hypo-config.md
|
|
|
281
369
|
git commit -m "chore: release v<version>"
|
|
282
370
|
# Then open the release PR, pass review + green CI, and squash-merge to main.
|
|
283
371
|
|
|
284
|
-
# 6. Tag the merge commit with an ANNOTATED tag
|
|
372
|
+
# 6. Tag the merge commit with an ANNOTATED tag, never a lightweight tag.
|
|
285
373
|
# Annotation body shape: English summary, then "---" on its own line,
|
|
286
|
-
# then a Korean summary block.
|
|
374
|
+
# then a Korean summary block. The GitHub Release republishes this body
|
|
375
|
+
# verbatim, so keep it on the same public surface as the CHANGELOG: PR
|
|
376
|
+
# numbers (#N) only, no internal tracker ids (check-tracker-ids --tag gates it).
|
|
287
377
|
git tag -a v<version> -m "$(cat <<'EOF'
|
|
288
|
-
Hypomnema v<version
|
|
378
|
+
Hypomnema v<version>: <one-line English summary>
|
|
289
379
|
|
|
290
|
-
<a few lines of English body
|
|
380
|
+
<a few lines of English body: what shipped, links, etc.>
|
|
291
381
|
|
|
292
382
|
---
|
|
293
383
|
|
|
294
|
-
Hypomnema v<version
|
|
384
|
+
Hypomnema v<version>: <한 줄 한글 요약>
|
|
295
385
|
|
|
296
386
|
<몇 줄의 한글 요약 본문.>
|
|
297
387
|
EOF
|
|
@@ -300,6 +390,7 @@ EOF
|
|
|
300
390
|
# 7. Rehearse the release locally (same checks CI runs against the tag)
|
|
301
391
|
node scripts/check-bilingual.mjs --tag v<version>
|
|
302
392
|
node scripts/check-versions.mjs --tag v<version>
|
|
393
|
+
node scripts/check-tracker-ids.mjs --tag v<version> # no tracker ids leak into the tag body
|
|
303
394
|
npm publish --dry-run --access public # packs + prepublishOnly, NO registry PUT
|
|
304
395
|
|
|
305
396
|
# 8. Push the SPECIFIC tag alone — NOT --tags (that would push stale local tags
|
|
@@ -59,21 +59,33 @@ function emitContinue() {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
function emitBlock(sessionId, transcriptPath, gate = null) {
|
|
62
|
-
// One-line
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
62
|
+
// One-line recovery action. The gate-precise branches below name an EXACT
|
|
63
|
+
// command so "only the marker is missing" stays a one-shot fix — but that
|
|
64
|
+
// command must be a runnable `node <pkg>/scripts/crystallize.mjs` invocation,
|
|
65
|
+
// never a bare `crystallize` (a package.json `bin` that is NOT on PATH in a
|
|
66
|
+
// plugin install → `command not found`). When PKG_ROOT is
|
|
67
|
+
// unresolved we cannot build that path, so fall back to the /hypo:crystallize
|
|
68
|
+
// skill, which resolves its own package root (the same alias the generic
|
|
69
|
+
// branch uses). Passing --session-id writes the per-session marker that clears
|
|
70
|
+
// this block. Surface the transcript path so the close can pass
|
|
71
|
+
// --transcript-path=<path>, which scopes the marker's lint gate to this
|
|
72
|
+
// session's own files (Bug A coherence: a marker written without lint would
|
|
73
|
+
// only let Stop pass for /compact to immediately re-block on the same errors).
|
|
74
|
+
// Quote the paths so the printed command stays copy-paste runnable even when
|
|
75
|
+
// an install/transcript path contains spaces (display text only — never exec'd
|
|
76
|
+
// here).
|
|
77
|
+
const transcriptHint = transcriptPath ? ` --transcript-path="${transcriptPath}"` : '';
|
|
78
|
+
const cliBase = PKG_ROOT ? `node "${join(PKG_ROOT, 'scripts', 'crystallize.mjs')}"` : null;
|
|
79
|
+
const markCmd = cliBase
|
|
80
|
+
? `${cliBase} --mark-session-closed --session-id=${sessionId}${transcriptHint}`
|
|
81
|
+
: `/hypo:crystallize (session_id=${sessionId}${transcriptHint})`;
|
|
72
82
|
// The log-only escape hatch for a non-project (wiki/tooling-only)
|
|
73
83
|
// session. Offered ONLY as an explicit alternative when a close blocker is
|
|
74
84
|
// present — never as the default recovery, so a real project session is not
|
|
75
85
|
// taught to bypass the ADR 0043 close invariant (codex design Finding 3).
|
|
76
|
-
const logOnlyCmd =
|
|
86
|
+
const logOnlyCmd = cliBase
|
|
87
|
+
? `${cliBase} --mark-session-closed --log-only --session-id=${sessionId}${transcriptHint}`
|
|
88
|
+
: `/hypo:crystallize --log-only (session_id=${sessionId}${transcriptHint})`;
|
|
77
89
|
// ADR 0047: refine the message with the read-only /compact gate result.
|
|
78
90
|
// - gate green → the close is compact-ready and ONLY the marker is missing
|
|
79
91
|
// (the hand-edit close case: files Written + committed directly, bypassing
|