hafez 1.3.0 → 2.0.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 (75) hide show
  1. package/README.md +83 -32
  2. package/dist/apply.d.ts +33 -0
  3. package/dist/apply.js +693 -0
  4. package/dist/batch-ops.d.ts +372 -26
  5. package/dist/batch-ops.js +355 -73
  6. package/dist/cli/args.d.ts +48 -6
  7. package/dist/cli/args.js +74 -9
  8. package/dist/cli/batch-errors.js +19 -11
  9. package/dist/cli/block-hook.d.ts +9 -0
  10. package/dist/cli/block-hook.js +90 -0
  11. package/dist/cli/commands-schema.js +2 -0
  12. package/dist/cli/commands.d.ts +28 -3
  13. package/dist/cli/commands.js +440 -157
  14. package/dist/cli/format.d.ts +7 -3
  15. package/dist/cli/format.js +27 -10
  16. package/dist/cli/index.d.ts +55 -0
  17. package/dist/cli/index.js +215 -153
  18. package/dist/cli/install.d.ts +53 -0
  19. package/dist/cli/install.js +297 -0
  20. package/dist/cli/onboard.d.ts +15 -2
  21. package/dist/cli/onboard.js +265 -90
  22. package/dist/cli/resolve-vault.d.ts +11 -4
  23. package/dist/cli/resolve-vault.js +13 -11
  24. package/dist/cli/schema-introspect.js +4 -3
  25. package/dist/cli/upgrade.d.ts +51 -0
  26. package/dist/cli/upgrade.js +351 -0
  27. package/dist/closest.d.ts +8 -0
  28. package/dist/closest.js +65 -0
  29. package/dist/contracts.d.ts +65 -6
  30. package/dist/contracts.js +148 -23
  31. package/dist/dates.d.ts +10 -0
  32. package/dist/dates.js +27 -0
  33. package/dist/db.d.ts +40 -2
  34. package/dist/db.js +363 -66
  35. package/dist/digest.d.ts +6 -4
  36. package/dist/digest.js +28 -17
  37. package/dist/document.d.ts +135 -88
  38. package/dist/document.js +665 -379
  39. package/dist/export-okf.d.ts +13 -0
  40. package/dist/export-okf.js +50 -20
  41. package/dist/git.js +165 -48
  42. package/dist/harness.d.ts +58 -0
  43. package/dist/harness.js +50 -0
  44. package/dist/index.d.ts +2 -2
  45. package/dist/index.js +301 -826
  46. package/dist/knowledge-index.d.ts +23 -1
  47. package/dist/knowledge-index.js +62 -6
  48. package/dist/merge.d.ts +1 -1
  49. package/dist/merge.js +98 -64
  50. package/dist/near-match.d.ts +9 -0
  51. package/dist/near-match.js +34 -0
  52. package/dist/schema.js +4 -4
  53. package/dist/stale.d.ts +41 -0
  54. package/dist/stale.js +43 -0
  55. package/dist/stopwords.d.ts +6 -0
  56. package/dist/stopwords.js +25 -0
  57. package/dist/surfaces/items.d.ts +366 -0
  58. package/dist/surfaces/items.js +523 -0
  59. package/dist/surfaces/surfaces.d.ts +32 -0
  60. package/dist/surfaces/surfaces.js +230 -0
  61. package/dist/templates.d.ts +6 -0
  62. package/dist/templates.js +27 -27
  63. package/dist/types.d.ts +78 -22
  64. package/dist/validate.d.ts +7 -0
  65. package/dist/validate.js +109 -0
  66. package/dist/vault.d.ts +18 -0
  67. package/dist/vault.js +51 -5
  68. package/package.json +4 -3
  69. package/skill/hafez/SKILL.md +68 -0
  70. package/skill/hafez-save/SKILL.md +29 -0
  71. package/dist/cli/help-agent.d.ts +0 -1
  72. package/dist/cli/help-agent.js +0 -186
  73. package/dist/query.d.ts +0 -24
  74. package/dist/query.js +0 -169
  75. package/skill/SKILL.md +0 -196
