hafez 1.2.0 → 1.4.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 (52) hide show
  1. package/README.md +67 -9
  2. package/dist/apply.d.ts +30 -0
  3. package/dist/apply.js +582 -0
  4. package/dist/batch-ops.d.ts +470 -0
  5. package/dist/batch-ops.js +446 -0
  6. package/dist/cli/args.d.ts +19 -0
  7. package/dist/cli/args.js +53 -0
  8. package/dist/cli/batch-errors.js +6 -3
  9. package/dist/cli/commands.d.ts +24 -108
  10. package/dist/cli/commands.js +297 -313
  11. package/dist/cli/help-agent.d.ts +0 -5
  12. package/dist/cli/help-agent.js +44 -5
  13. package/dist/cli/index.d.ts +41 -0
  14. package/dist/cli/index.js +172 -172
  15. package/dist/cli/resolve-vault.js +2 -1
  16. package/dist/cli/schema-introspect.d.ts +1 -1
  17. package/dist/cli/schema-introspect.js +6 -22
  18. package/dist/cli/upgrade.d.ts +42 -0
  19. package/dist/cli/upgrade.js +305 -0
  20. package/dist/cli.js +0 -0
  21. package/dist/contracts.d.ts +55 -6
  22. package/dist/contracts.js +110 -23
  23. package/dist/dates.d.ts +10 -0
  24. package/dist/dates.js +27 -0
  25. package/dist/db.d.ts +27 -2
  26. package/dist/db.js +318 -56
  27. package/dist/digest.js +2 -0
  28. package/dist/document.d.ts +117 -0
  29. package/dist/document.js +578 -0
  30. package/dist/export-okf.js +48 -34
  31. package/dist/git.d.ts +7 -8
  32. package/dist/git.js +198 -63
  33. package/dist/index.d.ts +3 -4
  34. package/dist/index.js +302 -915
  35. package/dist/knowledge-index.d.ts +23 -1
  36. package/dist/knowledge-index.js +71 -13
  37. package/dist/merge.d.ts +1 -1
  38. package/dist/merge.js +106 -86
  39. package/dist/schema.js +4 -4
  40. package/dist/templates.d.ts +6 -0
  41. package/dist/templates.js +27 -27
  42. package/dist/types.d.ts +86 -12
  43. package/dist/vault.d.ts +51 -6
  44. package/dist/vault.js +114 -11
  45. package/package.json +2 -2
  46. package/skill/SKILL.md +51 -110
  47. package/dist/parser.d.ts +0 -18
  48. package/dist/parser.js +0 -68
  49. package/dist/query.d.ts +0 -24
  50. package/dist/query.js +0 -167
  51. package/dist/sections.d.ts +0 -54
  52. package/dist/sections.js +0 -297
