hypomnema 1.4.1 → 1.5.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.
Files changed (69) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.ko.md +1 -1
  4. package/README.md +1 -1
  5. package/commands/audit.md +1 -1
  6. package/commands/crystallize.md +11 -9
  7. package/commands/doctor.md +1 -1
  8. package/commands/feedback.md +2 -2
  9. package/commands/graph.md +1 -1
  10. package/commands/ingest.md +1 -1
  11. package/commands/init.md +2 -2
  12. package/commands/lint.md +1 -1
  13. package/commands/query.md +1 -1
  14. package/commands/rename.md +1 -1
  15. package/commands/resume.md +1 -1
  16. package/commands/stats.md +1 -1
  17. package/commands/uninstall.md +4 -2
  18. package/commands/upgrade.md +1 -1
  19. package/commands/verify.md +1 -1
  20. package/docs/ARCHITECTURE.md +2 -2
  21. package/docs/CONTRIBUTING.md +20 -12
  22. package/hooks/hypo-auto-commit.mjs +2 -2
  23. package/hooks/hypo-auto-minimal-crystallize.mjs +30 -18
  24. package/hooks/hypo-compact-guard.mjs +2 -2
  25. package/hooks/hypo-cwd-change.mjs +27 -37
  26. package/hooks/hypo-personal-check.mjs +37 -22
  27. package/hooks/hypo-session-end.mjs +1 -1
  28. package/hooks/hypo-session-record.mjs +2 -2
  29. package/hooks/hypo-session-start.mjs +34 -40
  30. package/hooks/hypo-shared.mjs +364 -82
  31. package/hooks/version-check.mjs +1 -1
  32. package/package.json +5 -1
  33. package/scripts/check-tracker-ids.mjs +69 -31
  34. package/scripts/crystallize.mjs +322 -70
  35. package/scripts/doctor.mjs +7 -7
  36. package/scripts/feedback-sync.mjs +5 -5
  37. package/scripts/feedback.mjs +9 -10
  38. package/scripts/init.mjs +7 -7
  39. package/scripts/lib/check-tracker-ids.mjs +90 -32
  40. package/scripts/lib/design-history-stale.mjs +1 -1
  41. package/scripts/lib/extensions.mjs +7 -7
  42. package/scripts/lib/failure-type.mjs +1 -1
  43. package/scripts/lib/feedback-scope.mjs +1 -1
  44. package/scripts/lib/project-create.mjs +25 -7
  45. package/scripts/lib/schema-vocab.mjs +105 -1
  46. package/scripts/lib/template-schema-version.mjs +1 -1
  47. package/scripts/lib/wd-match.mjs +181 -0
  48. package/scripts/lib/wikilink.mjs +1 -1
  49. package/scripts/lint.mjs +14 -6
  50. package/scripts/rename.mjs +1 -1
  51. package/scripts/resume.mjs +20 -22
  52. package/scripts/session-audit.mjs +1 -1
  53. package/scripts/stats.mjs +3 -3
  54. package/scripts/uninstall.mjs +3 -3
  55. package/scripts/upgrade.mjs +17 -18
  56. package/skills/crystallize/SKILL.md +16 -8
  57. package/skills/graph/SKILL.md +2 -2
  58. package/skills/ingest/SKILL.md +4 -4
  59. package/skills/lint/SKILL.md +2 -2
  60. package/skills/query/SKILL.md +2 -2
  61. package/skills/verify/SKILL.md +2 -2
  62. package/templates/SCHEMA.md +12 -4
  63. package/templates/hypo-config.md +1 -1
  64. package/templates/hypo-guide.md +24 -15
  65. package/templates/projects/_template/hot.md +1 -1
  66. package/scripts/fix-status-verify.mjs +0 -256
  67. package/scripts/lib/adr-corpus.mjs +0 -79
  68. package/scripts/lib/fix-manifest.mjs +0 -109
  69. package/scripts/lib/fix-status-verify.mjs +0 -439
@@ -249,7 +249,7 @@ export function isOptedOut(env = process.env) {
249
249
  return Boolean(env.HYPO_NO_UPDATE_CHECK || env.NO_UPDATE_NOTIFIER || env.CI);
250
250
  }
251
251
 
252
- // ── stale-sibling detection (ADR 0038) ───────────────────────────────────────
252
+ // ── stale-sibling detection ───────────────────────────────────────────────────
253
253
  //
254
254
  // A second, OLDER Hypomnema can sit on $PATH (e.g. a stale `npm i -g hypomnema`)
255
255
  // while a newer copy owns the active hooks. The CLI bin (`hypomnema`) then routes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypomnema",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "LLM-native personal wiki system for Claude Code",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -14,6 +14,10 @@
14
14
  "!scripts/bump-version.mjs",
15
15
  "!scripts/smoke-pack.mjs",
16
16
  "!scripts/smoke-plugin.mjs",
