things-api 0.10.0 → 0.12.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 +50 -13
- package/dist/audit/schema.d.ts +7 -0
- package/dist/audit/schema.js.map +1 -1
- package/dist/cli/clock.d.ts +8 -0
- package/dist/cli/clock.js +24 -0
- package/dist/cli/clock.js.map +1 -0
- package/dist/cli/commands/area.d.ts +18 -11
- package/dist/cli/commands/area.js +61 -74
- package/dist/cli/commands/area.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +1 -2
- package/dist/cli/commands/doctor.js +11 -1
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/install-skill.d.ts +60 -0
- package/dist/cli/commands/install-skill.js +256 -0
- package/dist/cli/commands/install-skill.js.map +1 -0
- package/dist/cli/commands/mcp.js +9 -0
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/project.d.ts +1 -0
- package/dist/cli/commands/project.js +27 -34
- package/dist/cli/commands/project.js.map +1 -1
- package/dist/cli/commands/reads.d.ts +15 -2
- package/dist/cli/commands/reads.js +144 -44
- package/dist/cli/commands/reads.js.map +1 -1
- package/dist/cli/commands/setup.js +7 -2
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/show.js +38 -14
- package/dist/cli/commands/show.js.map +1 -1
- package/dist/cli/commands/todo.js +15 -9
- package/dist/cli/commands/todo.js.map +1 -1
- package/dist/cli/commands/writes.js +797 -174
- package/dist/cli/commands/writes.js.map +1 -1
- package/dist/cli/did-you-mean.d.ts +14 -3
- package/dist/cli/did-you-mean.js +26 -3
- package/dist/cli/did-you-mean.js.map +1 -1
- package/dist/cli/glyphs.d.ts +32 -2
- package/dist/cli/glyphs.js +83 -12
- package/dist/cli/glyphs.js.map +1 -1
- package/dist/cli/help.js +121 -16
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/main.js +33 -2
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/move-hint.d.ts +46 -0
- package/dist/cli/move-hint.js +196 -0
- package/dist/cli/move-hint.js.map +1 -0
- package/dist/cli/period.d.ts +2 -8
- package/dist/cli/period.js +44 -30
- package/dist/cli/period.js.map +1 -1
- package/dist/cli/read-driver.d.ts +43 -5
- package/dist/cli/read-driver.js +91 -15
- package/dist/cli/read-driver.js.map +1 -1
- package/dist/cli/render.d.ts +19 -8
- package/dist/cli/render.js +70 -27
- package/dist/cli/render.js.map +1 -1
- package/dist/cli/resolve-invocation.d.ts +2 -2
- package/dist/cli/resolve-invocation.js +3 -3
- package/dist/cli/resolve-invocation.js.map +1 -1
- package/dist/cli/skill-check.d.ts +27 -0
- package/dist/cli/skill-check.js +99 -0
- package/dist/cli/skill-check.js.map +1 -0
- package/dist/cli/skill.d.ts +70 -0
- package/dist/cli/skill.js +152 -0
- package/dist/cli/skill.js.map +1 -0
- package/dist/cli/tag-filters.d.ts +6 -2
- package/dist/cli/tag-filters.js +8 -6
- package/dist/cli/tag-filters.js.map +1 -1
- package/dist/cli/verb-hint.js +28 -3
- package/dist/cli/verb-hint.js.map +1 -1
- package/dist/cli/version.d.ts +4 -0
- package/dist/cli/version.js +18 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/client.d.ts +171 -27
- package/dist/client.js +279 -40
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +66 -2
- package/dist/config.js +120 -12
- package/dist/config.js.map +1 -1
- package/dist/contracts.d.ts +186 -28
- package/dist/contracts.js +22 -1
- package/dist/contracts.js.map +1 -1
- package/dist/diagnose.d.ts +34 -2
- package/dist/diagnose.js +36 -1
- package/dist/diagnose.js.map +1 -1
- package/dist/index.d.ts +25 -9
- package/dist/index.js +22 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +9 -0
- package/dist/mcp/server.js +1157 -684
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/clock.d.ts +61 -0
- package/dist/model/clock.js +71 -0
- package/dist/model/clock.js.map +1 -0
- package/dist/model/dates.d.ts +26 -3
- package/dist/model/dates.js +84 -3
- package/dist/model/dates.js.map +1 -1
- package/dist/model/entities.d.ts +60 -3
- package/dist/model/entities.js.map +1 -1
- package/dist/model/mappers.d.ts +4 -2
- package/dist/model/mappers.js +66 -9
- package/dist/model/mappers.js.map +1 -1
- package/dist/model/recurrence.d.ts +8 -1
- package/dist/model/recurrence.js.map +1 -1
- package/dist/read/area-filter.d.ts +76 -0
- package/dist/read/area-filter.js +59 -0
- package/dist/read/area-filter.js.map +1 -0
- package/dist/read/area-view.d.ts +12 -12
- package/dist/read/area-view.js +58 -34
- package/dist/read/area-view.js.map +1 -1
- package/dist/read/detail.d.ts +1 -1
- package/dist/read/detail.js +26 -12
- package/dist/read/detail.js.map +1 -1
- package/dist/read/log-boundary.d.ts +1 -1
- package/dist/read/log-boundary.js +13 -3
- package/dist/read/log-boundary.js.map +1 -1
- package/dist/read/predicates.d.ts +18 -0
- package/dist/read/predicates.js +19 -0
- package/dist/read/predicates.js.map +1 -1
- package/dist/read/project-view.d.ts +32 -16
- package/dist/read/project-view.js +80 -45
- package/dist/read/project-view.js.map +1 -1
- package/dist/read/pseudo-area.d.ts +29 -0
- package/dist/read/pseudo-area.js +27 -0
- package/dist/read/pseudo-area.js.map +1 -0
- package/dist/read/queries.d.ts +108 -19
- package/dist/read/queries.js +212 -35
- package/dist/read/queries.js.map +1 -1
- package/dist/read/scope.d.ts +126 -0
- package/dist/read/scope.js +162 -0
- package/dist/read/scope.js.map +1 -0
- package/dist/read/search-rank.d.ts +2 -5
- package/dist/read/shape.d.ts +162 -0
- package/dist/read/shape.js +686 -0
- package/dist/read/shape.js.map +1 -0
- package/dist/read/show-target.d.ts +9 -1
- package/dist/read/show-target.js +45 -4
- package/dist/read/show-target.js.map +1 -1
- package/dist/read/snapshot.d.ts +1 -1
- package/dist/read/snapshot.js +9 -2
- package/dist/read/snapshot.js.map +1 -1
- package/dist/read/stage.d.ts +199 -0
- package/dist/read/stage.js +125 -0
- package/dist/read/stage.js.map +1 -0
- package/dist/read/truncation.d.ts +8 -6
- package/dist/read/truncation.js +35 -10
- package/dist/read/truncation.js.map +1 -1
- package/dist/read/views.d.ts +61 -20
- package/dist/read/views.js +240 -82
- package/dist/read/views.js.map +1 -1
- package/dist/surface-copy.d.ts +9 -0
- package/dist/surface-copy.js +9 -0
- package/dist/surface-copy.js.map +1 -1
- package/dist/write/accessibility-probe.d.ts +1 -1
- package/dist/write/accessibility-probe.js +8 -0
- package/dist/write/accessibility-probe.js.map +1 -1
- package/dist/write/automation-probe.d.ts +1 -1
- package/dist/write/automation-probe.js +8 -0
- package/dist/write/automation-probe.js.map +1 -1
- package/dist/write/batch.d.ts +49 -10
- package/dist/write/batch.js +423 -70
- package/dist/write/batch.js.map +1 -1
- package/dist/write/commands.d.ts +1 -1
- package/dist/write/commands.js +316 -66
- package/dist/write/commands.js.map +1 -1
- package/dist/write/guards.d.ts +1 -1
- package/dist/write/guards.js +94 -10
- package/dist/write/guards.js.map +1 -1
- package/dist/write/heading.d.ts +10 -1
- package/dist/write/heading.js +35 -5
- package/dist/write/heading.js.map +1 -1
- package/dist/write/make-repeating-project.d.ts +2 -2
- package/dist/write/make-repeating-project.js +9 -9
- package/dist/write/make-repeating-project.js.map +1 -1
- package/dist/write/move.d.ts +130 -0
- package/dist/write/move.js +1533 -0
- package/dist/write/move.js.map +1 -0
- package/dist/write/operations.d.ts +105 -19
- package/dist/write/operations.js +56 -7
- package/dist/write/operations.js.map +1 -1
- package/dist/write/opid.d.ts +31 -0
- package/dist/write/opid.js +30 -0
- package/dist/write/opid.js.map +1 -0
- package/dist/write/pipeline.d.ts +122 -3
- package/dist/write/pipeline.js +309 -52
- package/dist/write/pipeline.js.map +1 -1
- package/dist/write/planner.js +8 -1
- package/dist/write/planner.js.map +1 -1
- package/dist/write/pre-state.d.ts +197 -6
- package/dist/write/pre-state.js +427 -20
- package/dist/write/pre-state.js.map +1 -1
- package/dist/write/recurrence-rule-blob.d.ts +65 -0
- package/dist/write/recurrence-rule-blob.js +150 -0
- package/dist/write/recurrence-rule-blob.js.map +1 -0
- package/dist/write/reorder.d.ts +23 -3
- package/dist/write/reorder.js +1871 -85
- package/dist/write/reorder.js.map +1 -1
- package/dist/write/reversibility.js +19 -7
- package/dist/write/reversibility.js.map +1 -1
- package/dist/write/scope-guard.d.ts +31 -0
- package/dist/write/scope-guard.js +162 -0
- package/dist/write/scope-guard.js.map +1 -0
- package/dist/write/undo.js +120 -13
- package/dist/write/undo.js.map +1 -1
- package/dist/write/vectors/applescript.js +16 -7
- package/dist/write/vectors/applescript.js.map +1 -1
- package/dist/write/vectors/registry.d.ts +5 -7
- package/dist/write/vectors/registry.js +49 -2
- package/dist/write/vectors/registry.js.map +1 -1
- package/dist/write/vectors/shortcuts.js +1 -1
- package/dist/write/vectors/shortcuts.js.map +1 -1
- package/dist/write/vectors/simulator.d.ts +44 -0
- package/dist/write/vectors/simulator.js +1192 -0
- package/dist/write/vectors/simulator.js.map +1 -0
- package/dist/write/vectors/types.d.ts +46 -0
- package/dist/write/vectors/ui-certification.d.ts +10 -4
- package/dist/write/vectors/ui-certification.js +43 -10
- package/dist/write/vectors/ui-certification.js.map +1 -1
- package/dist/write/vectors/ui-drag.d.ts +21 -1
- package/dist/write/vectors/ui-drag.js +138 -27
- package/dist/write/vectors/ui-drag.js.map +1 -1
- package/dist/write/vectors/ui-recipes.d.ts +34 -1
- package/dist/write/vectors/ui-recipes.js +217 -6
- package/dist/write/vectors/ui-recipes.js.map +1 -1
- package/dist/write/vectors/ui.d.ts +40 -1
- package/dist/write/vectors/ui.js +196 -39
- package/dist/write/vectors/ui.js.map +1 -1
- package/dist/write/verify/delta.d.ts +127 -2
- package/dist/write/verify/delta.js +255 -16
- package/dist/write/verify/delta.js.map +1 -1
- package/dist/write/verify/poller.d.ts +7 -1
- package/dist/write/verify/poller.js +20 -1
- package/dist/write/verify/poller.js.map +1 -1
- package/package.json +24 -3
- package/schema/envelope.schema.json +383 -0
- package/skills/things-cli/SKILL.md +70 -0
- package/skills/things-cli/references/banner.md +35 -0
- package/skills/things-cli/references/contracts.md +62 -0
- package/skills/things-cli/references/errors.md +49 -0
- package/skills/things-cli/references/gui.md +11 -0
- package/skills/things-cli/references/model.md +60 -0
- package/skills/things-cli/references/ordering.md +71 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { EFFECTIVE_AREA, ReferenceResolutionError, resolveAreaUuid, resolveProjectUuid, } from "./queries.js";
|
|
2
|
+
/**
|
|
3
|
+
* Fail-closed if a requested scope is unresolvable — `things mcp --scope <bogus>`
|
|
4
|
+
* refuses to start, a CLI invocation errors as usage — so the daemon never runs
|
|
5
|
+
* unscoped when a scope was asked for. A subclass of {@link ReferenceResolutionError}
|
|
6
|
+
* so existing usage-class handlers treat it uniformly.
|
|
7
|
+
*/
|
|
8
|
+
export class ScopeResolutionError extends ReferenceResolutionError {
|
|
9
|
+
constructor(message, ref) {
|
|
10
|
+
super(message, { code: "not-found", ref });
|
|
11
|
+
this.name = "ScopeResolutionError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Resolve a scope ref (uuid, uuid-prefix, or unique area/project name) to a
|
|
16
|
+
* pinned {@link ResolvedScope}. Areas win over same-named projects (mirroring
|
|
17
|
+
* `classifyShowTarget`). A to-do / heading / tag ref is a usage error — only an
|
|
18
|
+
* area or a project can be a container. Fail-closed: an unresolvable ref throws
|
|
19
|
+
* {@link ScopeResolutionError}.
|
|
20
|
+
*/
|
|
21
|
+
export function resolveScope(db, ref, source) {
|
|
22
|
+
// Area first (an area outranks a same-named project, like the show router).
|
|
23
|
+
try {
|
|
24
|
+
const uuid = resolveAreaUuid(db, ref, { prefixTier: false });
|
|
25
|
+
const row = db.prepare("SELECT title FROM TMArea WHERE uuid = ?").get(uuid);
|
|
26
|
+
return { kind: "area", uuid, title: row?.title ?? "", source, areaUuid: uuid };
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
// An ambiguous area name is a real conflict — surface it. A plain not-found
|
|
30
|
+
// falls through to project resolution.
|
|
31
|
+
if (err instanceof RangeError && err.message.includes("matches")) {
|
|
32
|
+
throw new ScopeResolutionError(`scope "${ref}" is ambiguous — ${err.message}`, ref);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const uuid = resolveProjectUuid(db, ref, { prefixTier: false });
|
|
37
|
+
const row = db.prepare("SELECT title, area FROM TMTask WHERE uuid = ?").get(uuid);
|
|
38
|
+
return {
|
|
39
|
+
kind: "project",
|
|
40
|
+
uuid,
|
|
41
|
+
title: row?.title ?? "",
|
|
42
|
+
source,
|
|
43
|
+
areaUuid: row?.area ?? null,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
if (err instanceof RangeError && err.message.includes("matches")) {
|
|
48
|
+
throw new ScopeResolutionError(`scope "${ref}" is ambiguous — ${err.message}`, ref);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
throw new ScopeResolutionError(`scope "${ref}" matches no area or project — a scope must name a container (only areas and ` +
|
|
52
|
+
"projects can be a container; to-dos, headings, and tags cannot)", ref);
|
|
53
|
+
}
|
|
54
|
+
/** The `meta.scope` projection of a resolved scope (drops the internal `areaUuid`). */
|
|
55
|
+
export function scopeMeta(scope) {
|
|
56
|
+
return { kind: scope.kind, uuid: scope.uuid, title: scope.title, source: scope.source };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The entity-level membership predicate — the SAME relation as
|
|
60
|
+
* {@link scopeMembershipSql}, for an already-shaped view row. Area scope: the
|
|
61
|
+
* row's EFFECTIVE area is the scope (its `area` Ref, which queries.ts already
|
|
62
|
+
* resolves transitively). Project scope: the row IS the project, is a direct
|
|
63
|
+
* child, or is nested under one of the project's headings.
|
|
64
|
+
*/
|
|
65
|
+
export function inScopeItem(item, scope) {
|
|
66
|
+
if (scope.kind === "area") {
|
|
67
|
+
const area = "area" in item ? item.area : null;
|
|
68
|
+
return area != null && area.uuid === scope.uuid;
|
|
69
|
+
}
|
|
70
|
+
const p = scope.uuid;
|
|
71
|
+
if (item.uuid === p)
|
|
72
|
+
return true;
|
|
73
|
+
const project = "project" in item ? item.project : null;
|
|
74
|
+
if (project != null && project.uuid === p)
|
|
75
|
+
return true;
|
|
76
|
+
const hp = "headingProject" in item ? item.headingProject : undefined;
|
|
77
|
+
if (hp != null && hp.uuid === p)
|
|
78
|
+
return true;
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The SQL fragment on alias `t` — the single membership source the leak-critical
|
|
83
|
+
* query paths AND the write ancestry check share. Area: the effective-area
|
|
84
|
+
* COALESCE equals the scope. Project: the row is the project, its direct child,
|
|
85
|
+
* or a heading-nested child.
|
|
86
|
+
*/
|
|
87
|
+
export function scopeMembershipSql(scope) {
|
|
88
|
+
if (scope.kind === "area") {
|
|
89
|
+
return { where: `${EFFECTIVE_AREA} = ?`, binds: [scope.uuid] };
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
where: "(t.uuid = ? OR t.project = ? OR t.heading IN " +
|
|
93
|
+
"(SELECT uuid FROM TMTask WHERE type = 2 AND project = ?))",
|
|
94
|
+
binds: [scope.uuid, scope.uuid, scope.uuid],
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/** True when the given uuid is an in-scope TMTask row (single-row leak paths, write parity). */
|
|
98
|
+
export function isUuidInScope(db, uuid, scope) {
|
|
99
|
+
const mem = scopeMembershipSql(scope);
|
|
100
|
+
const row = db
|
|
101
|
+
.prepare(`SELECT 1 AS ok FROM TMTask t WHERE t.uuid = ? AND ${mem.where} LIMIT 1`)
|
|
102
|
+
.get(uuid, ...mem.binds);
|
|
103
|
+
return row !== undefined;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The membership clause for {@link resolveTaskUuidPrefix} (alias `t`): the same
|
|
107
|
+
* fragment as {@link scopeMembershipSql}, so an out-of-scope uuid resolves to
|
|
108
|
+
* "not found" through the identical code path a nonexistent one does.
|
|
109
|
+
*/
|
|
110
|
+
export function taskMembershipClause(scope) {
|
|
111
|
+
return scopeMembershipSql(scope);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The membership clause for {@link resolveNamedRef} over TMTask projects
|
|
115
|
+
* (UNqualified columns — that resolver aliases nothing). A project carries its
|
|
116
|
+
* area directly (no inheritance), so area scope compares `area`; project scope
|
|
117
|
+
* pins the one project uuid.
|
|
118
|
+
*/
|
|
119
|
+
export function namedProjectClause(scope) {
|
|
120
|
+
if (scope.kind === "area")
|
|
121
|
+
return { where: "area = ?", binds: [scope.uuid] };
|
|
122
|
+
return { where: "uuid = ?", binds: [scope.uuid] };
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* The membership clause for {@link resolveNamedRef} over TMArea (UNqualified).
|
|
126
|
+
* Area scope: the one scope area. Project scope: the project's own area (an
|
|
127
|
+
* area-less project has none, so nothing resolves — `0`).
|
|
128
|
+
*/
|
|
129
|
+
export function namedAreaClause(scope) {
|
|
130
|
+
if (scope.kind === "area")
|
|
131
|
+
return { where: "uuid = ?", binds: [scope.uuid] };
|
|
132
|
+
return scope.areaUuid === null
|
|
133
|
+
? { where: "0", binds: [] }
|
|
134
|
+
: { where: "uuid = ?", binds: [scope.areaUuid] };
|
|
135
|
+
}
|
|
136
|
+
/** Filter a flat view (upcoming/logbook/trash/search/changes) to in-scope rows. */
|
|
137
|
+
export function filterListByScope(items, scope) {
|
|
138
|
+
return items.filter((i) => inScopeItem(i, scope));
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Filter the grouped sidebar catalogue (anytime/someday) to in-scope rows: each
|
|
142
|
+
* section's items are filtered and empty sections drop, so the per-block caps
|
|
143
|
+
* size the survivors.
|
|
144
|
+
*/
|
|
145
|
+
export function filterSectionsByScope(sections, scope) {
|
|
146
|
+
return sections
|
|
147
|
+
.map((s) => ({ area: s.area, items: s.items.filter((i) => inScopeItem(i, scope)) }))
|
|
148
|
+
.filter((s) => s.items.length > 0);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Filter the Today split to in-scope rows, RECOMPUTING the badge over the
|
|
152
|
+
* surviving OPEN members so it never counts a dropped (out-of-scope) row — the
|
|
153
|
+
* same treatment `filterTodayByArea` gives the area filter.
|
|
154
|
+
*/
|
|
155
|
+
export function filterTodayByScope(view, scope, todayIso) {
|
|
156
|
+
const today = view.today.filter((i) => inScopeItem(i, scope));
|
|
157
|
+
const evening = view.evening.filter((i) => inScopeItem(i, scope));
|
|
158
|
+
const open = [...today, ...evening].filter((i) => i.status === "open");
|
|
159
|
+
const dueOrOverdue = open.filter((i) => i.deadline !== null && i.deadline <= todayIso).length;
|
|
160
|
+
return { today, evening, badge: { dueOrOverdue, other: open.length - dueOrOverdue } };
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/read/scope.ts"],"names":[],"mappings":"AAmBA,OAAO,EACL,cAAc,EACd,wBAAwB,EACxB,eAAe,EACf,kBAAkB,GACnB,MAAM,cAAc,CAAC;AA+BtB;;;;;GAKG;AACH,MAAM,OAAO,oBAAqB,SAAQ,wBAAwB;IAChE,YAAY,OAAe,EAAE,GAAW;QACtC,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,EAAgB,EAAE,GAAW,EAAE,MAAmB;IAC7E,4EAA4E;IAC5E,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,eAAe,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7D,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,GAAG,CAAC,IAAI,CAE7D,CAAC;QACd,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACjF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,4EAA4E;QAC5E,uCAAuC;QACvC,IAAI,GAAG,YAAY,UAAU,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACjE,MAAM,IAAI,oBAAoB,CAAC,UAAU,GAAG,oBAAoB,GAAG,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;IACD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,kBAAkB,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;QAChE,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAAC,GAAG,CAAC,IAAI,CAEnE,CAAC;QACd,OAAO;YACL,IAAI,EAAE,SAAS;YACf,IAAI;YACJ,KAAK,EAAE,GAAG,EAAE,KAAK,IAAI,EAAE;YACvB,MAAM;YACN,QAAQ,EAAE,GAAG,EAAE,IAAI,IAAI,IAAI;SAC5B,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,UAAU,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACjE,MAAM,IAAI,oBAAoB,CAAC,UAAU,GAAG,oBAAoB,GAAG,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;IACD,MAAM,IAAI,oBAAoB,CAC5B,UAAU,GAAG,+EAA+E;QAC1F,iEAAiE,EACnE,GAAG,CACJ,CAAC;AACJ,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,SAAS,CAAC,KAAoB;IAC5C,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;AAC1F,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,IAAwB,EAAE,KAAoB;IACxE,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QAC/C,OAAO,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC;IAClD,CAAC;IACD,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC;IACrB,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,OAAO,GAAG,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACxD,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACvD,MAAM,EAAE,GAAG,gBAAgB,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC;IACtE,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7C,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAoB;IACrD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC1B,OAAO,EAAE,KAAK,EAAE,GAAG,cAAc,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;IACjE,CAAC;IACD,OAAO;QACL,KAAK,EACH,+CAA+C;YAC/C,2DAA2D;QAC7D,KAAK,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC;KAC5C,CAAC;AACJ,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,aAAa,CAAC,EAAgB,EAAE,IAAY,EAAE,KAAoB;IAChF,MAAM,GAAG,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,EAAE;SACX,OAAO,CAAC,qDAAqD,GAAG,CAAC,KAAK,UAAU,CAAC;SACjF,GAAG,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,KAAK,CAA+B,CAAC;IACzD,OAAO,GAAG,KAAK,SAAS,CAAC;AAC3B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAoB;IACvD,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAoB;IACrD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;IAC7E,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,KAAoB;IAClD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;IAC7E,OAAO,KAAK,CAAC,QAAQ,KAAK,IAAI;QAC5B,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE;QAC3B,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;AACrD,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,iBAAiB,CAAqB,KAAU,EAAE,KAAoB;IACpF,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAA0B,EAC1B,KAAoB;IAEpB,OAAO,QAAQ;SACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;SACnF,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACvC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAe,EACf,KAAoB,EACpB,QAAiB;IAEjB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAClE,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IACvE,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC,MAAM,CAAC;IAC9F,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,GAAG,YAAY,EAAE,EAAE,CAAC;AACxF,CAAC"}
|
|
@@ -18,12 +18,9 @@ import type { ListItem } from "./views.ts";
|
|
|
18
18
|
export type MatchField = "title" | "notes" | "heading" | "checklist";
|
|
19
19
|
export interface SearchMatch {
|
|
20
20
|
item: ListItem;
|
|
21
|
+
/** The RANK field (strongest match by rank order); the displayed provenance
|
|
22
|
+
* annotation rides the item as `match` and follows its own precedence. */
|
|
21
23
|
field: MatchField;
|
|
22
|
-
/** Present when `field === "heading"`: the heading whose title matched. */
|
|
23
|
-
matchedVia?: {
|
|
24
|
-
kind: "heading";
|
|
25
|
-
title: string;
|
|
26
|
-
};
|
|
27
24
|
}
|
|
28
25
|
export declare function fieldRank(field: MatchField): number;
|
|
29
26
|
/** Containers (projects, areas) sort above to-dos. */
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The read-payload SHAPING transform: the token-economy rules R6 and R7, the
|
|
3
|
+
* universal item-DTO reshapes (R9), and the R10 lifecycle taxonomy — applied at
|
|
4
|
+
* the JSON emit boundary of the read surfaces (the CLI `--json` read envelope,
|
|
5
|
+
* src/cli/read-driver.ts, and the MCP read tool results, src/mcp/server.ts), the
|
|
6
|
+
* same boundaries omit-empty runs at. Shaping runs BEFORE omit-empty. The
|
|
7
|
+
* human-render path keeps the full, unshaped entities, so this is JSON-only.
|
|
8
|
+
*
|
|
9
|
+
* Both R6/R7 are deterministic BY VIEW KIND / SECTION — the emitter knows whether
|
|
10
|
+
* it is inside a single-container view, a lifecycle bucket, or a mixed list —
|
|
11
|
+
* never a per-item heuristic.
|
|
12
|
+
*
|
|
13
|
+
* ## R10 — the `stage` lifecycle taxonomy (every tier, every kind incl. detail)
|
|
14
|
+
* The three former wire fields `start` / `logged` / `trashed` are DELETED from
|
|
15
|
+
* every item and replaced by ONE derived `stage` ∈ `inbox | upcoming | anytime |
|
|
16
|
+
* someday | logbook | trash` (src/read/stage.ts `deriveStage`, the single pure
|
|
17
|
+
* derivation reused by the card bucketing so `stage` can never disagree with the
|
|
18
|
+
* bucket a view puts an item in). Today/evening membership is a SEPARATE
|
|
19
|
+
* presence-keyed axis — `today: true` / `evening: true` (evening implies today) —
|
|
20
|
+
* derived in the mapper with the Today view's own two-arm predicate.
|
|
21
|
+
* - `stage` is DROPPED only where the enclosing node PROVABLY states it — the R6
|
|
22
|
+
* rule (drop only what the node provably says). That is the stage-PURE flat
|
|
23
|
+
* views (inbox, `anytime`, someday, logbook, trash) and the stage-named card
|
|
24
|
+
* sub-buckets (anytime/upcoming/someday/logbook/trash, which the bucketer splits
|
|
25
|
+
* BY stage). The `anytime` catalogue is stage-PURE (R10.2): every member is an
|
|
26
|
+
* Anytime-view row (ANYTIME_SELF) — undated-active, arrived-active, or arrived
|
|
27
|
+
* someday-scheduled — and an ARRIVED dated row derives `anytime` (Upcoming is
|
|
28
|
+
* STRICTLY FUTURE, UPC1), so the field is redundant there.
|
|
29
|
+
* `stage` is KEPT on the stage-MIXED or derived surfaces: the `upcoming` view
|
|
30
|
+
* carries deadline-forecast stage-`anytime`/`someday` rows alongside its
|
|
31
|
+
* future-dated stage-`upcoming` ones — dropping `stage` there would delete
|
|
32
|
+
* non-redundant information — plus `today` (mixes upcoming + anytime-deadline
|
|
33
|
+
* rows), search, changes, the projects/areas listings, the card NODE, and
|
|
34
|
+
* detail.
|
|
35
|
+
* - the former `todaySection` field is RETIRED from the wire entirely (R10.1):
|
|
36
|
+
* `todaySection: "evening"` merely duplicated the `evening: true` marker. It
|
|
37
|
+
* remains an internal entity field (the human render and the write-verify delta
|
|
38
|
+
* still read it); shaping deletes it from the JSON copy.
|
|
39
|
+
*
|
|
40
|
+
* ## R12 — `when`, the derived TIME-AXIS position (replaces startDate + markers)
|
|
41
|
+
* Today/evening membership and the scheduled/projected date collapse onto ONE
|
|
42
|
+
* derived, presence-keyed field `when` (src/read/stage.ts `deriveWhen`): `"today"`
|
|
43
|
+
* / `"evening"` (Today-view membership, from the SAME `today`/`evening` markers the
|
|
44
|
+
* mapper stamps — never re-derived, so `when` can never disagree with the star), a
|
|
45
|
+
* FUTURE ISO date (a strictly-future scheduled row, or a template's projected next
|
|
46
|
+
* occurrence), or absent (unscheduled + not in Today; also an unprojected template
|
|
47
|
+
* and every logged/trashed row). The doctrine line: **`stage` enumerates the
|
|
48
|
+
* sidebar BUCKETS an item lives in; `when` enumerates its TIME POSITIONS (today |
|
|
49
|
+
* evening | a future date).** Someday is deliberately NOT a `when` value (it is a
|
|
50
|
+
* bucket → stage). Tier/drop rules:
|
|
51
|
+
* - the former `today`/`evening` marker KEYS are DELETED from the wire on EVERY
|
|
52
|
+
* tier — `when` carries the fact; the markers stay internal (they feed `when`).
|
|
53
|
+
* - the raw `startDate` is DELETED in COMPACT (a list needs the position, not the
|
|
54
|
+
* substrate) and KEPT in FULL/DETAIL beside `when` — different facts: `startDate`
|
|
55
|
+
* = what is stored, `when` = where it sits.
|
|
56
|
+
* - a template's `repeating.nextOccurrence` is GONE from the wire — `when` replaces
|
|
57
|
+
* it (same fact, one word); the resting-templates `{date: null}` group is
|
|
58
|
+
* unchanged (an unprojected template has no `when`).
|
|
59
|
+
* - `when` is DROPPED inside the `today` view's own sections (the section key states
|
|
60
|
+
* today/evening) and inside any card/heading `upcoming` DATE-GROUP for a member
|
|
61
|
+
* whose `when` equals the group's date (the group states it). KEPT everywhere
|
|
62
|
+
* else it is present — including the flat `upcoming`/`anytime`/`inbox`/`someday`
|
|
63
|
+
* catalogues, search, changes (a deadline-pulled row reads `when: "today"` in the
|
|
64
|
+
* mixed search/changes surfaces, informatively; note R13 re-files it to stage
|
|
65
|
+
* `anytime` and the flat inbox/someday views now EXCLUDE it — it appears in the
|
|
66
|
+
* `anytime` catalogue instead, `when: "today"` kept, stage dropped as pure).
|
|
67
|
+
*
|
|
68
|
+
* ## R13 — provisional Today members + GUI-faithful pulled-row membership
|
|
69
|
+
* BANNER1 / BANNER1b (docs/lab/banner1-research.md). Two coupled facts:
|
|
70
|
+
* - **`provisional: true`** — a presence-keyed marker on every Today member the GUI
|
|
71
|
+
* pips / counts in the "You have N new to-dos" banner: a Today member NOT yet
|
|
72
|
+
* materialized (`start != active OR startDate IS NULL`, BANNER1 L1). Derived from
|
|
73
|
+
* the SAME today/evening markers + fields the stage/`when` axes use (never
|
|
74
|
+
* re-derived). Emitted on EVERY tier, NEVER dropped (the banner is not a section,
|
|
75
|
+
* so no node implies it). Absent on non-Today rows and on materialized ones.
|
|
76
|
+
* Read-only: the app clears it by materializing the row on banner-OK, a GUI-only
|
|
77
|
+
* side effect our read cannot perform (watchers beware).
|
|
78
|
+
* - **stage `anytime` for a deadline pull** — a due-deadline pull re-files an undated
|
|
79
|
+
* Inbox/Someday row into Anytime (deriveStage step 2½, L-A). So EVERY Today member
|
|
80
|
+
* derives stage `anytime`, and the `today` view's own sections become stage-PURE →
|
|
81
|
+
* `stage` is DROPPED there (TODAY_SECTION_DROP), alongside the section-implied
|
|
82
|
+
* `when`. The flat someday/inbox views EXCLUDE pulled rows and the anytime view
|
|
83
|
+
* INCLUDES them (src/read/views.ts + predicates.ts DEADLINE_PULLED) — GUI fidelity.
|
|
84
|
+
*
|
|
85
|
+
* ## Universal item-DTO reshapes (R9 — EVERY tier, EVERY read kind incl. detail)
|
|
86
|
+
* - **checklist nesting** — flat counts → presence-keyed `checklist: {open,total}`.
|
|
87
|
+
* - **todos counts** — a project's flat leaf-action counts → presence-keyed
|
|
88
|
+
* `todos: {open, total}` (omit when total 0).
|
|
89
|
+
* - **repeating template/instance split (R11)** — the wire drops the
|
|
90
|
+
* `isTemplate`/`isInstance` discriminators; key presence carries the fact. A
|
|
91
|
+
* TEMPLATE keeps a nested `repeating: {paused?, deadlined?, rule?,
|
|
92
|
+
* latestInstance?}` — the series object (rule config + backward pointer +
|
|
93
|
+
* state flags); presence MEANS template. The forward pointer `nextOccurrence`
|
|
94
|
+
* moved to the top-level `when` (R12 — a template's projected date IS its time
|
|
95
|
+
* position); `latestInstance` is detail-only (SL1). An INSTANCE keeps a flat
|
|
96
|
+
* `instanceOf: <templateUuid>` and no `repeating`. A plain row keeps neither.
|
|
97
|
+
* See {@link reshapeRepeatingWire}.
|
|
98
|
+
* - **string tags** — `tags`/`inheritedTags` become plain arrays of names.
|
|
99
|
+
* - **one project key** — a headed item's owning project (formerly
|
|
100
|
+
* `headingProject`) is merged into `project`; `headingProject` never appears.
|
|
101
|
+
*
|
|
102
|
+
* ## R6 — no-redundant-ancestry (both tiers)
|
|
103
|
+
* project-view children drop `project`+`area` (heading-group members also drop
|
|
104
|
+
* `heading`); area-view children/project-cards drop `area`; anytime/someday
|
|
105
|
+
* section items drop `area`. Mixed lists keep every ref. (In the COMPACT tier the
|
|
106
|
+
* `heading` ref is additionally dropped everywhere — R7.)
|
|
107
|
+
*
|
|
108
|
+
* ## R7 — named detail tiers (compact | full)
|
|
109
|
+
* List contexts default to COMPACT; `detail`/`show` and `--full` / `full:true`
|
|
110
|
+
* use FULL. Compact drops `created`/`modified`, the full `notes` string (a
|
|
111
|
+
* presence-keyed `hasNotes: true` marks a row with notes), and the `heading` ref;
|
|
112
|
+
* `status` is omitted when `open`. FULL keeps them but still applies R6, the
|
|
113
|
+
* universal reshapes, and R10.
|
|
114
|
+
*/
|
|
115
|
+
import { type Stage, type When } from "./stage.ts";
|
|
116
|
+
/**
|
|
117
|
+
* Apply the universal reshapes + R6 + R7 + R10 to a read payload for one view
|
|
118
|
+
* `kind`. `full` forces the FULL tier (R7 default-pruning off, everything else
|
|
119
|
+
* applied); an unrecognized kind passes through unchanged. The input is never
|
|
120
|
+
* mutated (shallow copies throughout), so the human-render path keeps the full
|
|
121
|
+
* entities.
|
|
122
|
+
*/
|
|
123
|
+
export declare function shapeReadPayload(kind: string, data: unknown, full: boolean): unknown;
|
|
124
|
+
/** The disambiguation-candidate kinds an error may list (a subset of the entity kinds). */
|
|
125
|
+
export type CandidateType = "to-do" | "project" | "heading" | "area" | "tag";
|
|
126
|
+
/**
|
|
127
|
+
* The ONE fixed error-candidate shape — the presence-keyed disambiguation DTO a
|
|
128
|
+
* not-found / ambiguous resolution lists under `error.detail.candidates` (and the
|
|
129
|
+
* did-you-mean fallback under the same key). Deliberately minimal and INVARIANT
|
|
130
|
+
* across request flags: `--full` / `--all` / etc. NEVER widen it, because an
|
|
131
|
+
* error payload is the most determinism-critical surface. A candidate carries
|
|
132
|
+
* ONLY material that helps a caller pick the right entity, drawn from the SAME
|
|
133
|
+
* single-source derivations the read wire uses — never the raw internal entity
|
|
134
|
+
* (no counts, no notes, no dates, no null-stuffed keys):
|
|
135
|
+
* - `uuid` / `title` / `type` — always present (`type` names the kind).
|
|
136
|
+
* - `area` / `project` — container hint as a TITLE string, present only when set.
|
|
137
|
+
* - `stage` / `when` — the R10/R12 lifecycle words, present only for a to-do /
|
|
138
|
+
* project candidate whose source row carries the materialized lifecycle fields
|
|
139
|
+
* (a thin uuid+title resolver row carries neither — presence-keyed, so absent).
|
|
140
|
+
* A trashed / logged candidate needs no boolean: `stage` already reads `"trash"`
|
|
141
|
+
* / `"logbook"` for it — the same vocabulary the wire uses.
|
|
142
|
+
*/
|
|
143
|
+
export interface CandidateRef {
|
|
144
|
+
uuid: string;
|
|
145
|
+
title: string;
|
|
146
|
+
type: CandidateType;
|
|
147
|
+
area?: string;
|
|
148
|
+
project?: string;
|
|
149
|
+
stage?: Stage;
|
|
150
|
+
when?: When;
|
|
151
|
+
}
|
|
152
|
+
/** The fixed cap on a listed candidate array; the error `message` states the total when it overflows. */
|
|
153
|
+
export declare const CANDIDATE_CAP = 8;
|
|
154
|
+
/**
|
|
155
|
+
* Project ONE entity — a materialized to-do/project/area/heading, or a thin
|
|
156
|
+
* `{uuid, title}` resolver row — to the fixed {@link CandidateRef}. The SINGLE
|
|
157
|
+
* source every error-candidate emit flows through (the did-you-mean fallback and
|
|
158
|
+
* every not-found/ambiguous resolver), so the candidate shape can never vary by
|
|
159
|
+
* site. Reuses the wire's own {@link stageOf}/{@link whenOf} derivations — the
|
|
160
|
+
* lifecycle words are never re-derived here.
|
|
161
|
+
*/
|
|
162
|
+
export declare function candidateRef(type: CandidateType, src: unknown): CandidateRef;
|