package/README.md CHANGED
@@ -18,27 +18,26 @@ Claude Code (or any agent with shell access):
18
18
  ```text
19
19
  Set up Hafez, an agent-native knowledge vault (github.com/shrvn-r/hafez):
20
20
 
21
- 1. Install the CLI (needs Node.js 22+ and git): npm install -g hafez
22
- On npm 11+, append --allow-scripts=better-sqlite3 (npm 11 blocks install
23
- scripts by default; the SQLite bindings need theirs, and the install
24
- reports success even when they were skipped).
21
+ 1. Install the CLI (needs Node.js 22+ and git):
22
+ npm install -g hafez --allow-scripts=better-sqlite3
23
+ Always include that flag: npm 11+ blocks install scripts by default, the
24
+ SQLite bindings need theirs, and the install reports success even when
25
+ they were skipped. npm majors predating the flag print
26
+ "npm warn Unknown cli config" and proceed.
25
27
  2. Check git identity is configured (git config user.name and user.email);
26
28
  if not, ask me for a name and email and set them with git config --global.
27
29
  3. Create my vault — a git repo with entities/ and knowledge/ directories and an
28
30
  initial commit. Suggest ~/vault but ask me where I want it first.
29
31
  4. Register it: hafez init --register <vault-path>
30
- 5. If you are Claude Code, install the bundled skill: copy skill/SKILL.md
31
- from the installed package ("$(npm root -g)/hafez/skill/SKILL.md") to
32
- ~/.claude/skills/hafez/SKILL.md. Any other harness: skip this — step 7
33
- covers integration.
34
- 6. Read hafez help --agent, then verify end-to-end: create a test capture,
32
+ 5. Read hafez help --agent, then verify end-to-end: create a test capture,
35
33
  hafez read it back, and show me hafez stats.
36
- 7. Run hafez onboard and follow what it prints: interview me to seed the
37
- vault with my current projects, then help me choose how deeply to
38
- integrate Hafez into my agent setup.
34
+ 6. Run hafez onboard and follow what it prints: ask me how Hafez should
35
+ run, install it (the two skills, and the Block in your instructions
36
+ file), and, if the vault is empty, interview me to seed it with my
37
+ current projects.
39
38
  ```
40
39
 
41
- From then on, just mention your projects by name in any session — the skill
40
+ From then on, just mention your projects by name in any session — the Block
42
41
  teaches the agent when to read and write the vault, no commands required.
43
42
 
44
43
  Upgrading from an earlier name of this tool? Remove the old skill directory
@@ -50,9 +49,10 @@ triggers compete for the same invocations.
50
49
  The same thing by hand:
51
50
 
52
51
  ```bash
53
- # Install (Node.js 22+ and git required).
54
- # On npm 11+, append: --allow-scripts=better-sqlite3
55
- npm install -g hafez
52
+ # Install (Node.js 22+ and git required). Always include the flag: npm 11+
53
+ # blocks install scripts by default and the SQLite bindings need theirs;
54
+ # older npm majors print "npm warn Unknown cli config" and proceed.
55
+ npm install -g hafez --allow-scripts=better-sqlite3
56
56
 
57
57
  # One-time, if you've never used git on this machine:
58
58
  # git config --global user.name "Your Name"
@@ -64,18 +64,67 @@ cd ~/vault && git init && git commit --allow-empty -m "init vault"
64
64
  hafez init --register ~/vault # remember this vault (one-time)
65
65
  hafez init # show current vault resolution
66
66
 
67
- # Claude Code only (optional): the bundled skill
68
- mkdir -p ~/.claude/skills/hafez
69
- cp "$(npm root -g)/hafez/skill/SKILL.md" ~/.claude/skills/hafez/SKILL.md
70
-
71
- # Then, in your agent — any harness: "run hafez onboard and follow it" —
72
- # guided first run (seed the vault with your current projects, choose an
73
- # integration level)
67
+ # Then, in Claude Code or Codex: "run hafez onboard and follow it" —
68
+ # guided setup (choose how Hafez runs, install the two skills and the Block,
69
+ # seed an empty vault)
74
70
  ```
75
71
 
76
72
  Prefer installing without the npm registry? The GitHub release tarball is the
