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
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
- import type { BatchOperation, CreateEntityFields, CreateKnowledgeFields, SessionLogEntry, UpdateFields } from './types.js';
2
+ import type { BatchOperation, CreateEntityFields, CreateKnowledgeFields, DeletableKind, KnowledgeSubtype, SessionLogEntry, UpdateFields } from './types.js';
3
+ export declare const splitCommaList: (value: string) => string[];
3
4
  export declare const SessionLogSchema: z.ZodObject<{
4
5
  type: z.ZodEnum<{
5
6
  [x: string]: string;
@@ -21,20 +22,22 @@ export declare const UpdateFieldsSchema: z.ZodObject<{
21
22
  body: z.ZodOptional<z.ZodString>;
22
23
  agent: z.ZodString;
23
24
  }, z.core.$strict>>;
25
+ agent: z.ZodOptional<z.ZodString>;
24
26
  brief: z.ZodOptional<z.ZodNullable<z.ZodString>>;
25
27
  add_action: z.ZodOptional<z.ZodString>;
26
28
  add_actions: z.ZodOptional<z.ZodArray<z.ZodString>>;
27
29
  complete_action: z.ZodOptional<z.ZodString>;
28
30
  remove_action: z.ZodOptional<z.ZodString>;
29
31
  clear_actions: z.ZodOptional<z.ZodBoolean>;
32
+ parent: z.ZodOptional<z.ZodString>;
30
33
  description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
31
34
  resource: z.ZodOptional<z.ZodNullable<z.ZodString>>;
32
- domain: z.ZodOptional<z.ZodArray<z.ZodString>>;
35
+ domain: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
33
36
  confidence: z.ZodOptional<z.ZodEnum<{
34
37
  [x: string]: string;
35
38
  }>>;
36
- tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
37
- related: z.ZodOptional<z.ZodArray<z.ZodString>>;
39
+ tags: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
40
+ related: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
38
41
  synthesis: z.ZodOptional<z.ZodString>;
39
42
  insight: z.ZodOptional<z.ZodString>;
40
43
  add_evidence: z.ZodOptional<z.ZodString>;
@@ -47,10 +50,10 @@ export declare const CreateEntityFieldsSchema: z.ZodObject<{
47
50
  purpose: z.ZodOptional<z.ZodString>;
48
51
  description: z.ZodOptional<z.ZodString>;
49
52
  resource: z.ZodOptional<z.ZodString>;
50
- domain: z.ZodOptional<z.ZodArray<z.ZodString>>;
53
+ domain: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
51
54
  parent: z.ZodOptional<z.ZodString>;
52
- related: z.ZodOptional<z.ZodArray<z.ZodString>>;
53
- tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
55
+ related: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
56
+ tags: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
54
57
  brief: z.ZodOptional<z.ZodString>;
55
58
  add_action: z.ZodOptional<z.ZodString>;
56
59
  add_actions: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -59,23 +62,33 @@ export declare const CreateKnowledgeFieldsSchema: z.ZodObject<{
59
62
  subtype: z.ZodOptional<z.ZodEnum<{
60
63
  [x: string]: string;
61
64
  }>>;
65
+ status: z.ZodOptional<z.ZodEnum<{
66
+ [x: string]: string;
67
+ }>>;
68
+ confidence: z.ZodOptional<z.ZodEnum<{
69
+ [x: string]: string;
70
+ }>>;
62
71
  synthesis: z.ZodOptional<z.ZodString>;
63
72
  insight: z.ZodOptional<z.ZodString>;
64
73
  description: z.ZodOptional<z.ZodString>;
65
- domain: z.ZodOptional<z.ZodArray<z.ZodString>>;
66
- related: z.ZodOptional<z.ZodArray<z.ZodString>>;
67
- tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
74
+ domain: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
75
+ related: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
76
+ tags: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
68
77
  'session-date': z.ZodOptional<z.ZodString>;
69
78
  }, z.core.$strict>;
70
79
  export declare const CreateSessionFieldsSchema: z.ZodObject<{
71
80
  synthesis: z.ZodOptional<z.ZodString>;
72
81
  insight: z.ZodOptional<z.ZodString>;
73
- related: z.ZodOptional<z.ZodArray<z.ZodString>>;
82
+ related: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
74
83
  'session-date': z.ZodOptional<z.ZodString>;
75
84
  }, z.core.$strict>;
76
85
  /** What `digest` may put in a session-create op — typechecked against the
77
86
  * schema so the two can never silently diverge again. */
78
87
  export type CreateSessionFieldsInput = z.infer<typeof CreateSessionFieldsSchema>;
88
+ /** The fields an update's mechanised session log entry names — empty when
89
+ * the update earns none. Shared by the update check (which rejects an
90
+ * `agent` with no entry to name) and the Apply update arm (which writes it). */
91
+ export declare function loggedFields(fields: UpdateFields): (keyof UpdateFields)[];
79
92
  export declare const BatchOperationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
80
93
  op: z.ZodLiteral<"update">;
81
94
  slug: z.ZodString;
@@ -92,20 +105,22 @@ export declare const BatchOperationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
92
105
  body: z.ZodOptional<z.ZodString>;
93
106
  agent: z.ZodString;
94
107
  }, z.core.$strict>>;
108
+ agent: z.ZodOptional<z.ZodString>;
95
109
  brief: z.ZodOptional<z.ZodNullable<z.ZodString>>;
96
110
  add_action: z.ZodOptional<z.ZodString>;
97
111
  add_actions: z.ZodOptional<z.ZodArray<z.ZodString>>;
98
112
  complete_action: z.ZodOptional<z.ZodString>;
99
113
  remove_action: z.ZodOptional<z.ZodString>;
100
114
  clear_actions: z.ZodOptional<z.ZodBoolean>;
115
+ parent: z.ZodOptional<z.ZodString>;
101
116
  description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
102
117
  resource: z.ZodOptional<z.ZodNullable<z.ZodString>>;
103
- domain: z.ZodOptional<z.ZodArray<z.ZodString>>;
118
+ domain: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
104
119
  confidence: z.ZodOptional<z.ZodEnum<{
105
120
  [x: string]: string;
106
121
  }>>;
107
- tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
108
- related: z.ZodOptional<z.ZodArray<z.ZodString>>;
122
+ tags: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
123
+ related: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
109
124
  synthesis: z.ZodOptional<z.ZodString>;
110
125
  insight: z.ZodOptional<z.ZodString>;
111
126
  add_evidence: z.ZodOptional<z.ZodString>;
@@ -141,22 +156,52 @@ export declare const BatchOperationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
141
156
  project: "project";
142
157
  knowledge: "knowledge";
143
158
  }>;
159
+ }, z.core.$strict>, z.ZodObject<{
160
+ op: z.ZodLiteral<"delete">;
161
+ slug: z.ZodString;
144
162
  }, z.core.$strict>], "op">;