@@ -0,0 +1,470 @@
1
+ import { z } from 'zod';
2
+ import type { BatchOperation, CreateEntityFields, CreateKnowledgeFields, KnowledgeSubtype, SessionLogEntry, UpdateFields } from './types.js';
3
+ export declare const SessionLogSchema: z.ZodObject<{
4
+ type: z.ZodEnum<{
5
+ [x: string]: string;
6
+ }>;
7
+ summary: z.ZodString;
8
+ body: z.ZodOptional<z.ZodString>;
9
+ agent: z.ZodString;
10
+ }, z.core.$strict>;
11
+ export declare const UpdateFieldsSchema: z.ZodObject<{
12
+ status: z.ZodOptional<z.ZodEnum<{
13
+ [x: string]: string;
14
+ }>>;
15
+ current_state: z.ZodOptional<z.ZodString>;
16
+ session_log: z.ZodOptional<z.ZodObject<{
17
+ type: z.ZodEnum<{
18
+ [x: string]: string;
19
+ }>;
20
+ summary: z.ZodString;
21
+ body: z.ZodOptional<z.ZodString>;
22
+ agent: z.ZodString;
23
+ }, z.core.$strict>>;
24
+ brief: z.ZodOptional<z.ZodNullable<z.ZodString>>;
25
+ add_action: z.ZodOptional<z.ZodString>;
26
+ add_actions: z.ZodOptional<z.ZodArray<z.ZodString>>;
27
+ complete_action: z.ZodOptional<z.ZodString>;
28
+ remove_action: z.ZodOptional<z.ZodString>;
29
+ clear_actions: z.ZodOptional<z.ZodBoolean>;
30
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
31
+ resource: z.ZodOptional<z.ZodNullable<z.ZodString>>;
32
+ domain: z.ZodOptional<z.ZodArray<z.ZodString>>;
33
+ confidence: z.ZodOptional<z.ZodEnum<{
34
+ [x: string]: string;
35
+ }>>;
36
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
37
+ related: z.ZodOptional<z.ZodArray<z.ZodString>>;
38
+ synthesis: z.ZodOptional<z.ZodString>;
39
+ insight: z.ZodOptional<z.ZodString>;
40
+ add_evidence: z.ZodOptional<z.ZodString>;
41
+ add_source: z.ZodOptional<z.ZodString>;
42
+ }, z.core.$strict>;
43
+ export declare const CreateEntityFieldsSchema: z.ZodObject<{
44
+ type: z.ZodEnum<{
45
+ [x: string]: string;
46
+ }>;
47
+ purpose: z.ZodOptional<z.ZodString>;
48
+ description: z.ZodOptional<z.ZodString>;
49
+ resource: z.ZodOptional<z.ZodString>;
50
+ domain: z.ZodOptional<z.ZodArray<z.ZodString>>;
51
+ parent: z.ZodOptional<z.ZodString>;
52
+ related: z.ZodOptional<z.ZodArray<z.ZodString>>;
53
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
54
+ brief: z.ZodOptional<z.ZodString>;
55
+ add_action: z.ZodOptional<z.ZodString>;
56
+ add_actions: z.ZodOptional<z.ZodArray<z.ZodString>>;
57
+ }, z.core.$strict>;
58
+ export declare const CreateKnowledgeFieldsSchema: z.ZodObject<{
59
+ subtype: z.ZodOptional<z.ZodEnum<{
60
+ [x: string]: string;
61
+ }>>;
62
+ status: z.ZodOptional<z.ZodEnum<{
63
+ [x: string]: string;
64
+ }>>;
65
+ synthesis: z.ZodOptional<z.ZodString>;
66
+ insight: z.ZodOptional<z.ZodString>;
67
+ description: z.ZodOptional<z.ZodString>;
68
+ domain: z.ZodOptional<z.ZodArray<z.ZodString>>;
69
+ related: z.ZodOptional<z.ZodArray<z.ZodString>>;
70
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
71
+ 'session-date': z.ZodOptional<z.ZodString>;
72
+ }, z.core.$strict>;
73
+ export declare const CreateSessionFieldsSchema: z.ZodObject<{
74
+ synthesis: z.ZodOptional<z.ZodString>;
75
+ insight: z.ZodOptional<z.ZodString>;
76
+ related: z.ZodOptional<z.ZodArray<z.ZodString>>;
77
+ 'session-date': z.ZodOptional<z.ZodString>;
78
+ }, z.core.$strict>;
79
+ /** What `digest` may put in a session-create op — typechecked against the
80
+ * schema so the two can never silently diverge again. */
81
+ export type CreateSessionFieldsInput = z.infer<typeof CreateSessionFieldsSchema>;
82
+ export declare const BatchOperationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
83
+ op: z.ZodLiteral<"update">;
84
+ slug: z.ZodString;
85
+ fields: z.ZodObject<{
86
+ status: z.ZodOptional<z.ZodEnum<{
87
+ [x: string]: string;
88
+ }>>;
89
+ current_state: z.ZodOptional<z.ZodString>;
90
+ session_log: z.ZodOptional<z.ZodObject<{
91
+ type: z.ZodEnum<{
92
+ [x: string]: string;
93
+ }>;
94
+ summary: z.ZodString;
95
+ body: z.ZodOptional<z.ZodString>;
96
+ agent: z.ZodString;
97
+ }, z.core.$strict>>;
98
+ brief: z.ZodOptional<z.ZodNullable<z.ZodString>>;
99
+ add_action: z.ZodOptional<z.ZodString>;
100
+ add_actions: z.ZodOptional<z.ZodArray<z.ZodString>>;
101
+ complete_action: z.ZodOptional<z.ZodString>;
102
+ remove_action: z.ZodOptional<z.ZodString>;
103
+ clear_actions: z.ZodOptional<z.ZodBoolean>;
104
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
105
+ resource: z.ZodOptional<z.ZodNullable<z.ZodString>>;
106
+ domain: z.ZodOptional<z.ZodArray<z.ZodString>>;
107
+ confidence: z.ZodOptional<z.ZodEnum<{
108
+ [x: string]: string;
109
+ }>>;
110
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
111
+ related: z.ZodOptional<z.ZodArray<z.ZodString>>;
112
+ synthesis: z.ZodOptional<z.ZodString>;
113
+ insight: z.ZodOptional<z.ZodString>;
114
+ add_evidence: z.ZodOptional<z.ZodString>;
115
+ add_source: z.ZodOptional<z.ZodString>;
116
+ }, z.core.$strict>;
117
+ }, z.core.$strict>, z.ZodObject<{
118
+ op: z.ZodLiteral<"create">;
119
+ }, z.core.$strip>, z.ZodObject<{
120
+ op: z.ZodLiteral<"capture">;
121
+ name: z.ZodString;
122
+ notes: z.ZodOptional<z.ZodString>;
123
+ }, z.core.$strict>, z.ZodObject<{
124
+ op: z.ZodLiteral<"link">;
125
+ slug: z.ZodString;
126
+ target: z.ZodString;
127
+ relation: z.ZodEnum<{
128
+ parent: "parent";
129
+ related: "related";
130
+ }>;
131
+ }, z.core.$strict>, z.ZodObject<{
132
+ op: z.ZodLiteral<"unlink">;
133
+ slug: z.ZodString;
134
+ target: z.ZodString;
135
+ relation: z.ZodEnum<{
136
+ parent: "parent";
137
+ related: "related";
138
+ }>;
139
+ }, z.core.$strict>, z.ZodObject<{
140
+ op: z.ZodLiteral<"promote">;
141
+ slug: z.ZodString;
142
+ target: z.ZodEnum<{
143
+ entity: "entity";
144
+ project: "project";
145
+ knowledge: "knowledge";
146
+ }>;
147
+ }, z.core.$strict>], "op">;
148
+ /** Canonicalize an operation's declared aliases.
149
+ *
150
+ * Precedence when both are present: the canonical field wins and the alias is
151
+ * dropped. Never mutates the caller's object — an op carrying no alias is
152
+ * returned as-is. */
153
+ export declare function normalizeAliases<T>(op: T): T;
154
+ /** normalizeAliases over a payload — the form the Spine and dry-run use. */
155
+ export declare function normalizeOperations(operations: BatchOperation[]): BatchOperation[];
156
+ /** What a slug resolves to. `subtype` is carried for knowledge so ops that
157
+ * gate on the plan/insight distinction see it for files already on disk AND
158
+ * for notes created earlier in the same batch. */
159
+ export interface ResolvedTarget {
160
+ kind: 'entity' | 'knowledge';
161
+ type: string;
162
+ subtype?: KnowledgeSubtype;
163
+ }
164
+ /** Vault context handed to each spec's semantic check by validateBatchCore.
165
+ * Simulation-aware: creates earlier in the batch count as existing. */
166
+ export interface OpCheckContext {
167
+ resolve(slug: string): ResolvedTarget | null;
168
+ existsAnywhere(slug: string): boolean;
169
+ sessionExists(slug: string): boolean;
170
+ simulate(slug: string, info: ResolvedTarget): void;
171
+ simulateSession(slug: string): void;
172
+ /** Kind gating is subtype-aware for knowledge: a plan carries `status`,
173
+ * an insight does not (see contracts.SUBTYPE_STATUSES). */
174
+ validateKindFields(kind: 'entity' | 'knowledge', fields: UpdateFields, subtype?: KnowledgeSubtype): void;
175
+ validateSessionLogEntry(entry: SessionLogEntry): string[];
176
+ buildEntityFrontmatter(name: string, fields: CreateEntityFields): void;
177
+ buildKnowledgeFrontmatter(name: string, fields: CreateKnowledgeFields): void;
178
+ }
179
+ export interface OpCheckResult {
180
+ slug: string;
181
+ errors: string[];
182
+ created?: boolean;
183
+ warning?: string;
184
+ /** Error class of the primary failure, when it maps to a specific
185
+ * HafezError code. The Spine uses it so single-op callers keep NOT_FOUND /
186
+ * SLUG_EXISTS semantics (and their exit codes) through spec validation;
187
+ * batch-level failures stay VALIDATION_FAILED regardless. */
188
+ primaryCode?: 'NOT_FOUND' | 'SLUG_EXISTS';
189
+ }
190
+ /** The one source of the missing-slug error text — specs and the Spine's
191
+ * shape-failure precedence rule (validateBatchCore) must not drift apart. */
192
+ export declare function notFoundError(slug: string): string;
193
+ /** The one op-error line format. Every surface that localises an error to its
194
+ * op — the validate phase's error list, apply's execution-time failures, and
195
+ * the CLI's dry-run report — renders it through here, so an agent parsing
196
+ * `op[i] (op slug): …` sees one shape whichever surface produced it. */
197
+ export declare function opErrorLine(index: number, op: string, slug: string, message: string): string;
198
+ /** The one "the batch was rejected, nothing landed" header — shared by the
199
+ * library's validate gate and the CLI's shape-parse gate, which reject the
200
+ * same payload at different depths and must say so identically. `batch
201
+ * --dry-run` deliberately words its own header differently: it reports a
202
+ * hypothetical ("would be applied"), not a refusal. */
203
+ export declare function batchInvalidHeader(invalidCount: number, total: number): string;
204
+ /** The one source of the duplicate-session disposition text. A duplicate
205
+ * session is not an error — the op is skipped and the batch continues — and
206
+ * dry-run (spec warning) and apply (BatchResult.warning) report it with this
207
+ * same sentence so the two can never drift. */
208
+ export declare function duplicateSessionWarning(slug: string): string;
209
+ export interface OpSpec {
210
+ /** Stable identifier used by `schema <name>` and the op catalog. */
211
+ name: string;
212
+ op: BatchOperation['op'];
213
+ kind?: 'entity' | 'knowledge' | 'session';
214
+ schema: z.ZodType;
215
+ description: string;
216
+ /** Optional fields force-included in the generated example payload. */
217
+ exampleInclude: readonly string[];
218
+ check(op: any, ctx: OpCheckContext): OpCheckResult;
219
+ }
220
+ declare const OP_SPEC_ROWS: readonly [{
221
+ readonly name: "update";
222
+ readonly op: "update";
223
+ readonly schema: z.ZodObject<{
224
+ op: z.ZodLiteral<"update">;
225
+ slug: z.ZodString;
226
+ fields: z.ZodObject<{
227
+ status: z.ZodOptional<z.ZodEnum<{
228
+ [x: string]: string;
229
+ }>>;
230
+ current_state: z.ZodOptional<z.ZodString>;
231
+ session_log: z.ZodOptional<z.ZodObject<{
232
+ type: z.ZodEnum<{
233
+ [x: string]: string;
234
+ }>;
235
+ summary: z.ZodString;
236
+ body: z.ZodOptional<z.ZodString>;
237
+ agent: z.ZodString;
238
+ }, z.core.$strict>>;
239
+ brief: z.ZodOptional<z.ZodNullable<z.ZodString>>;
240
+ add_action: z.ZodOptional<z.ZodString>;
241
+ add_actions: z.ZodOptional<z.ZodArray<z.ZodString>>;
242
+ complete_action: z.ZodOptional<z.ZodString>;
243
+ remove_action: z.ZodOptional<z.ZodString>;
244
+ clear_actions: z.ZodOptional<z.ZodBoolean>;
245
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
246
+ resource: z.ZodOptional<z.ZodNullable<z.ZodString>>;
247
+ domain: z.ZodOptional<z.ZodArray<z.ZodString>>;
248
+ confidence: z.ZodOptional<z.ZodEnum<{
249
+ [x: string]: string;
250
+ }>>;
251
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
252
+ related: z.ZodOptional<z.ZodArray<z.ZodString>>;
253
+ synthesis: z.ZodOptional<z.ZodString>;
254
+ insight: z.ZodOptional<z.ZodString>;
255
+ add_evidence: z.ZodOptional<z.ZodString>;
256
+ add_source: z.ZodOptional<z.ZodString>;
257
+ }, z.core.$strict>;
258
+ }, z.core.$strict>;
259
+ readonly description: "Update an entity or knowledge note (status, brief, next actions, session log, synthesis, …). `insight` is an alias for `synthesis` (knowledge-only; ignored when `synthesis` is also given). On knowledge notes `status` is plan-subtype only (active|done); insights reject it.";
260
+ readonly exampleInclude: readonly ["status"];
261
+ readonly check: (op: Extract<BatchOperation, {
262
+ op: "update";
263
+ }>, ctx: OpCheckContext) => {
264
+ slug: string;
265
+ errors: string[];
266
+ primaryCode: "SLUG_EXISTS" | "NOT_FOUND" | undefined;
267
+ };
268
+ }, {
269
+ readonly name: "create-entity";
270
+ readonly op: "create";
271
+ readonly kind: "entity";
272
+ readonly schema: z.ZodObject<{
273
+ op: z.ZodLiteral<"create">;
274
+ kind: z.ZodLiteral<"entity">;
275
+ name: z.ZodString;
276
+ fields: z.ZodObject<{
277
+ type: z.ZodEnum<{
278
+ [x: string]: string;
279
+ }>;
280
+ purpose: z.ZodOptional<z.ZodString>;
281
+ description: z.ZodOptional<z.ZodString>;
282
+ resource: z.ZodOptional<z.ZodString>;
283
+ domain: z.ZodOptional<z.ZodArray<z.ZodString>>;
284
+ parent: z.ZodOptional<z.ZodString>;
285
+ related: z.ZodOptional<z.ZodArray<z.ZodString>>;
286
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
287
+ brief: z.ZodOptional<z.ZodString>;
288
+ add_action: z.ZodOptional<z.ZodString>;
289
+ add_actions: z.ZodOptional<z.ZodArray<z.ZodString>>;
290
+ }, z.core.$strict>;
291
+ }, z.core.$strict>;
292
+ 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.";
293
+ readonly exampleInclude: readonly ["type"];
294
+ readonly check: (op: Extract<BatchOperation, {
295
+ op: "create";
296
+ kind: "entity";
297
+ }>, ctx: OpCheckContext) => {
298
+ slug: string;
299
+ errors: string[];
300
+ created: boolean;
301
+ primaryCode: "SLUG_EXISTS" | "NOT_FOUND" | undefined;
302
+ };
303
+ }, {
304
+ readonly name: "create-knowledge";
305
+ readonly op: "create";
306
+ readonly kind: "knowledge";
307
+ readonly schema: z.ZodObject<{
308
+ op: z.ZodLiteral<"create">;
309
+ kind: z.ZodLiteral<"knowledge">;
310
+ name: z.ZodString;
311
+ fields: z.ZodOptional<z.ZodObject<{
312
+ subtype: z.ZodOptional<z.ZodEnum<{
313
+ [x: string]: string;
314
+ }>>;
315
+ status: z.ZodOptional<z.ZodEnum<{
316
+ [x: string]: string;
317
+ }>>;
318
+ synthesis: z.ZodOptional<z.ZodString>;
319
+ insight: z.ZodOptional<z.ZodString>;
320
+ description: z.ZodOptional<z.ZodString>;
321
+ domain: z.ZodOptional<z.ZodArray<z.ZodString>>;
322
+ related: z.ZodOptional<z.ZodArray<z.ZodString>>;
323
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
324
+ 'session-date': z.ZodOptional<z.ZodString>;
325
+ }, z.core.$strict>>;
326
+ }, z.core.$strict>;
327
+ readonly description: "Create a new knowledge note (insight / plan subtype). `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.";
328
+ readonly exampleInclude: readonly ["subtype", "synthesis"];
329
+ readonly check: (op: Extract<BatchOperation, {
330
+ op: "create";
331
+ kind: "knowledge";
332
+ }>, ctx: OpCheckContext) => {
333
+ slug: string;
334
+ errors: string[];
335
+ created: boolean;
336
+ primaryCode: "SLUG_EXISTS" | "NOT_FOUND" | undefined;
337
+ };
338
+ }, {
339
+ readonly name: "create-session";
340
+ readonly op: "create";
341
+ readonly kind: "session";
342
+ readonly schema: z.ZodObject<{
343
+ op: z.ZodLiteral<"create">;
344
+ kind: z.ZodLiteral<"session">;
345
+ name: z.ZodString;
346
+ fields: z.ZodOptional<z.ZodObject<{
347
+ synthesis: z.ZodOptional<z.ZodString>;
348
+ insight: z.ZodOptional<z.ZodString>;
349
+ related: z.ZodOptional<z.ZodArray<z.ZodString>>;
350
+ 'session-date': z.ZodOptional<z.ZodString>;
351
+ }, z.core.$strict>>;
352
+ }, z.core.$strict>;
353
+ readonly description: "Create a new session note linked to an entity. `insight` is an alias for `synthesis` (ignored when `synthesis` is also given).";
354
+ readonly exampleInclude: readonly ["synthesis"];
355
+ readonly check: (op: Extract<BatchOperation, {
356
+ op: "create";
357
+ kind: "session";
358
+ }>, ctx: OpCheckContext) => {
359
+ slug: string;
360
+ errors: never[];
361
+ warning: string;
362
+ created?: undefined;
363
+ } | {
364
+ slug: string;
365
+ errors: never[];
366
+ created: true;
367
+ warning?: undefined;
368
+ };
369
+ }, {
370
+ readonly name: "capture";
371
+ readonly op: "capture";
372
+ readonly schema: z.ZodObject<{
373
+ op: z.ZodLiteral<"capture">;
374
+ name: z.ZodString;
375
+ notes: z.ZodOptional<z.ZodString>;
376
+ }, z.core.$strict>;
377
+ readonly description: "Quick capture — a raw inbox item with no structure required.";
378
+ readonly exampleInclude: readonly ["notes"];
379
+ readonly check: (op: Extract<BatchOperation, {
380
+ op: "capture";
381
+ }>, ctx: OpCheckContext) => {
382
+ slug: string;
383
+ errors: string[];
384
+ created: boolean;
385
+ primaryCode: "SLUG_EXISTS" | "NOT_FOUND" | undefined;
386
+ };
387
+ }, {
388
+ readonly name: "link";
389
+ readonly op: "link";
390
+ readonly schema: z.ZodObject<{
391
+ op: z.ZodLiteral<"link">;
392
+ slug: z.ZodString;
393
+ target: z.ZodString;
394
+ relation: z.ZodEnum<{
395
+ parent: "parent";
396
+ related: "related";
397
+ }>;
398
+ }, z.core.$strict>;
399
+ readonly description: "Add a parent or related link between two entities.";
400
+ readonly exampleInclude: readonly [];
401
+ readonly check: (op: Extract<BatchOperation, {
402
+ op: "link";
403
+ }>, ctx: OpCheckContext) => {
404
+ slug: string;
405
+ errors: string[];
406
+ primaryCode: "SLUG_EXISTS" | "NOT_FOUND" | undefined;
407
+ };
408
+ }, {
409
+ readonly name: "unlink";
410
+ readonly op: "unlink";
411
+ readonly schema: z.ZodObject<{
412
+ op: z.ZodLiteral<"unlink">;
413
+ slug: z.ZodString;
414
+ target: z.ZodString;
415
+ relation: z.ZodEnum<{
416
+ parent: "parent";
417
+ related: "related";
418
+ }>;
419
+ }, z.core.$strict>;
420
+ readonly description: "Remove a parent or related link between two entities.";
421
+ readonly exampleInclude: readonly [];
422
+ readonly check: (op: Extract<BatchOperation, {
423
+ op: "unlink";
424
+ }>, ctx: OpCheckContext) => {
425
+ slug: string;
426
+ errors: string[];
427
+ primaryCode: "SLUG_EXISTS" | "NOT_FOUND" | undefined;
428
+ };
429
+ }, {
430
+ readonly name: "promote";
431
+ readonly op: "promote";
432
+ readonly schema: z.ZodObject<{
433
+ op: z.ZodLiteral<"promote">;
434
+ slug: z.ZodString;
435
+ target: z.ZodEnum<{
436
+ entity: "entity";
437
+ project: "project";
438
+ knowledge: "knowledge";
439
+ }>;
440
+ }, z.core.$strict>;
441
+ readonly description: "Promote a capture to entity/project/knowledge, or an entity to project.";
442
+ readonly exampleInclude: readonly [];
443
+ readonly check: (op: Extract<BatchOperation, {
444
+ op: "promote";
445
+ }>, ctx: OpCheckContext) => {
446
+ slug: string;
447
+ errors: string[];
448
+ primaryCode: "SLUG_EXISTS" | "NOT_FOUND" | undefined;
449
+ };
450
+ }];
451
+ /** Every op the table defines. The Apply table (src/apply.ts) is keyed by this
452
+ * union, so a spec row added here without an apply arm fails to build. */
453
+ export type OpSpecName = (typeof OP_SPEC_ROWS)[number]['name'];
454
+ export declare const OP_SPECS: readonly (OpSpec & {
455
+ name: OpSpecName;
456
+ })[];
457
+ /** Find the spec for a (shape-valid) operation. */
458
+ export declare function specFor(op: BatchOperation): OpSpec & {
459
+ name: OpSpecName;
460
+ };
461
+ /** Op names for error text ("expected one of […]") — derived, never hardcoded. */
462
+ export declare function validOpNames(): string[];
463
+ /** Ops whose payload addresses an existing file by `slug` — derived from the
464
+ * Zod shapes, so a new slug-bearing op picks up slug-level rules (the
465
+ * NOT_FOUND precedence on shape failure in validateBatchCore) without a
466
+ * hand-kept list. */
467
+ export declare function slugBearingOpNames(): string[];
468
+ /** Create kinds for error text — derived from the table. */
469
+ export declare function validCreateKinds(): string[];
470
+ export {};