77
- same artifact: `npm install -g https://github.com/shrvn-r/hafez/releases/latest/download/hafez.tgz`
78
- (npm 12+ additionally needs `--allow-remote=root`).
73
+ same artifact, running the same install scripts, so it takes the same flag —
74
+ plus `--allow-remote=root`, which npm 12+ requires for a remote URL:
75
+
76
+ ```bash
77
+ npm install -g https://github.com/shrvn-r/hafez/releases/latest/download/hafez.tgz --allow-scripts=better-sqlite3 --allow-remote=root
78
+ ```
79
+
80
+ ## Updating
81
+
82
+ Tell your agent: **update hafez**. Or paste: "Run `hafez upgrade` and follow
83
+ what it prints."
84
+
85
+ `hafez upgrade` checks and prints — it never installs. The steps it prints
86
+ install code and overwrite your agent instructions file, so **you** approve
87
+ them; don't let an agent run them unattended. Re-run `hafez upgrade`
88
+ afterwards to verify.
89
+
90
+ If `hafez upgrade` fails with `Unknown command:`, your installed hafez
91
+ predates the command — run the manual steps below once, then use it.
92
+
93
+ ### Updating by hand
94
+
95
+ ```bash
96
+ # 1. Install. Same flag rule as a fresh install; <version> is the version you
97
+ # are moving to (npm view hafez version).
98
+ npm install -g hafez@<version> --allow-scripts=better-sqlite3
99
+
100
+ # From the GitHub release tarball instead (npm 12+ needs --allow-remote):
101
+ npm install -g https://github.com/shrvn-r/hafez/releases/download/v<version>/hafez.tgz --allow-scripts=better-sqlite3 --allow-remote=root
102
+
103
+ # 2. The skills, and the Block if you have one, ship inside the package, so
104
+ # an upgraded package leaves the installed copies stale. The new binary
105
+ # has `hafez upgrade`: it checks them by hash and prints the
106
+ # `hafez onboard --install` line that refreshes them.
107
+ hafez upgrade
108
+
109
+ # 3. Rebuild the read index. A schema bump invalidates it rather than
110
+ # rebuilding it, so the first query after an upgrade can answer empty.
111
+ hafez index rebuild
112
+ ```
113
+
114
+ The prose above always includes every install flag, because static text cannot
115
+ probe your npm — `hafez upgrade` does probe it and prints the exact form your
116
+ npm accepts. Same instruction, two renderings; the extra flags are harmless
117
+ (`npm warn Unknown cli config`, then it proceeds).
118
+
119
+ A Hafez section pasted into your instructions file by hand, before the Block
120
+ had markers, is not checked: delete it, then install the Block with
121
+ `hafez onboard`.
122
+
123
+ Your vault is untouched by an upgrade: the files, the git history, and the
124
+ registered vault path all survive. Only the read index is invalidated.
125
+
126
+ If any command reports unbuilt SQLite bindings, reinstall with
127
+ `--allow-scripts=better-sqlite3` — the CLI prints this itself when it happens.
79
128
 
80
129
  ## Quick start
81
130
 
@@ -100,7 +149,7 @@ hafez query --kind knowledge --domain security
100
149
  hafez search "token rotation"
101
150
 
102
151
  # Record progress
103
- hafez update auth-refactor --log "progress: JWT flow implemented" --agent claude
152
+ hafez update auth-refactor --log "progress: JWT flow implemented"
104
153
  hafez update auth-refactor --complete-action "migration plan"
