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.
- package/README.md +83 -32
- package/dist/apply.d.ts +33 -0
- package/dist/apply.js +693 -0
- package/dist/batch-ops.d.ts +372 -26
- package/dist/batch-ops.js +355 -73
- package/dist/cli/args.d.ts +48 -6
- package/dist/cli/args.js +74 -9
- package/dist/cli/batch-errors.js +19 -11
- package/dist/cli/block-hook.d.ts +9 -0
- package/dist/cli/block-hook.js +90 -0
- package/dist/cli/commands-schema.js +2 -0
- package/dist/cli/commands.d.ts +28 -3
- package/dist/cli/commands.js +440 -157
- package/dist/cli/format.d.ts +7 -3
- package/dist/cli/format.js +27 -10
- package/dist/cli/index.d.ts +55 -0
- package/dist/cli/index.js +215 -153
- package/dist/cli/install.d.ts +53 -0
- package/dist/cli/install.js +297 -0
- package/dist/cli/onboard.d.ts +15 -2
- package/dist/cli/onboard.js +265 -90
- package/dist/cli/resolve-vault.d.ts +11 -4
- package/dist/cli/resolve-vault.js +13 -11
- package/dist/cli/schema-introspect.js +4 -3
- package/dist/cli/upgrade.d.ts +51 -0
- package/dist/cli/upgrade.js +351 -0
- package/dist/closest.d.ts +8 -0
- package/dist/closest.js +65 -0
- package/dist/contracts.d.ts +65 -6
- package/dist/contracts.js +148 -23
- package/dist/dates.d.ts +10 -0
- package/dist/dates.js +27 -0
- package/dist/db.d.ts +40 -2
- package/dist/db.js +363 -66
- package/dist/digest.d.ts +6 -4
- package/dist/digest.js +28 -17
- package/dist/document.d.ts +135 -88
- package/dist/document.js +665 -379
- package/dist/export-okf.d.ts +13 -0
- package/dist/export-okf.js +50 -20
- package/dist/git.js +165 -48
- package/dist/harness.d.ts +58 -0
- package/dist/harness.js +50 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +301 -826
- package/dist/knowledge-index.d.ts +23 -1
- package/dist/knowledge-index.js +62 -6
- package/dist/merge.d.ts +1 -1
- package/dist/merge.js +98 -64
- package/dist/near-match.d.ts +9 -0
- package/dist/near-match.js +34 -0
- package/dist/schema.js +4 -4
- package/dist/stale.d.ts +41 -0
- package/dist/stale.js +43 -0
- package/dist/stopwords.d.ts +6 -0
- package/dist/stopwords.js +25 -0
- package/dist/surfaces/items.d.ts +366 -0
- package/dist/surfaces/items.js +523 -0
- package/dist/surfaces/surfaces.d.ts +32 -0
- package/dist/surfaces/surfaces.js +230 -0
- package/dist/templates.d.ts +6 -0
- package/dist/templates.js +27 -27
- package/dist/types.d.ts +78 -22
- package/dist/validate.d.ts +7 -0
- package/dist/validate.js +109 -0
- package/dist/vault.d.ts +18 -0
- package/dist/vault.js +51 -5
- package/package.json +4 -3
- package/skill/hafez/SKILL.md +68 -0
- package/skill/hafez-save/SKILL.md +29 -0
- package/dist/cli/help-agent.d.ts +0 -1
- package/dist/cli/help-agent.js +0 -186
- package/dist/query.d.ts +0 -24
- package/dist/query.js +0 -169
- package/skill/SKILL.md +0 -196
package/dist/contracts.js
CHANGED
|
@@ -1,24 +1,48 @@
|
|
|
1
|
+
// --- Canonical enum tuples (single source of truth) ---
|
|
2
|
+
// Every consumer (file validators, the Op Spec table, help renderer, and the
|
|
3
|
+
// enum unions in types.ts) imports these — no other file may declare local
|
|
4
|
+
// copies, and the contracts below are built out of them rather than beside
|
|
5
|
+
// them.
|
|
6
|
+
export const ENTITY_TYPES = ['capture', 'entity', 'project'];
|
|
7
|
+
export const ENTITY_STATUSES = ['active', 'paused', 'done'];
|
|
8
|
+
export const SESSION_LOG_TYPES = ['progress', 'decision', 'blocker', 'research'];
|
|
9
|
+
export const CONFIDENCE_LEVELS = ['observation', 'pattern', 'principle'];
|
|
10
|
+
// 'insight' is the subtype (frontmatter classification), 'Synthesis' is the section heading.
|
|
11
|
+
// The rename was insight→synthesis for the section/field only; the subtype stays 'insight'.
|
|
12
|
+
export const VALID_SUBTYPES = ['insight', 'plan'];
|
|
13
|
+
/** The item frontmatter contract, shared by all three item types — they
|
|
14
|
+
* differ in sections and lifecycle, never in which fields are mandatory.
|
|
15
|
+
* schema.validateEntityFrontmatter enforces exactly this list (parity test in
|
|
16
|
+
* tests/contracts.test.ts). */
|
|
17
|
+
const ITEM_REQUIRED = ['name', 'type', 'status', 'created', 'last-touched'];
|
|
18
|
+
/** Optional frontmatter for the types that can sit in a hierarchy. A capture
|
|
19
|
+
* has not been triaged yet, so it carries neither links nor staleness. */
|
|
20
|
+
const ITEM_OPTIONAL = ['domain', 'parent', 'related', 'tags', 'staleness-days'];
|
|
1
21
|
const CAPTURE = {
|
|
2
22
|
type: 'capture',
|
|
3
23
|
description: 'Quick capture. A link, a thought, a bug report. No structure required — just get it in.',
|
|
4
24
|
kind: 'item',
|
|
5
|
-
requiredFields:
|
|
25
|
+
requiredFields: ITEM_REQUIRED,
|
|
6
26
|
optionalFields: ['domain', 'tags'],
|
|
7
|
-
|
|
27
|
+
// A capture is triage-stage: it is either open or dealt with, never paused.
|
|
28
|
+
validStatuses: ENTITY_STATUSES.filter(s => s !== 'paused'),
|
|
8
29
|
defaultSections: ['Notes'],
|
|
9
30
|
// Brief/Next Actions: the CLI never type-gated setBrief/addNextAction, so captures
|
|
10
31
|
// carrying a delivery brief and actions are established practice — the contract
|
|
11
|
-
// follows observed behaviour (decided 2026-07-19).
|
|
12
|
-
|
|
32
|
+
// follows observed behaviour (decided 2026-07-19). Current State likewise:
|
|
33
|
+
// update --current-state is kind-gated, not type-gated, so captures can carry
|
|
34
|
+
// it — omitting it here made the heading non-structural under the per-type
|
|
35
|
+
// Document binding and a later Brief rewrite silently deleted the section.
|
|
36
|
+
optionalSections: ['Session Log', 'Brief', 'Next Actions', 'Current State'],
|
|
13
37
|
canPromoteTo: ['entity', 'project', 'knowledge'],
|
|
14
38
|
};
|
|
15
39
|
const ENTITY = {
|
|
16
40
|
type: 'entity',
|
|
17
41
|
description: 'Tracked work with substance. A bug, feature, decision, or task. The atomic unit of work.',
|
|
18
42
|
kind: 'item',
|
|
19
|
-
requiredFields:
|
|
20
|
-
optionalFields:
|
|
21
|
-
validStatuses: [
|
|
43
|
+
requiredFields: ITEM_REQUIRED,
|
|
44
|
+
optionalFields: ITEM_OPTIONAL,
|
|
45
|
+
validStatuses: [...ENTITY_STATUSES],
|
|
22
46
|
defaultSections: ['Context', 'Session Log'],
|
|
23
47
|
optionalSections: ['Brief', 'Next Actions', 'Current State'],
|
|
24
48
|
canPromoteTo: ['project'],
|
|
@@ -27,9 +51,9 @@ const PROJECT = {
|
|
|
27
51
|
type: 'project',
|
|
28
52
|
description: 'Scoped effort with goals and deliverables. Can have children. Can be finite or perpetual.',
|
|
29
53
|
kind: 'item',
|
|
30
|
-
requiredFields:
|
|
31
|
-
optionalFields:
|
|
32
|
-
validStatuses: [
|
|
54
|
+
requiredFields: ITEM_REQUIRED,
|
|
55
|
+
optionalFields: ITEM_OPTIONAL,
|
|
56
|
+
validStatuses: [...ENTITY_STATUSES],
|
|
33
57
|
defaultSections: ['Purpose', 'Goals', 'Session Log'],
|
|
34
58
|
optionalSections: ['Brief', 'Next Actions', 'Current State', 'Open Questions'],
|
|
35
59
|
canPromoteTo: [],
|
|
@@ -58,22 +82,26 @@ export function getContract(type) {
|
|
|
58
82
|
throw new Error(`Unknown type: ${type}. Valid types: ${Object.keys(CONTRACT_MAP).join(', ')}`);
|
|
59
83
|
return contract;
|
|
60
84
|
}
|
|
61
|
-
|
|
85
|
+
/** Every section a type's contract declares, default and optional alike —
|
|
86
|
+
* the one place the two lists are concatenated (sectionsFor and hasCapability
|
|
87
|
+
* both answer from it). */
|
|
88
|
+
function contractSections(type) {
|
|
62
89
|
const contract = getContract(type);
|
|
63
|
-
return contract.defaultSections
|
|
90
|
+
return [...contract.defaultSections, ...contract.optionalSections];
|
|
64
91
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
export const
|
|
72
|
-
// 'insight' is the subtype (frontmatter classification), 'Synthesis' is the section heading.
|
|
73
|
-
// The rename was insight→synthesis for the section/field only; the subtype stays 'insight'.
|
|
74
|
-
export const VALID_SUBTYPES = ['insight', 'plan'];
|
|
92
|
+
export function hasCapability(type, section) {
|
|
93
|
+
return contractSections(type).includes(section);
|
|
94
|
+
}
|
|
95
|
+
/** A knowledge note with no persisted subtype is an insight — the one place
|
|
96
|
+
* that default lives. Every consumer (templates, index rows, exports) reads
|
|
97
|
+
* it from here so classification can't drift between surfaces. */
|
|
98
|
+
export const DEFAULT_KNOWLEDGE_SUBTYPE = 'insight';
|
|
75
99
|
// --- Alias table ---
|
|
76
|
-
// Declared-alias fields
|
|
100
|
+
// Declared-alias fields, keyed by the op path they may appear on and mapped to
|
|
101
|
+
// their canonical name. The Op Spec layer (normalizeAliases in batch-ops.ts)
|
|
102
|
+
// normalizes them once, before validation, so every entry point applies the same
|
|
103
|
+
// canonical op; an op path absent from this table (create.entity.fields.insight)
|
|
104
|
+
// is the kind gate — the strict shape rejects the alias there.
|
|
77
105
|
// schema-introspect cannot infer these from Zod alone (both are declared .optional()),
|
|
78
106
|
// so rendering code reads this table to strip aliased keys from user-facing output.
|
|
79
107
|
export const ALIAS_KEYS = {
|
|
@@ -91,3 +119,100 @@ export const APPEND_ONLY_SECTIONS = new Set(['Evidence', 'Sources']);
|
|
|
91
119
|
/** Session-file sections. Sessions have no TypeContract (they are not typed
|
|
92
120
|
* entities), but their headings are still structural for Document splitting. */
|
|
93
121
|
export const SESSION_SECTIONS = ['Summary', 'Entities Touched', 'Decisions'];
|
|
122
|
+
/** Statuses a plan-subtype knowledge note may carry. Plans are tracked work
|
|
123
|
+
* with a lifecycle; the file validator and the mutation gate read this one
|
|
124
|
+
* tuple so they cannot drift. */
|
|
125
|
+
export const PLAN_STATUSES = ['active', 'done'];
|
|
126
|
+
/** Statuses by knowledge subtype. An empty list means `status` is not part of
|
|
127
|
+
* that subtype's contract at all — mutations setting it are rejected. */
|
|
128
|
+
export const SUBTYPE_STATUSES = {
|
|
129
|
+
insight: [],
|
|
130
|
+
plan: PLAN_STATUSES,
|
|
131
|
+
};
|
|
132
|
+
/** Sections a document of this shape can carry — the one answer to "would
|
|
133
|
+
* text written into section X survive on this document?". */
|
|
134
|
+
export function sectionsFor(target) {
|
|
135
|
+
if (target.kind === 'knowledge') {
|
|
136
|
+
return [...SUBTYPE_SECTIONS[target.subtype ?? DEFAULT_KNOWLEDGE_SUBTYPE]];
|
|
137
|
+
}
|
|
138
|
+
return contractSections(target.type);
|
|
139
|
+
}
|
|
140
|
+
/** Statuses this document may carry. Empty ⇒ `status` is not a field of its
|
|
141
|
+
* contract, so setting it is a validation error. */
|
|
142
|
+
export function statusesFor(target) {
|
|
143
|
+
return target.kind === 'knowledge'
|
|
144
|
+
? SUBTYPE_STATUSES[target.subtype ?? DEFAULT_KNOWLEDGE_SUBTYPE]
|
|
145
|
+
: getContract(target.type).validStatuses;
|
|
146
|
+
}
|
|
147
|
+
/** Create-op fields that write their text into a named body section. The
|
|
148
|
+
* chosen template decides whether that section exists; when it doesn't, the
|
|
149
|
+
* text has nowhere to land, so the op is rejected (see `unreachableFields`).
|
|
150
|
+
* Update-op content fields are absent on purpose — `setSection` /
|
|
151
|
+
* `appendToSection` create a missing section, so update never loses text. */
|
|
152
|
+
export const CREATE_FIELD_SECTIONS = {
|
|
153
|
+
purpose: 'Purpose',
|
|
154
|
+
notes: 'Notes',
|
|
155
|
+
brief: 'Brief',
|
|
156
|
+
add_action: 'Next Actions',
|
|
157
|
+
add_actions: 'Next Actions',
|
|
158
|
+
synthesis: 'Synthesis',
|
|
159
|
+
};
|
|
160
|
+
/** Fields present in `fields` whose target section this document cannot hold.
|
|
161
|
+
* Policy is reject-never-route: text is never silently dropped and never
|
|
162
|
+
* redirected into a section the caller did not name. */
|
|
163
|
+
export function unreachableFields(target, fields) {
|
|
164
|
+
const available = new Set(sectionsFor(target));
|
|
165
|
+
return Object.entries(CREATE_FIELD_SECTIONS)
|
|
166
|
+
.filter(([field, section]) => fields[field] !== undefined && !available.has(section))
|
|
167
|
+
.map(([field, section]) => ({ field, section }));
|
|
168
|
+
}
|
|
169
|
+
/** Human label for a target, used in every gate's error text. */
|
|
170
|
+
export function describeTarget(target) {
|
|
171
|
+
return target.kind === 'entity'
|
|
172
|
+
? `type '${target.type}'`
|
|
173
|
+
: `knowledge subtype '${target.subtype ?? DEFAULT_KNOWLEDGE_SUBTYPE}'`;
|
|
174
|
+
}
|
|
175
|
+
export function footerForm(target) {
|
|
176
|
+
if (target.kind === 'knowledge')
|
|
177
|
+
return target.subtype ?? DEFAULT_KNOWLEDGE_SUBTYPE;
|
|
178
|
+
return target.type === 'capture' ? 'capture' : 'entity';
|
|
179
|
+
}
|
|
180
|
+
/** The update fields each Footer names, in the order it names them. Every
|
|
181
|
+
* other field that contract's update accepts is in WRITE_LINE_OMITS with its
|
|
182
|
+
* reason; drift check 3 (tests/read-footer.test.ts) holds the two together
|
|
183
|
+
* against the Op Spec update shape and the kind gate. */
|
|
184
|
+
export const WRITE_LINE_FIELDS = {
|
|
185
|
+
entity: ['session_log', 'complete_action', 'remove_action', 'add_actions', 'brief', 'current_state', 'related', 'parent'],
|
|
186
|
+
insight: ['add_evidence', 'add_source', 'synthesis', 'confidence', 'domain', 'related'],
|
|
187
|
+
plan: ['status', 'domain', 'related'],
|
|
188
|
+
};
|
|
189
|
+
const SET_AT_CREATE = 'set at create, rarely rewritten; `hafez schema update` has it';
|
|
190
|
+
const INSIGHT_ALIAS = 'an alias of synthesis';
|
|
191
|
+
const PLAN_BODY = 'a plan\'s body is Goal, Steps and Dependencies, which no op writes';
|
|
192
|
+
/** Update fields a contract accepts that its Footer leaves out, and why. */
|
|
193
|
+
export const WRITE_LINE_OMITS = {
|
|
194
|
+
entity: {
|
|
195
|
+
status: 'a lifecycle change, not a write-back: the `hafez` skill\'s rare ops carry the status line',
|
|
196
|
+
agent: 'detected from the Harness; the override is never shown',
|
|
197
|
+
add_action: 'the one-line form of add_actions, written by the same flag',
|
|
198
|
+
clear_actions: 'drops lines unseen; the Footer drops one line by its Handle',
|
|
199
|
+
description: SET_AT_CREATE,
|
|
200
|
+
resource: SET_AT_CREATE,
|
|
201
|
+
domain: SET_AT_CREATE,
|
|
202
|
+
tags: SET_AT_CREATE,
|
|
203
|
+
},
|
|
204
|
+
insight: {
|
|
205
|
+
insight: INSIGHT_ALIAS,
|
|
206
|
+
description: SET_AT_CREATE,
|
|
207
|
+
tags: SET_AT_CREATE,
|
|
208
|
+
},
|
|
209
|
+
plan: {
|
|
210
|
+
synthesis: PLAN_BODY,
|
|
211
|
+
add_evidence: PLAN_BODY,
|
|
212
|
+
add_source: PLAN_BODY,
|
|
213
|
+
insight: INSIGHT_ALIAS,
|
|
214
|
+
confidence: 'an insight matures by confidence; a plan moves by status',
|
|
215
|
+
description: SET_AT_CREATE,
|
|
216
|
+
tags: SET_AT_CREATE,
|
|
217
|
+
},
|
|
218
|
+
};
|
package/dist/dates.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** The local calendar day as YYYY-MM-DD. The single source of "today". */
|
|
2
|
+
export declare function localDay(d?: Date): string;
|
|
3
|
+
/**
|
|
4
|
+
* Bare YYYY-MM-DD → local midnight, for git's approxidate. A date-only
|
|
5
|
+
* `--since` is otherwise filled with the *current* time of day ("since right
|
|
6
|
+
* now"), and any explicit instant must anchor to the same local day boundary
|
|
7
|
+
* the stamps and query comparisons use. Relative forms (`7.days.ago`) are
|
|
8
|
+
* already local and pass through untouched.
|
|
9
|
+
*/
|
|
10
|
+
export declare function normalizeSinceDate(since: string): string;
|
package/dist/dates.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// src/dates.ts
|
|
2
|
+
// The vault's one calendar-day convention: the LOCAL day.
|
|
3
|
+
//
|
|
4
|
+
// A hafez vault is personal — "today" means the user's today, so every
|
|
5
|
+
// surface that names a day (created / last-touched / session-log stamping,
|
|
6
|
+
// the dates `query --since/--before` compare against, and the `--since` the
|
|
7
|
+
// changelog hands to git) resolves to the local calendar day. Deriving
|
|
8
|
+
// stamps from UTC while comparing against local-midnight boundaries made the
|
|
9
|
+
// same date mean different days: west of UTC after ~13:00 local, a fresh
|
|
10
|
+
// entity was stamped with tomorrow.
|
|
11
|
+
function pad(n) {
|
|
12
|
+
return String(n).padStart(2, '0');
|
|
13
|
+
}
|
|
14
|
+
/** The local calendar day as YYYY-MM-DD. The single source of "today". */
|
|
15
|
+
export function localDay(d = new Date()) {
|
|
16
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Bare YYYY-MM-DD → local midnight, for git's approxidate. A date-only
|
|
20
|
+
* `--since` is otherwise filled with the *current* time of day ("since right
|
|
21
|
+
* now"), and any explicit instant must anchor to the same local day boundary
|
|
22
|
+
* the stamps and query comparisons use. Relative forms (`7.days.ago`) are
|
|
23
|
+
* already local and pass through untouched.
|
|
24
|
+
*/
|
|
25
|
+
export function normalizeSinceDate(since) {
|
|
26
|
+
return /^\d{4}-\d{2}-\d{2}$/.test(since) ? `${since}T00:00:00` : since;
|
|
27
|
+
}
|
package/dist/db.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { type VaultIndexRow } from './knowledge-index.js';
|
|
2
|
+
import type { SearchResult, VaultStats, QueryResult, KnowledgeQueryResult, UnifiedResult, EntityQueryOpts, KnowledgeQueryOpts, UnifiedQueryOpts, SortField } from './types.js';
|
|
3
|
+
export declare const SCHEMA_VERSION = "11";
|
|
3
4
|
interface IndexItem {
|
|
4
5
|
slug: string;
|
|
5
6
|
kind: 'entity' | 'knowledge';
|
|
@@ -38,7 +39,29 @@ export interface HafezIndex {
|
|
|
38
39
|
queryItems(opts: QueryOpts): IndexQueryResult;
|
|
39
40
|
search(query: string, kind?: 'entity' | 'knowledge' | 'all'): SearchResult[];
|
|
40
41
|
getStats(): VaultStats;
|
|
42
|
+
/** Every indexed document, in the shape index.md is rendered from. */
|
|
43
|
+
indexEntries(): VaultIndexRow[];
|
|
41
44
|
close(): void;
|
|
45
|
+
queryEntities(opts?: EntityQueryOpts): {
|
|
46
|
+
items: QueryResult[];
|
|
47
|
+
total: number;
|
|
48
|
+
};
|
|
49
|
+
queryChildren(parentSlug: string): {
|
|
50
|
+
items: QueryResult[];
|
|
51
|
+
total: number;
|
|
52
|
+
};
|
|
53
|
+
queryRelatedTo(slug: string, relation?: string): {
|
|
54
|
+
items: UnifiedResult[];
|
|
55
|
+
total: number;
|
|
56
|
+
};
|
|
57
|
+
queryKnowledge(opts?: KnowledgeQueryOpts): {
|
|
58
|
+
items: KnowledgeQueryResult[];
|
|
59
|
+
total: number;
|
|
60
|
+
};
|
|
61
|
+
queryUnified(opts?: UnifiedQueryOpts): {
|
|
62
|
+
items: UnifiedResult[];
|
|
63
|
+
total: number;
|
|
64
|
+
};
|
|
42
65
|
}
|
|
43
66
|
export interface QueryOpts {
|
|
44
67
|
kind?: 'entity' | 'knowledge' | 'all';
|
|
@@ -61,8 +84,23 @@ export interface QueryOpts {
|
|
|
61
84
|
limit?: number;
|
|
62
85
|
offset?: number;
|
|
63
86
|
}
|
|
87
|
+
/** @internal */
|
|
88
|
+
export declare function __setAfterScanHook(fn: (() => void) | null): void;
|
|
64
89
|
export declare function createIndex(vaultPath: string): HafezIndex;
|
|
65
90
|
export declare function createIndex(vaultPath: string, opts: {
|
|
66
91
|
readonly: true;
|
|
67
92
|
}): HafezIndex | null;
|
|
93
|
+
/** Opts a branch cannot map into SQL. Declared per branch and rejected on
|
|
94
|
+
* sight: the CLI has rejected these since 43124ba, but the rule lived only
|
|
95
|
+
* there, so a library caller got the silent drop the CLI had already closed.
|
|
96
|
+
* Asserted against the CLI's flag matrix in query-surface.test.ts. */
|
|
97
|
+
export declare const ENTITY_ONLY_OPTS: readonly ["filter", "type", "parent"];
|
|
98
|
+
export declare const KNOWLEDGE_ONLY_OPTS: readonly ["confidence", "subtype"];
|
|
99
|
+
/** Every opt any branch might carry, flattened. Only the unified read uses it,
|
|
100
|
+
* and only to check: the checks must see an opt the caller's own type forbids,
|
|
101
|
+
* because an untyped caller can still send it. */
|
|
102
|
+
export type UnmappableCheckOpts = Omit<EntityQueryOpts, 'sort_by'> & Omit<KnowledgeQueryOpts, 'sort_by'> & {
|
|
103
|
+
kind?: 'entity' | 'knowledge' | 'all';
|
|
104
|
+
sort_by?: SortField;
|
|
105
|
+
};
|
|
68
106
|
export {};
|