17
+ "!scripts/fix-status-verify.mjs",
18
+ "!scripts/lib/fix-status-verify.mjs",
19
+ "!scripts/lib/fix-manifest.mjs",
20
+ "!scripts/lib/adr-corpus.mjs",
17
21
  "commands/",
18
22
  "hooks/",
19
23
  "skills/",
@@ -1,13 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * check-tracker-ids.mjs — CLI gate: no wiki-internal tracker IDs (ISSUE-N,
4
- * fix #N) in OSS-public artifacts.
4
+ * fix #N, FEAT-N, IMPR-N, PRAC-N) in OSS-public artifacts.
5
5
  *
6
6
  * Rule source: CLAUDE.md learned_behaviors (no-internal-tracker-ids-in-oss-
7
7
  * artifacts, 2026-06-09). The repo ships through npm + a Claude Code plugin;
8
- * a `fix #N` / `ISSUE-N` in any shipped file or in README/CHANGELOG is a
9
- * dangling pointer into the maintainer's PRIVATE wiki tracker. GitHub refs
10
- * (`PR #N`, `(#N)`, `#N`, issue URLs) are legitimate and never flagged.
8
+ * an `ISSUE-N` / `fix #N` / `FEAT-N` / `IMPR-N` / `PRAC-N` in any shipped file or
9
+ * in README/CHANGELOG is a dangling pointer into the maintainer's PRIVATE wiki
10
+ * tracker. GitHub refs (`PR #N`, `(#N)`, `#N`, issue URLs) are legitimate and
11
+ * never flagged.
11
12
  *
12
13
  * Modes:
13
14
  * --all (default) Walk the public-artifact scope and scan every text
@@ -31,14 +32,16 @@
31
32
  * auto-ships it) + shipped trees commands/ hooks/ scripts/ skills/ templates/
32
33
  * docs/ .github/ .claude-plugin/. Excluded: tests/ and qa-runs/ (internal
33
34
  * maintainer artifacts — a tracker id in a test description aids traceability
34
- * and never reaches an installed user), node_modules/, .git/. The checker's OWN
35
- * sources are scanned (NOT exempt); their examples use `N` placeholders so they
36
- * stay clean.
35
+ * and never reaches an installed user), node_modules/, .git/, and the
36
+ * fix-status-verify subsystem (EXCLUDED_FILES maintainer-only, carries wiki
37
+ * `decisions/` paths as runtime data, un-shipped from the npm package). The
38
+ * checker's OWN sources are scanned (NOT exempt); their examples use `N`
39
+ * placeholders so they stay clean.
37
40
  *
38
- * ADR scope (narrower): README.md, README.ko.md, and docs/ additionally block
39
- * `ADR NNNN` / `decisions/NNNN` wiki-ADR pointers (USER_FACING_PATTERNS). Shipped
40
- * code comments and CHANGELOG history keep their ADR anchors, so this set is
41
- * applied per-file via patternsFor() only inside that doc surface.
41
+ * ADR scope: `ADR NNNN` / `decisions/NNNN` wiki-ADR pointers (DECISION_PATTERNS)
42
+ * are blocked everywhere in scope EXCEPT CHANGELOG.md, whose version history
43
+ * legitimately cites the decision behind a release line. patternsFor() applies the
44
+ * broader set to every in-scope file but the CHANGELOG.
42
45
  */
43
46
 
44
47
  import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs';
@@ -50,7 +53,7 @@ import {
50
53
  stripScissors,
51
54
  messageHasGitTemplate,
52
55
  BLOCKED_PATTERNS,
53
- USER_FACING_PATTERNS,
56
+ DECISION_PATTERNS,
54
57
  TAG_BODY_PATTERNS,
55
58
  } from './lib/check-tracker-ids.mjs';