163
+ /** Canonicalize an operation's declared aliases.
164
+ *
165
+ * Precedence when both are present: the canonical field wins and the alias is
166
+ * dropped. Never mutates the caller's object — an op carrying no alias is
167
+ * returned as-is. */
168
+ export declare function normalizeAliases<T>(op: T): T;
169
+ /** normalizeAliases over a payload — the form the Spine and dry-run use. */
170
+ export declare function normalizeOperations(operations: BatchOperation[]): BatchOperation[];
171
+ /** What a slug resolves to. `subtype` is carried for knowledge so ops that
172
+ * gate on the plan/insight distinction see it for files already on disk AND
173
+ * for notes created earlier in the same batch. */
174
+ export interface ResolvedTarget {
175
+ kind: 'entity' | 'knowledge';
176
+ type: string;
177
+ subtype?: KnowledgeSubtype;
178
+ }
179
+ /** The frontmatter links `validate` checks: what makes one file a referrer
180
+ * of another. */
181
+ export interface FileLinks {
182
+ parent?: string;
183
+ related?: string[];
184
+ }
145
185
  /** Vault context handed to each spec's semantic check by validateBatchCore.
146
186
  * Simulation-aware: creates earlier in the batch count as existing. */
147
187
  export interface OpCheckContext {
148
- resolve(slug: string): {
149
- kind: 'entity' | 'knowledge';
150
- type: string;
151
- } | null;
188
+ resolve(slug: string): ResolvedTarget | null;
152
189
  existsAnywhere(slug: string): boolean;
153
190
  sessionExists(slug: string): boolean;
154
- simulate(slug: string, info: {
155
- kind: 'entity' | 'knowledge';
156
- type: string;
157
- }): void;
191
+ simulate(slug: string, info: ResolvedTarget): void;
158
192
  simulateSession(slug: string): void;
159
- validateKindFields(kind: 'entity' | 'knowledge', fields: UpdateFields): void;
193
+ /** The parent/related a file carries after the earlier ops in the batch. */
194
+ linksOf(slug: string): FileLinks;
195
+ /** Record the parent/related a file will carry after this op. Every op
196
+ * that changes a link calls it, so `referrers` sees the batch so far. */
197
+ simulateLinks(slug: string, links: FileLinks): void;
198
+ /** Entities and knowledge notes whose parent or related names `slug`,
199
+ * after the earlier ops in the batch. A file never refers to itself. */
200
+ referrers(slug: string): string[];
201
+ simulateDelete(slug: string, kind: DeletableKind): void;
202
+ /** Kind gating is subtype-aware for knowledge: a plan carries `status`,
203
+ * an insight does not (see contracts.SUBTYPE_STATUSES). */
204
+ validateKindFields(kind: 'entity' | 'knowledge', fields: UpdateFields, subtype?: KnowledgeSubtype): void;
160
205
  validateSessionLogEntry(entry: SessionLogEntry): string[];
161
206
  buildEntityFrontmatter(name: string, fields: CreateEntityFields): void;
162
207
  buildKnowledgeFrontmatter(name: string, fields: CreateKnowledgeFields): void;
@@ -166,7 +211,36 @@ export interface OpCheckResult {
166
211
  errors: string[];
167
212
  created?: boolean;
168
213
  warning?: string;
214
+ /** Error class of the primary failure, when it maps to a specific
215
+ * HafezError code. The Spine uses it so single-op callers keep NOT_FOUND /
216
+ * SLUG_EXISTS semantics (and their exit codes) through spec validation;
217
+ * batch-level failures stay VALIDATION_FAILED regardless. */
218
+ primaryCode?: 'NOT_FOUND' | 'SLUG_EXISTS';
169
219
  }
220
+ /** The one source of the missing-slug error text — specs and the Spine's
221
+ * shape-failure precedence rule (validateBatchCore) must not drift apart. */
222
+ export declare function notFoundError(slug: string): string;
223
+ /** The one op-error line format. Every surface that localises an error to its
224
+ * op — the validate phase's error list, apply's execution-time failures, and
225
+ * the CLI's dry-run report — renders it through here, so an agent parsing
226
+ * `op[i] (op slug): …` sees one shape whichever surface produced it. */
227
+ export declare function opErrorLine(index: number, op: string, slug: string, message: string): string;
228
+ /** The one "the batch was rejected, nothing landed" header — shared by the
229
+ * library's validate gate and the CLI's shape-parse gate, which reject the
230
+ * same payload at different depths and must say so identically. `batch
231
+ * --dry-run` deliberately words its own header differently: it reports a
232
+ * hypothetical ("would be applied"), not a refusal. */
233
+ export declare function batchInvalidHeader(invalidCount: number, total: number): string;
234
+ /** The one source of the duplicate-session disposition text. A duplicate
235
+ * session is not an error — the op is skipped and the batch continues — and
236
+ * dry-run (spec warning) and apply (BatchResult.warning) report it with this
237
+ * same sentence so the two can never drift. */
238
+ export declare function duplicateSessionWarning(slug: string): string;
239
+ /** The parent chain `slug → parent → … → slug` that giving `slug` this
240
+ * parent closes, or null when the chain ends or loops without `slug`.
241
+ * Shared by the Op Spec checks (against the simulated batch) and
242
+ * `validateVault` (against the files). */
243
+ export declare function parentCycle(slug: string, parent: string | undefined, parentOf: (s: string) => string | undefined): string[] | null;
170
244
  export interface OpSpec {
171
245
  /** Stable identifier used by `schema <name>` and the op catalog. */
172
246
  name: string;
@@ -175,13 +249,285 @@ export interface OpSpec {
175
249
  schema: z.ZodType;
176
250
  description: string;
177
251
  /** Optional fields force-included in the generated example payload. */
178
- exampleInclude: string[];
252
+ exampleInclude: readonly string[];
253
+ /** The op's `slug` may name a session note as well as an entity or
254
+ * knowledge note. */
255
+ addressesSessions?: boolean;
179
256
  check(op: any, ctx: OpCheckContext): OpCheckResult;
180
257
  }
181
- export declare const OP_SPECS: OpSpec[];
258
+ declare const OP_SPEC_ROWS: readonly [{
259
+ readonly name: "update";
260
+ readonly op: "update";
261
+ readonly schema: z.ZodObject<{
262
+ op: z.ZodLiteral<"update">;
263
+ slug: z.ZodString;
264
+ fields: z.ZodObject<{
265
+ status: z.ZodOptional<z.ZodEnum<{
266
+ [x: string]: string;
267
+ }>>;
268
+ current_state: z.ZodOptional<z.ZodString>;
269
+ session_log: z.ZodOptional<z.ZodObject<{
270
+ type: z.ZodEnum<{
271
+ [x: string]: string;
272
+ }>;
273
+ summary: z.ZodString;
274
+ body: z.ZodOptional<z.ZodString>;
275
+ agent: z.ZodString;
276
+ }, z.core.$strict>>;
277
+ agent: z.ZodOptional<z.ZodString>;
278
+ brief: z.ZodOptional<z.ZodNullable<z.ZodString>>;
279
+ add_action: z.ZodOptional<z.ZodString>;
280
+ add_actions: z.ZodOptional<z.ZodArray<z.ZodString>>;
281
+ complete_action: z.ZodOptional<z.ZodString>;
282
+ remove_action: z.ZodOptional<z.ZodString>;
283
+ clear_actions: z.ZodOptional<z.ZodBoolean>;
284
+ parent: z.ZodOptional<z.ZodString>;
285
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
286
+ resource: z.ZodOptional<z.ZodNullable<z.ZodString>>;
287
+ domain: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
288
+ confidence: z.ZodOptional<z.ZodEnum<{
289
+ [x: string]: string;
290
+ }>>;
291
+ tags: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
292
+ related: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
293
+ synthesis: z.ZodOptional<z.ZodString>;
294
+ insight: z.ZodOptional<z.ZodString>;
295
+ add_evidence: z.ZodOptional<z.ZodString>;
296
+ add_source: z.ZodOptional<z.ZodString>;
297
+ }, z.core.$strict>;
298
+ }, z.core.$strict>;
299
+ readonly description: "Update an entity or knowledge note (status, brief, next actions, session log, synthesis, …). Next Actions fields compose within one op as prune, tick, add: `clear_actions` → `remove_action` → `complete_action` → `add_action(s)` — queries match the list as it was before the op (two queries naming one line is an error), added lines land last, so `clear_actions` + `add_actions` rebuilds the list; `clear_actions` with a query field is rejected. Lines leaving the list (removed, cleared, pruned with an emptied section, ticked past nine, oldest first) move to the entity's archive log. A Handle of an open action (as `read` shows it, or any longer or shorter prefix of four or more hex that names only that line) names that line; anything else is a case-insensitive substring of the text. `parent` sets the parent link (entity-only; the slug must exist, and the parent chain must not lead back to the entity). `insight` is an alias for `synthesis` (knowledge-only; ignored when `synthesis` is also given). An entity update with no `session_log` gets a `progress` entry naming the fields written, unless its only fields are action fields; `agent` names the agent on it (entity-only, detected from the Harness when absent, rejected alongside `session_log`). On knowledge notes `status` is plan-subtype only (active|done); insights reject it.";
300
+ readonly exampleInclude: readonly ["status"];
301
+ readonly check: (op: Extract<BatchOperation, {
302
+ op: "update";
303
+ }>, ctx: OpCheckContext) => {
304
+ slug: string;
305
+ errors: string[];
306
+ primaryCode: "SLUG_EXISTS" | "NOT_FOUND" | undefined;
307
+ };
308
+ }, {
309
+ readonly name: "create-entity";
310
+ readonly op: "create";
311
+ readonly kind: "entity";
312
+ readonly schema: z.ZodObject<{
313
+ op: z.ZodLiteral<"create">;
314
+ kind: z.ZodLiteral<"entity">;
315
+ name: z.ZodString;
316
+ fields: z.ZodObject<{
317
+ type: z.ZodEnum<{
318
+ [x: string]: string;
319
+ }>;
320
+ purpose: z.ZodOptional<z.ZodString>;
321
+ description: z.ZodOptional<z.ZodString>;
322
+ resource: z.ZodOptional<z.ZodString>;
323
+ domain: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
324
+ parent: z.ZodOptional<z.ZodString>;
325
+ related: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
326
+ tags: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
327
+ brief: z.ZodOptional<z.ZodString>;
328
+ add_action: z.ZodOptional<z.ZodString>;
329
+ add_actions: z.ZodOptional<z.ZodArray<z.ZodString>>;
330
+ }, z.core.$strict>;
331
+ }, z.core.$strict>;
332
+ readonly description: "Create a new entity (capture / entity / project). A field whose section the chosen type lacks is rejected, never dropped — `purpose` needs type project.";
333
+ readonly exampleInclude: readonly ["type"];
334
+ readonly check: (op: Extract<BatchOperation, {
335
+ op: "create";
336
+ kind: "entity";
337
+ }>, ctx: OpCheckContext) => {
338
+ slug: string;
339
+ errors: string[];
340
+ created: boolean;
341
+ primaryCode: "SLUG_EXISTS" | "NOT_FOUND" | undefined;
342
+ };
343
+ }, {
344
+ readonly name: "create-knowledge";
345
+ readonly op: "create";
346
+ readonly kind: "knowledge";
347
+ readonly schema: z.ZodObject<{
348
+ op: z.ZodLiteral<"create">;
349
+ kind: z.ZodLiteral<"knowledge">;
350
+ name: z.ZodString;
351
+ fields: z.ZodOptional<z.ZodObject<{
352
+ subtype: z.ZodOptional<z.ZodEnum<{
353
+ [x: string]: string;
354
+ }>>;
355
+ status: z.ZodOptional<z.ZodEnum<{
356
+ [x: string]: string;
357
+ }>>;
358
+ confidence: z.ZodOptional<z.ZodEnum<{
359
+ [x: string]: string;
360
+ }>>;
361
+ synthesis: z.ZodOptional<z.ZodString>;
362
+ insight: z.ZodOptional<z.ZodString>;
363
+ description: z.ZodOptional<z.ZodString>;
364
+ domain: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
365
+ related: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
366
+ tags: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
367
+ 'session-date': z.ZodOptional<z.ZodString>;
368
+ }, z.core.$strict>>;
369
+ }, z.core.$strict>;
370
+ readonly description: "Create a new knowledge note (insight / plan subtype). `confidence` defaults to observation. `insight` is an alias for `synthesis` (ignored when `synthesis` is also given). `status` (active|done) is plan-only; `synthesis` is insight-only — plan bodies are Goal/Steps/Dependencies, and a field whose section the subtype lacks is rejected, never dropped.";
371
+ readonly exampleInclude: readonly ["subtype", "synthesis"];
372
+ readonly check: (op: Extract<BatchOperation, {
373
+ op: "create";
374
+ kind: "knowledge";
375
+ }>, ctx: OpCheckContext) => {
376
+ slug: string;
377
+ errors: string[];
378
+ created: boolean;
379
+ primaryCode: "SLUG_EXISTS" | "NOT_FOUND" | undefined;
380
+ };
381
+ }, {
382
+ readonly name: "create-session";
383
+ readonly op: "create";
384
+ readonly kind: "session";
385
+ readonly schema: z.ZodObject<{
386
+ op: z.ZodLiteral<"create">;
387
+ kind: z.ZodLiteral<"session">;
388
+ name: z.ZodString;
389
+ fields: z.ZodOptional<z.ZodObject<{
390
+ synthesis: z.ZodOptional<z.ZodString>;
391
+ insight: z.ZodOptional<z.ZodString>;
392
+ related: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>>;
393
+ 'session-date': z.ZodOptional<z.ZodString>;
394
+ }, z.core.$strict>>;
395
+ }, z.core.$strict>;
396
+ readonly description: "Create a new session note linked to an entity. `insight` is an alias for `synthesis` (ignored when `synthesis` is also given).";
397
+ readonly exampleInclude: readonly ["synthesis"];
398
+ readonly check: (op: Extract<BatchOperation, {
399
+ op: "create";
400
+ kind: "session";
401
+ }>, ctx: OpCheckContext) => {
402
+ slug: string;
403
+ errors: never[];
404
+ warning: string;
405
+ created?: undefined;
406
+ } | {
407
+ slug: string;
408
+ errors: never[];
409
+ created: true;
410
+ warning?: undefined;
411
+ };
412
+ }, {
413
+ readonly name: "capture";
414
+ readonly op: "capture";
415
+ readonly schema: z.ZodObject<{
416
+ op: z.ZodLiteral<"capture">;
417
+ name: z.ZodString;
418
+ notes: z.ZodOptional<z.ZodString>;
419
+ }, z.core.$strict>;
420
+ readonly description: "Quick capture — a raw inbox item with no structure required.";
421
+ readonly exampleInclude: readonly ["notes"];
422
+ readonly check: (op: Extract<BatchOperation, {
423
+ op: "capture";
424
+ }>, ctx: OpCheckContext) => {
425
+ slug: string;
426
+ errors: string[];
427
+ created: boolean;
428
+ primaryCode: "SLUG_EXISTS" | "NOT_FOUND" | undefined;
429
+ };
430
+ }, {
431
+ readonly name: "link";
432
+ readonly op: "link";
433
+ readonly schema: z.ZodObject<{
434
+ op: z.ZodLiteral<"link">;
435
+ slug: z.ZodString;
436
+ target: z.ZodString;
437
+ relation: z.ZodEnum<{
438
+ parent: "parent";
439
+ related: "related";
440
+ }>;
441
+ }, z.core.$strict>;
442
+ readonly description: "Add a parent or related link between two entities.";
443
+ readonly exampleInclude: readonly [];
444
+ readonly check: (op: Extract<BatchOperation, {
445
+ op: "link";
446
+ }>, ctx: OpCheckContext) => {
447
+ slug: string;
448
+ errors: string[];
449
+ primaryCode: "SLUG_EXISTS" | "NOT_FOUND" | undefined;
450
+ };
451
+ }, {
452
+ readonly name: "unlink";
453
+ readonly op: "unlink";
454
+ readonly schema: z.ZodObject<{
455
+ op: z.ZodLiteral<"unlink">;
456
+ slug: z.ZodString;
457
+ target: z.ZodString;
458
+ relation: z.ZodEnum<{
459
+ parent: "parent";
460
+ related: "related";
461
+ }>;
462
+ }, z.core.$strict>;
463
+ readonly description: "Remove a parent or related link between two entities.";
464
+ readonly exampleInclude: readonly [];
465
+ readonly check: (op: Extract<BatchOperation, {
466
+ op: "unlink";
467
+ }>, ctx: OpCheckContext) => {
468
+ slug: string;
469
+ errors: string[];
470
+ primaryCode: "SLUG_EXISTS" | "NOT_FOUND" | undefined;
471
+ };
472
+ }, {
473
+ readonly name: "promote";
474
+ readonly op: "promote";
475
+ readonly schema: z.ZodObject<{
476
+ op: z.ZodLiteral<"promote">;
477
+ slug: z.ZodString;
478
+ target: z.ZodEnum<{
479
+ entity: "entity";
480
+ project: "project";
481
+ knowledge: "knowledge";
482
+ }>;
483
+ }, z.core.$strict>;
484
+ readonly description: "Promote a capture to entity/project/knowledge, or an entity to project.";
485
+ readonly exampleInclude: readonly [];
486
+ readonly check: (op: Extract<BatchOperation, {
487
+ op: "promote";
488
+ }>, ctx: OpCheckContext) => {
489
+ slug: string;
490
+ errors: string[];
491
+ primaryCode: "SLUG_EXISTS" | "NOT_FOUND" | undefined;
492
+ };
493
+ }, {
494
+ readonly name: "delete";
495
+ readonly op: "delete";
496
+ readonly schema: z.ZodObject<{
497
+ op: z.ZodLiteral<"delete">;
498
+ slug: z.ZodString;
499
+ }, z.core.$strict>;
500
+ readonly description: "Delete a knowledge or session note. An entity is never deleted — retire it with `hafez update <slug> --status done`. Rejected while another entity or knowledge note links to the note (parent/related): unlink or re-point those first — an earlier op in the same batch counts.";
501
+ readonly exampleInclude: readonly [];
502
+ readonly addressesSessions: true;
503
+ readonly check: (op: Extract<BatchOperation, {
504
+ op: "delete";
505
+ }>, ctx: OpCheckContext) => {
506
+ slug: string;
507
+ errors: string[];
508
+ primaryCode: "SLUG_EXISTS" | "NOT_FOUND" | undefined;
509
+ };
510
+ }];
511
+ /** Every op the table defines. The Apply table (src/apply.ts) is keyed by this
512
+ * union, so a spec row added here without an apply arm fails to build. */
513
+ export type OpSpecName = (typeof OP_SPEC_ROWS)[number]['name'];
514
+ export declare const OP_SPECS: readonly (OpSpec & {
515
+ name: OpSpecName;
516
+ })[];
182
517
  /** Find the spec for a (shape-valid) operation. */
183
- export declare function specFor(op: BatchOperation): OpSpec;
518
+ export declare function specFor(op: BatchOperation): OpSpec & {
519
+ name: OpSpecName;
520
+ };
184
521
  /** Op names for error text ("expected one of […]") — derived, never hardcoded. */
185
522
  export declare function validOpNames(): string[];
523
+ /** Ops whose payload addresses an existing file by `slug` — derived from the
524
+ * Zod shapes, so a new slug-bearing op picks up slug-level rules (the
525
+ * NOT_FOUND precedence on shape failure in validateBatchCore) without a
526
+ * hand-kept list. */
527
+ export declare function slugBearingOpNames(): string[];
528
+ /** Slug-bearing ops whose slug may name a session note — a missing entity
529
+ * or knowledge note alone is not NOT_FOUND for them. */
530
+ export declare function sessionAddressingOpNames(): string[];
186
531
  /** Create kinds for error text — derived from the table. */
187
532
  export declare function validCreateKinds(): string[];
533
+ export {};