105
154
  ```
106
155
 
@@ -138,18 +187,20 @@ Links (`parent`, `related`) are validated — they must point at slugs that exis
138
187
  | `hafez create <entity\|knowledge> <name> [flags]` | Create a document |
139
188
  | `hafez capture <name> [--notes]` | Quick inbox capture |
140
189
  | `hafez promote <slug> <entity\|project\|knowledge>` | Promote a capture upward |
190
+ | `hafez delete <slug>` | Delete a knowledge or session note (entities retire with `--status done`) |
141
191
  | `hafez update <slug> [flags]` | Status, brief, actions, session log, synthesis, evidence… |
142
192
  | `hafez link / unlink <slug> <target> --relation <parent\|related>` | Manage relationships |
143
- | `hafez batch [--dry-run] [--file payload.json]` | JSON ops (stdin or `--file`) → atomic multi-op, single git commit, rollback on failure; dry-run runs the same validation as apply and reports derived slugs |
193
+ | `hafez batch [--dry-run] [--data '<json>' \| --file payload.json]` | JSON ops (stdin, `--data` or `--file`) → atomic multi-op, single git commit, rollback on failure; dry-run runs the same validation as apply and reports derived slugs |
144
194
  | `hafez stats` | Vault summary: counts, stale items, recents |
145
195
  | `hafez changelog --since 7.days.ago` | Git-derived change history |
146
196
  | `hafez sync` | Pull remote, push local commits (semantic merge on conflicts) |
147
197
  | `hafez validate` / `hafez index rebuild` | Integrity check / rebuild the read index |
148
- | `hafez onboard` | Agent-directed first run: seeding interview + integration setup |
198
+ | `hafez onboard` | Setup status, then the script your agent follows: Mode, install, permissions, seeding |
199
+ | `hafez onboard --install --mode <always-on\|invoke-only>` / `--remove` | Write (or remove) the two skills and, always-on, the marked Block in the harness's instructions file |
149
200
  | `hafez schema [op] [--examples]` | Machine-readable JSON schema for every operation |
150
201
  | `hafez export --okf [--out <dir>]` | Read-only OKF v0.1 bundle export |
151
202
 
152
- This is not exhaustive — `hafez help --agent` prints the full, always-current reference. Add `--json` to any command for structured output.
203
+ This is not exhaustive — `hafez --help` lists every command, and `hafez schema <op>` prints the machine-readable shape of any op. Add `--json` to any command for structured output.
153
204
 
154
205
  ## Library usage
155
206
 
@@ -188,9 +239,9 @@ for everything on the [AGENTS.md standard](https://agents.md) (Codex, Cursor,
188
239
  Copilot, …). This repo follows the same convention: `AGENTS.md` is canonical
189
240
  and `CLAUDE.md` imports it.
190
241
 
191
- - **`hafez onboard`** — an agent-directed first-run guide: a seeding interview for the empty vault, then a choice of integration level (an always-active block for the harness's global instructions file, or invoke-only). Re-running it later is the intended way to seed newly started work — on a set-up vault it's just the interview.
192
- - **`hafez help --agent`** — a complete API reference designed to be loaded into an agent's context.
193
- - **Claude Code skill** — an optional adapter for one harness: the package bundles a skill (installed in [Setup](#setup)) covering the full session lifecycle: loading context at session start, vault ops mid-session, and a session-end digest.
242
+ - **`hafez onboard`** — agent-directed setup, run from inside Claude Code or Codex (any other harness: `onboard --install --harness <h>`): where things stand (the vault, and per harness found the Block, skills, hook and allowlist), then the script the agent follows — choose always-on or invoke-only, install, allow the command, optionally add the session-start hook, seed an empty vault, and four lines for the user. Re-running it is reconfigure: it walks only what is not current.
243
+ - **`hafez help --agent`** — the `hafez` skill body, one text from the same source: the reference an agent reads when the skill is not installed.
244
+ - **Two skills, `hafez` and `hafez-save`** — written by `hafez onboard --install` to `~/.claude/skills` and `~/.agents/skills`, so every harness reading either directory gets them: the less common operations and the tool itself, and the session save. The Block, the skills and every sample of command output are rendered from one source and checked byte for byte in CI; the samples are in [`tests/fixtures/surfaces/`](tests/fixtures/surfaces/).
194
245
  - **`hafez schema <op> --examples`** — JSON schemas with working examples for every batch operation, so agents can self-correct.
195
246
  - **`hafez batch`** — apply a whole session's worth of updates atomically from a single JSON payload. Validation errors report every bad op at once with did-you-mean hints.
196
247
  - **Markdown-native output** by default, `--json` everywhere for machine consumption.
@@ -0,0 +1,33 @@
1
+ import type { BatchOperation, BatchResult, CreateEntityFields, DeletableKind, CreateKnowledgeFields, KnowledgeSubtype, UpdateFields, UpdateResult } from './types.js';
2
+ export interface AppliedOp {
3
+ filesWritten: string[];
4
+ filesDeleted: string[];
5
+ result: BatchResult;
6
+ commitMessage: string;
7
+ indexRemovals: string[];
8
+ indexUpserts: Array<{
9
+ slug: string;
10
+ kind: 'entity' | 'knowledge';
11
+ }>;
12
+ /** Set by the update arm: the line each Next Actions query matched. */
13
+ updateResult?: UpdateResult;
14
+ /** Set by the delete arm: the kind of note it removed. */
15
+ deletedKind?: DeletableKind;
16
+ }
17
+ /** Everything an apply arm needs from its caller: where the vault is, and how
18
+ * to hand the Spine a pre-write snapshot for rollback. Path resolution, the
19
+ * existence checks, and the local-day clock are ordinary imports — one adapter
20
+ * would only be a hypothetical seam. */
21
+ export interface ApplyContext {
22
+ vaultPath: string;
23
+ captureOriginal(path: string): void;
24
+ }
25
+ export declare function validateKindFields(kind: 'entity' | 'knowledge', fields: UpdateFields, subtype?: KnowledgeSubtype): void;
26
+ export declare function buildEntityFrontmatter(name: string, ef: CreateEntityFields, existsFn: (slug: string) => boolean): Record<string, any>;
27
+ export declare function buildKnowledgeFrontmatter(name: string, kf: CreateKnowledgeFields, existsFn: (slug: string) => boolean): Record<string, any>;
28
+ /** The single apply path for every mutation. Writes vault files but never
29
+ * touches git or SQLite: the Spine commits [...filesWritten, ...filesDeleted]
30
+ * under commitMessage (single ops) or one composed batch message, then runs
31
+ * the index updates. ctx.captureOriginal snapshots files for rollback before
32
+ * they change. */
33
+ export declare function applyOperation(op: BatchOperation, ctx: ApplyContext): AppliedOp;