56
59
  import {
@@ -70,7 +73,8 @@ const REPO_ROOT = process.env.CHECK_TRACKER_ROOT || join(__dirname, '..');
70
73
 
71
74
  const RULE_REF =
72
75
  'Rule: CLAUDE.md learned_behaviors (no-internal-tracker-ids-in-oss-artifacts). ' +
73
- 'OSS-public artifacts must not reference the private wiki tracker (ISSUE-N / fix #N). ' +
76
+ 'OSS-public artifacts must not reference the private wiki tracker ' +
77
+ '(ISSUE-N / fix #N / FEAT-N / IMPR-N / PRAC-N). ' +
74
78
  'Use a GitHub ref (#N / PR #N) or drop the reference.';
75
79
 
76
80
  // Top-level public-artifact entry points. Files are scanned directly; dirs are
@@ -94,15 +98,49 @@ const SCOPE_DIRS = [
94
98
  // and never reaches an installed user). The checker's OWN sources are NOT
95
99
  // excluded — they use `N` placeholders in their examples so they scan clean.
96
100
  const EXCLUDED_DIRS = new Set(['node_modules', '.git', 'tests', 'qa-runs']);
97
- const EXCLUDED_FILES = new Set();
101
+ // The fix-status-verify subsystem (run only via `npm run fix:verify`, never by a
102
+ // shipped command/hook/skill) is a maintainer evidence-verification tool. Its
103
+ // manifest carries `decisions/NNNN` wiki paths as RUNTIME DATA (resolved against
104
+ // the maintainer's local wiki), so the anchors cannot be stripped the way a
105
+ // comment can. It is removed from the npm package (package.json `files`) and
106
+ // excluded here so the gate does not flag its load-bearing data.
107
+ // Stored POSIX-style ('/'); paths are normalized before lookup (see toPosix).
108
+ const EXCLUDED_FILES = new Set([
109
+ 'scripts/fix-status-verify.mjs',
110
+ 'scripts/lib/fix-status-verify.mjs',
111
+ 'scripts/lib/fix-manifest.mjs',
112
+ 'scripts/lib/adr-corpus.mjs',
113
+ ]);
98
114
 
99
115
  // Only text artifacts. Binary / lockfiles add noise and never carry prose refs.
100
- const TEXT_EXT = new Set(['.md', '.mjs', '.js', '.cjs', '.json', '.yml', '.yaml', '.sh', '.txt']);
116
+ // .svg is included because the shipped docs/assets/ logos are hand-authored XML
117
+ // text whose <title>/<desc>/comment fields could carry a dangling wiki pointer.
118
+ const TEXT_EXT = new Set([
119
+ '.md',
120
+ '.mjs',
121
+ '.js',
122
+ '.cjs',
123
+ '.json',
124
+ '.yml',
125
+ '.yaml',
126
+ '.sh',
127
+ '.txt',
128
+ '.svg',
129
+ ]);
130
+
131
+ // Normalize OS separators to '/' so the two scan modes classify a path the same
132
+ // way on every host: --all builds relPath via relative() (platform sep, so '\' on
133
+ // Windows) while --staged takes git's output (always '/'). Without this, a Windows
134
+ // --staged run would neither exclude the verifier files nor recognize scope dirs.
135
+ // No-op on POSIX (sep is already '/').
136
+ function toPosix(relPath) {
137
+ return sep === '/' ? relPath : relPath.split(sep).join('/');
138
+ }
101
139
 
102
140
  function isExcludedRel(relPath) {
103
- const parts = relPath.split(sep);
104
- if (parts.some((p) => EXCLUDED_DIRS.has(p))) return true;
105
- if (EXCLUDED_FILES.has(relPath)) return true;
141
+ const p = toPosix(relPath);
142
+ if (p.split('/').some((seg) => EXCLUDED_DIRS.has(seg))) return true;
143
+ if (EXCLUDED_FILES.has(p)) return true;
106
144
  return false;
107
145
  }
108
146
 
@@ -116,22 +154,22 @@ function isTextFile(p) {
116
154
  function isInScope(relPath) {
117
155
  if (isExcludedRel(relPath)) return false;
118
156
  if (!isTextFile(relPath)) return false;
119
- if (SCOPE_FILES.includes(relPath)) return true;
120
- return SCOPE_DIRS.includes(relPath.split(sep)[0]);
157
+ const p = toPosix(relPath);
158
+ if (SCOPE_FILES.includes(p)) return true;
159
+ return SCOPE_DIRS.includes(p.split('/')[0]);
121
160
  }
122
161
 
123
- // User-facing prose surface: README.md, README.ko.md, and the docs/ tree. These
124
- // additionally block `ADR NNNN` / `decisions/NNNN` (dangling wiki-ADR pointers).
125
- // Everything else in scope shipped code, CHANGELOG, package.json — keeps its ADR
126
- // anchors, so the broader pattern set is applied here ONLY.
127
- const USER_FACING_DOCS = new Set(['README.md', 'README.ko.md']);
128
- function isUserFacingDoc(relPath) {
129
- return USER_FACING_DOCS.has(relPath) || relPath.split(sep)[0] === 'docs';
130
- }
162
+ // `ADR NNNN` / `decisions/NNNN` are dangling pointers into the maintainer's
163
+ // private wiki ADR set, so they are blocked everywhere in scope EXCEPT the
164
+ // CHANGELOG, whose version history legitimately cites the decision behind a
165
+ // release line (and never reaches an installed user as a live link). The verifier
166
+ // subsystem that carries `decisions/` paths as runtime data is already removed by
167
+ // EXCLUDED_FILES, so it is never reached here.
168
+ const ADR_EXEMPT_FILES = new Set(['CHANGELOG.md']);
131
169
  function patternsFor(relPath) {
132
- return isUserFacingDoc(relPath)
133
- ? [...BLOCKED_PATTERNS, ...USER_FACING_PATTERNS]
134
- : BLOCKED_PATTERNS;
170
+ return ADR_EXEMPT_FILES.has(toPosix(relPath))
171
+ ? BLOCKED_PATTERNS
172
+ : [...BLOCKED_PATTERNS, ...DECISION_PATTERNS];
135
173
  }
136
174
 
137
175
  // Recursively collect in-scope text files under an absolute dir.