things-api 0.11.0 → 0.13.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 (208) hide show
  1. package/README.md +16 -5
  2. package/dist/audit/schema.d.ts +7 -0
  3. package/dist/audit/schema.js.map +1 -1
  4. package/dist/cli/canonical-ref.d.ts +21 -0
  5. package/dist/cli/canonical-ref.js +23 -0
  6. package/dist/cli/canonical-ref.js.map +1 -0
  7. package/dist/cli/commands/area.d.ts +18 -11
  8. package/dist/cli/commands/area.js +81 -77
  9. package/dist/cli/commands/area.js.map +1 -1
  10. package/dist/cli/commands/doctor.d.ts +1 -2
  11. package/dist/cli/commands/doctor.js +11 -1
  12. package/dist/cli/commands/doctor.js.map +1 -1
  13. package/dist/cli/commands/install-skill.d.ts +19 -4
  14. package/dist/cli/commands/install-skill.js +130 -52
  15. package/dist/cli/commands/install-skill.js.map +1 -1
  16. package/dist/cli/commands/mcp.js +21 -1
  17. package/dist/cli/commands/mcp.js.map +1 -1
  18. package/dist/cli/commands/project.d.ts +1 -0
  19. package/dist/cli/commands/project.js +92 -48
  20. package/dist/cli/commands/project.js.map +1 -1
  21. package/dist/cli/commands/reads.d.ts +5 -1
  22. package/dist/cli/commands/reads.js +110 -31
  23. package/dist/cli/commands/reads.js.map +1 -1
  24. package/dist/cli/commands/setup.js +11 -4
  25. package/dist/cli/commands/setup.js.map +1 -1
  26. package/dist/cli/commands/show.js +75 -36
  27. package/dist/cli/commands/show.js.map +1 -1
  28. package/dist/cli/commands/todo.js +2 -2
  29. package/dist/cli/commands/todo.js.map +1 -1
  30. package/dist/cli/commands/writes.js +795 -144
  31. package/dist/cli/commands/writes.js.map +1 -1
  32. package/dist/cli/did-you-mean.d.ts +14 -3
  33. package/dist/cli/did-you-mean.js +44 -7
  34. package/dist/cli/did-you-mean.js.map +1 -1
  35. package/dist/cli/dry-run.d.ts +55 -0
  36. package/dist/cli/dry-run.js +92 -0
  37. package/dist/cli/dry-run.js.map +1 -0
  38. package/dist/cli/glyphs.d.ts +16 -2
  39. package/dist/cli/glyphs.js +60 -12
  40. package/dist/cli/glyphs.js.map +1 -1
  41. package/dist/cli/help.js +69 -13
  42. package/dist/cli/help.js.map +1 -1
  43. package/dist/cli/main.js +8 -1
  44. package/dist/cli/main.js.map +1 -1
  45. package/dist/cli/move-hint.d.ts +3 -2
  46. package/dist/cli/move-hint.js +2 -2
  47. package/dist/cli/move-hint.js.map +1 -1
  48. package/dist/cli/read-driver.d.ts +53 -5
  49. package/dist/cli/read-driver.js +82 -15
  50. package/dist/cli/read-driver.js.map +1 -1
  51. package/dist/cli/ref-render.d.ts +14 -0
  52. package/dist/cli/ref-render.js +9 -0
  53. package/dist/cli/ref-render.js.map +1 -0
  54. package/dist/cli/render.d.ts +40 -14
  55. package/dist/cli/render.js +128 -55
  56. package/dist/cli/render.js.map +1 -1
  57. package/dist/cli/resolve-invocation.d.ts +7 -5
  58. package/dist/cli/resolve-invocation.js +16 -7
  59. package/dist/cli/resolve-invocation.js.map +1 -1
  60. package/dist/cli/skill-check.d.ts +12 -6
  61. package/dist/cli/skill-check.js +31 -14
  62. package/dist/cli/skill-check.js.map +1 -1
  63. package/dist/cli/skill.d.ts +8 -0
  64. package/dist/cli/skill.js +10 -0
  65. package/dist/cli/skill.js.map +1 -1
  66. package/dist/cli/verb-hint.js +1 -1
  67. package/dist/cli/verb-hint.js.map +1 -1
  68. package/dist/client.d.ts +158 -26
  69. package/dist/client.js +254 -38
  70. package/dist/client.js.map +1 -1
  71. package/dist/config.d.ts +66 -2
  72. package/dist/config.js +120 -12
  73. package/dist/config.js.map +1 -1
  74. package/dist/contracts.d.ts +187 -28
  75. package/dist/contracts.js +22 -1
  76. package/dist/contracts.js.map +1 -1
  77. package/dist/db/baselines/db-v26.js +4 -1
  78. package/dist/db/baselines/db-v26.js.map +1 -1
  79. package/dist/diagnose.d.ts +34 -2
  80. package/dist/diagnose.js +36 -1
  81. package/dist/diagnose.js.map +1 -1
  82. package/dist/index.d.ts +21 -8
  83. package/dist/index.js +26 -3
  84. package/dist/index.js.map +1 -1
  85. package/dist/mcp/server.d.ts +9 -0
  86. package/dist/mcp/server.js +790 -322
  87. package/dist/mcp/server.js.map +1 -1
  88. package/dist/model/entities.d.ts +57 -4
  89. package/dist/model/entities.js.map +1 -1
  90. package/dist/model/mappers.d.ts +2 -0
  91. package/dist/model/mappers.js +44 -2
  92. package/dist/model/mappers.js.map +1 -1
  93. package/dist/model/recurrence.d.ts +8 -1
  94. package/dist/model/recurrence.js.map +1 -1
  95. package/dist/model/serialize.js +15 -3
  96. package/dist/model/serialize.js.map +1 -1
  97. package/dist/read/area-filter.d.ts +76 -0
  98. package/dist/read/area-filter.js +58 -0
  99. package/dist/read/area-filter.js.map +1 -0
  100. package/dist/read/area-view.d.ts +22 -11
  101. package/dist/read/area-view.js +54 -28
  102. package/dist/read/area-view.js.map +1 -1
  103. package/dist/read/detail.js +15 -8
  104. package/dist/read/detail.js.map +1 -1
  105. package/dist/read/predicates.d.ts +18 -0
  106. package/dist/read/predicates.js +19 -0
  107. package/dist/read/predicates.js.map +1 -1
  108. package/dist/read/project-view.d.ts +91 -15
  109. package/dist/read/project-view.js +135 -37
  110. package/dist/read/project-view.js.map +1 -1
  111. package/dist/read/pseudo-area.d.ts +29 -0
  112. package/dist/read/pseudo-area.js +27 -0
  113. package/dist/read/pseudo-area.js.map +1 -0
  114. package/dist/read/queries.d.ts +175 -19
  115. package/dist/read/queries.js +376 -32
  116. package/dist/read/queries.js.map +1 -1
  117. package/dist/read/scope.d.ts +126 -0
  118. package/dist/read/scope.js +161 -0
  119. package/dist/read/scope.js.map +1 -0
  120. package/dist/read/search-rank.d.ts +2 -5
  121. package/dist/read/shape.d.ts +181 -0
  122. package/dist/read/shape.js +737 -0
  123. package/dist/read/shape.js.map +1 -0
  124. package/dist/read/show-target.d.ts +9 -1
  125. package/dist/read/show-target.js +77 -17
  126. package/dist/read/show-target.js.map +1 -1
  127. package/dist/read/stage.d.ts +199 -0
  128. package/dist/read/stage.js +125 -0
  129. package/dist/read/stage.js.map +1 -0
  130. package/dist/read/truncation.d.ts +7 -12
  131. package/dist/read/truncation.js +56 -21
  132. package/dist/read/truncation.js.map +1 -1
  133. package/dist/read/views.d.ts +68 -16
  134. package/dist/read/views.js +206 -52
  135. package/dist/read/views.js.map +1 -1
  136. package/dist/surface-copy.d.ts +16 -0
  137. package/dist/surface-copy.js +16 -0
  138. package/dist/surface-copy.js.map +1 -1
  139. package/dist/write/batch.d.ts +49 -10
  140. package/dist/write/batch.js +423 -71
  141. package/dist/write/batch.js.map +1 -1
  142. package/dist/write/commands.js +268 -55
  143. package/dist/write/commands.js.map +1 -1
  144. package/dist/write/guards.d.ts +1 -1
  145. package/dist/write/guards.js +71 -10
  146. package/dist/write/guards.js.map +1 -1
  147. package/dist/write/heading.d.ts +10 -1
  148. package/dist/write/heading.js +35 -5
  149. package/dist/write/heading.js.map +1 -1
  150. package/dist/write/make-repeating-project.d.ts +2 -2
  151. package/dist/write/make-repeating-project.js +9 -9
  152. package/dist/write/make-repeating-project.js.map +1 -1
  153. package/dist/write/move.d.ts +134 -0
  154. package/dist/write/move.js +1874 -0
  155. package/dist/write/move.js.map +1 -0
  156. package/dist/write/operations.d.ts +105 -19
  157. package/dist/write/operations.js +56 -7
  158. package/dist/write/operations.js.map +1 -1
  159. package/dist/write/opid.d.ts +31 -0
  160. package/dist/write/opid.js +30 -0
  161. package/dist/write/opid.js.map +1 -0
  162. package/dist/write/pipeline.d.ts +70 -3
  163. package/dist/write/pipeline.js +198 -33
  164. package/dist/write/pipeline.js.map +1 -1
  165. package/dist/write/pre-state.d.ts +172 -8
  166. package/dist/write/pre-state.js +467 -25
  167. package/dist/write/pre-state.js.map +1 -1
  168. package/dist/write/reorder.d.ts +23 -3
  169. package/dist/write/reorder.js +2106 -86
  170. package/dist/write/reorder.js.map +1 -1
  171. package/dist/write/reversibility.js +19 -7
  172. package/dist/write/reversibility.js.map +1 -1
  173. package/dist/write/scope-guard.d.ts +31 -0
  174. package/dist/write/scope-guard.js +162 -0
  175. package/dist/write/scope-guard.js.map +1 -0
  176. package/dist/write/undo.js +120 -13
  177. package/dist/write/undo.js.map +1 -1
  178. package/dist/write/vectors/applescript.js +16 -7
  179. package/dist/write/vectors/applescript.js.map +1 -1
  180. package/dist/write/vectors/shortcuts.js +1 -1
  181. package/dist/write/vectors/shortcuts.js.map +1 -1
  182. package/dist/write/vectors/simulator.js +83 -27
  183. package/dist/write/vectors/simulator.js.map +1 -1
  184. package/dist/write/vectors/types.d.ts +11 -0
  185. package/dist/write/vectors/ui-certification.d.ts +3 -3
  186. package/dist/write/vectors/ui-certification.js +41 -5
  187. package/dist/write/vectors/ui-certification.js.map +1 -1
  188. package/dist/write/vectors/ui-drag.d.ts +21 -1
  189. package/dist/write/vectors/ui-drag.js +138 -27
  190. package/dist/write/vectors/ui-drag.js.map +1 -1
  191. package/dist/write/vectors/ui-recipes.d.ts +21 -1
  192. package/dist/write/vectors/ui-recipes.js +166 -7
  193. package/dist/write/vectors/ui-recipes.js.map +1 -1
  194. package/dist/write/vectors/ui.d.ts +25 -1
  195. package/dist/write/vectors/ui.js +142 -33
  196. package/dist/write/vectors/ui.js.map +1 -1
  197. package/dist/write/verify/delta.d.ts +17 -1
  198. package/dist/write/verify/delta.js +106 -29
  199. package/dist/write/verify/delta.js.map +1 -1
  200. package/package.json +7 -1
  201. package/schema/envelope.schema.json +397 -0
  202. package/skills/things-cli/SKILL.md +36 -17
  203. package/skills/things-cli/references/banner.md +35 -0
  204. package/skills/things-cli/references/contracts.md +32 -9
  205. package/skills/things-cli/references/errors.md +57 -0
  206. package/skills/things-cli/references/gui.md +1 -1
  207. package/skills/things-cli/references/model.md +18 -7
  208. package/skills/things-cli/references/ordering.md +88 -0
@@ -8,8 +8,46 @@
8
8
  import { getInvocation } from "./resolve-invocation.js";
9
9
  import { dim } from "./style.js";
10
10
  import { viewHeaderLines } from "./render.js";
11
- import { candidatesJson, DidYouMeanError, renderDidYouMean } from "./did-you-mean.js";
12
- import { ClockError, DEFAULT_LIST_LIMIT, errorEnvelope, ExitCode, okEnvelope, omitEmpty, openThings, ReferenceResolutionError, schemaWarnings, ThingsDbNotFoundError, ThingsDbOpenError, } from "../index.js";
11
+ import { setRenderRefPromoter } from "./ref-render.js";
12
+ import { candidatesJson, DidYouMeanError, didYouMeanMessage, renderDidYouMean, } from "./did-you-mean.js";
13
+ import { ClockError, DEFAULT_LIST_LIMIT, errorEnvelope, ExitCode, okEnvelope, omitEmpty, openThings, shapeReadPayload, ReferenceResolutionError, schemaWarnings, ThingsDbNotFoundError, ThingsDbOpenError, } from "../index.js";
14
+ /**
15
+ * Kinds whose read payload is a flat list; their envelope `data` is the R1
16
+ * `{ items: [...] }` wrapper (data is ALWAYS a JSON object, never a bare array).
17
+ */
18
+ const ITEMS_WRAPPER_KINDS = new Set([
19
+ "inbox",
20
+ "today",
21
+ "upcoming",
22
+ "logbook",
23
+ "trash",
24
+ "changes",
25
+ "search",
26
+ "projects",
27
+ "areas",
28
+ "tags",
29
+ ]);
30
+ /**
31
+ * Shape a read payload into its envelope `data` object (the 1.0 contract, R1/R2):
32
+ * `data` is always an object. Flat lists (incl. `today`, one flat `items[]` of
33
+ * Today members) become `{ items }`; the sectioned catalogues (anytime/someday)
34
+ * become `{ sections }`; the composite cards become `{ view }`; a single-entity
35
+ * detail becomes `{ item }`. Everything already object-shaped (open/snapshot/…)
36
+ * passes through. The human-render path keeps the raw inner payload — this
37
+ * transform is the JSON emit boundary only. `today`'s whole-view `counts`
38
+ * aggregate rides `meta.counts`, not `data` (runRead), so `data` stays pure rows.
39
+ */
40
+ export function wrapEnvelopeData(kind, data) {
41
+ if (ITEMS_WRAPPER_KINDS.has(kind))
42
+ return { items: data };
43
+ if (kind === "anytime" || kind === "someday")
44
+ return { sections: data };
45
+ if (kind === "area-view" || kind === "project-view")
46
+ return { view: data };
47
+ if (kind === "detail")
48
+ return { item: data };
49
+ return data;
50
+ }
13
51
  /**
14
52
  * The single usage-error emitter every command surface routes flag/argument
15
53
  * errors through, so `--json` is honored uniformly: under `--json` a
@@ -21,7 +59,7 @@ import { ClockError, DEFAULT_LIST_LIMIT, errorEnvelope, ExitCode, okEnvelope, om
21
59
  export function usageError(opts, message, details) {
22
60
  if (opts.json === true) {
23
61
  const meta = { dbVersion: null, fingerprint: "unknown", elapsedMs: 0 };
24
- process.stdout.write(`${JSON.stringify(errorEnvelope({ code: "usage", message, ...(details !== undefined && { details }) }, meta))}\n`);
62
+ process.stdout.write(`${JSON.stringify(errorEnvelope({ code: "usage", message, ...(details !== undefined && { detail: details }) }, meta))}\n`);
25
63
  }
26
64
  else {
27
65
  process.stderr.write(`error: ${message}\n`);
@@ -47,11 +85,20 @@ export function runRead(opts, kind, fn, render, hintBase, header) {
47
85
  let client = null;
48
86
  try {
49
87
  client = openThings(opts.db ? { dbPath: opts.db } : {});
88
+ // Arm the render-time ref promoter so human list rows can promote an inline
89
+ // container hint's uuid prefix (TTY only — the JSON path never calls the
90
+ // renderers). Grouped views render inside `fn`, so this must precede it;
91
+ // cleared in `finally`. The `--json` envelope shapes its own refs separately.
92
+ if (!opts.json)
93
+ setRenderRefPromoter(client.refPromoter());
50
94
  const fp = client.fingerprint();
51
95
  // Reads never block on a schema change — they warn (design decision). The
52
96
  // note reuses the same cached fingerprint the write path gates on.
53
- const warnings = schemaWarnings(client.schemaStatus());
54
- const { data, truncation, grouped, lines: precomputed } = fn(client);
97
+ const { data, truncation, kind: kindOverride, filter, counts, warnings: readWarnings, lines: precomputed, } = fn(client);
98
+ // Schema-drift advisories plus any read-specific advisories (e.g. the loose
99
+ // pseudo-area resolution-shadow disclosure).
100
+ const warnings = [...schemaWarnings(client.schemaStatus()), ...(readWarnings ?? [])];
101
+ const effectiveKind = kindOverride ?? kind;
55
102
  // The canonical command a sugar invocation normalized to — known now that
56
103
  // `fn` has resolved any reference. Present only for the routing sugars
57
104
  // (bare noun, keyword-in-show, uuid/share-link routing); null otherwise.
@@ -59,15 +106,20 @@ export function runRead(opts, kind, fn, render, hintBase, header) {
59
106
  // The clock honesty field: present only when a consumer zone / pinned now
60
107
  // is in effect (absent = host clock, so the wire shape is unchanged).
61
108
  const clock = client.clockMeta();
109
+ // The active container scope (additive): present only when the client is
110
+ // jailed, so an agent knows its own jail (not an oracle for what's outside).
111
+ const scope = client.scope;
62
112
  const meta = {
63
113
  dbVersion: fp.observation.databaseVersion,
64
114
  fingerprint: fp.kind === "ok" ? "ok" : fp.kind === "drift" ? "drift" : "unknown",
65
115
  elapsedMs: Date.now() - started,
66
116
  ...(truncation !== undefined && { truncation }),
67
- ...(grouped !== undefined && { grouped }),
68
117
  ...(resolvedCommand !== null && { resolvedCommand }),
69
118
  ...(warnings.length > 0 && { warnings }),
70
119
  ...(clock !== undefined && { clock }),
120
+ ...(filter !== undefined && { filter }),
121
+ ...(counts !== undefined && { counts }),
122
+ ...(scope !== undefined && { scope }),
71
123
  };
72
124
  // Human output gets the note once on STDERR (never mixed into the piped
73
125
  // stdout rows); the --json envelope carries it in meta.warnings instead.
@@ -79,7 +131,8 @@ export function runRead(opts, kind, fn, render, hintBase, header) {
79
131
  // Omit-empty applies to the entity/data payload only (contracts.md); the
80
132
  // envelope meta/truncation is untouched, and the human render below keeps
81
133
  // the full, unpruned `data`.
82
- process.stdout.write(`${JSON.stringify(okEnvelope(kind, omitEmpty(data), meta))}\n`);
134
+ const shaped = shapeReadPayload(effectiveKind, data, opts.full === true, client.refPromoter());
135
+ process.stdout.write(`${JSON.stringify(okEnvelope(effectiveKind, omitEmpty(wrapEnvelopeData(effectiveKind, shaped)), meta))}\n`);
83
136
  }
84
137
  else {
85
138
  const lines = precomputed ?? render(data);
@@ -97,9 +150,16 @@ export function runRead(opts, kind, fn, render, hintBase, header) {
97
150
  // sugar invocation resolved to, adjacent to the header. Same gates as the
98
151
  // preamble (TTY-only, never in --json) — canonical invocations echo
99
152
  // nothing because `resolvedCommand` is null for them.
100
- const out = resolvedCommand !== null && process.stdout.isTTY === true
101
- ? [dim(`≡ ${resolvedCommand}`), ...withHeader]
102
- : withHeader;
153
+ // The scope banner: one dim line naming the active jail, so a scoped
154
+ // read is never silently partial (TTY-only, never in --json). A
155
+ // stored-config scope must not be a mystery jail.
156
+ const scopeBanner = scope !== undefined && process.stdout.isTTY === true
157
+ ? [dim(`scoped to ${scope.kind} "${scope.title}"`)]
158
+ : [];
159
+ const normalized = resolvedCommand !== null && process.stdout.isTTY === true
160
+ ? [dim(`≡ ${resolvedCommand}`)]
161
+ : [];
162
+ const out = [...scopeBanner, ...normalized, ...withHeader];
103
163
  process.stdout.write(`${out.join("\n")}\n`);
104
164
  }
105
165
  process.exitCode = ExitCode.Ok;
@@ -117,8 +177,8 @@ export function runRead(opts, kind, fn, render, hintBase, header) {
117
177
  if (opts.json) {
118
178
  process.stdout.write(`${JSON.stringify(errorEnvelope({
119
179
  code: "not-found",
120
- message: err.message,
121
- details: { candidates: candidatesJson(err) },
180
+ message: didYouMeanMessage(err),
181
+ detail: { candidates: candidatesJson(err) },
122
182
  }, meta))}\n`);
123
183
  }
124
184
  else {
@@ -131,7 +191,7 @@ export function runRead(opts, kind, fn, render, hintBase, header) {
131
191
  // usage-class failure carrying machine-readable candidates.
132
192
  if (err instanceof ReferenceResolutionError) {
133
193
  if (opts.json) {
134
- process.stdout.write(`${JSON.stringify(errorEnvelope({ code: err.code, message: err.message, details: { candidates: err.candidates } }, meta))}\n`);
194
+ process.stdout.write(`${JSON.stringify(errorEnvelope({ code: err.code, message: err.message, detail: { candidates: err.candidates } }, meta))}\n`);
135
195
  }
136
196
  else {
137
197
  process.stderr.write(`error: ${err.message}\n`);
@@ -156,6 +216,7 @@ export function runRead(opts, kind, fn, render, hintBase, header) {
156
216
  process.exitCode = isEnv ? ExitCode.Environment : ExitCode.Unexpected;
157
217
  }
158
218
  finally {
219
+ setRenderRefPromoter(null); // never leak a closed-DB promoter past this read
159
220
  client?.close();
160
221
  }
161
222
  }
@@ -164,8 +225,14 @@ export function runRead(opts, kind, fn, render, hintBase, header) {
164
225
  * turns it into human lines. Generic so `fn`'s return type flows into
165
226
  * `render`'s parameter — the compiler verifies the renderer matches the data.
166
227
  */
167
- export function withClient(opts, kind, fn, render) {
168
- runRead(opts, kind, (client) => ({ data: fn(client) }), render);
228
+ export function withClient(opts, kind, fn, render,
229
+ /** Optional read-specific advisories (merged into `meta.warnings` + stderr). */
230
+ warnings) {
231
+ runRead(opts, kind, (client) => {
232
+ const data = fn(client);
233
+ const w = warnings?.(client);
234
+ return { data, ...(w !== undefined && w.length > 0 && { warnings: w }) };
235
+ }, render);
169
236
  }
170
237
  /**
171
238
  * Resolve the shared `--limit`/`--all` pair (flat views) into a row cap
@@ -1 +1 @@
1
- {"version":3,"file":"read-driver.js","sourceRoot":"","sources":["../../src/cli/read-driver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"read-driver.js","sourceRoot":"","sources":["../../src/cli/read-driver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The CLI's process-wide render-time ref promoter — the same module-state
3
+ * pattern the render clock (./clock.ts) and width fit (./width.ts) use. The read
4
+ * driver sets it (from `client.refPromoter()`) before rendering human output and
5
+ * clears it after, so the pure renderers can decide whether an INLINE container
6
+ * hint should promote its uuid prefix — `(Family)` → `(Family [TC9yozLk])` —
7
+ * using the SAME round-trip predicate the JSON `*Uuid` promotion uses (no fork).
8
+ * Unset (the default, and in unit tests that import the renderers directly) it is
9
+ * null, so a container hint stays the bare `(title)` — byte-identical output.
10
+ */
11
+ import type { RefPromoter } from "../index.ts";
12
+ export declare function setRenderRefPromoter(p: RefPromoter | null): void;
13
+ /** The active render-time promoter, or null (host default — no inline promotion). */
14
+ export declare function renderRefPromoter(): RefPromoter | null;
@@ -0,0 +1,9 @@
1
+ let promoter = null;
2
+ export function setRenderRefPromoter(p) {
3
+ promoter = p;
4
+ }
5
+ /** The active render-time promoter, or null (host default — no inline promotion). */
6
+ export function renderRefPromoter() {
7
+ return promoter;
8
+ }
9
+ //# sourceMappingURL=ref-render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ref-render.js","sourceRoot":"","sources":["../../src/cli/ref-render.ts"],"names":[],"mappings":"AAYA,IAAI,QAAQ,GAAuB,IAAI,CAAC;AAExC,MAAM,UAAU,oBAAoB,CAAC,CAAqB;IACxD,QAAQ,GAAG,CAAC,CAAC;AACf,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,iBAAiB;IAC/B,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -7,7 +7,7 @@
7
7
  * (agents and humans both need stable references); colors engage on a TTY only
8
8
  * (../cli/style.ts).
9
9
  */
10
- import { type GroupedLimits, type GroupedTruncation, type ListItem, type SectionCount, type SidebarSection, type TodayView } from "../index.ts";
10
+ import { type GroupedLimits, type ListItem, type SectionCount, type SidebarSection, type TodayView, type Truncation } from "../index.ts";
11
11
  import { stripSgr } from "./width.ts";
12
12
  /**
13
13
  * A view's TTY-only title preamble: bold view name + its dim Things deep link,
@@ -39,6 +39,14 @@ export interface FormatOpts {
39
39
  /** Container uuids already implied by surrounding output — their context suffix is dropped. */
40
40
  suppressProject?: string | null;
41
41
  suppressArea?: string | null;
42
+ /**
43
+ * Hint the row's HEADING (muted `(Heading)`) instead of its container — the
44
+ * project-view LOGBOOK rows, where a swept child of an OPEN heading labels its
45
+ * heading (the two-view asymmetry, HEADARC2-B: the in-project logged toggle
46
+ * labels the heading; the global Logbook labels the project). No-op on a row
47
+ * with no heading (falls back to the normal container/area hint).
48
+ */
49
+ headingContext?: boolean;
42
50
  /** Reference instant for date-relative tokens (tests pin this; defaults to now). */
43
51
  now?: Date;
44
52
  /** Pre-styled Today/Evening mark (★/⏾), rendered right after the box — GUI position. */
@@ -81,7 +89,7 @@ export declare function formatItem(item: ListItem, uuidWidth?: number, opts?: Fo
81
89
  * effective This-Evening members (raw evening assignment counts only while
82
90
  * startDate is exactly today — the UI's daily expiry), null otherwise.
83
91
  */
84
- export declare function todayMark(item: ListItem, now?: Date): string | null;
92
+ export declare function todayMark(item: ListItem): string | null;
85
93
  /** Minimum displayed-prefix length: shorter prefixes collide across the DB. */
86
94
  export declare const UUID_DISPLAY_MIN = 8;
87
95
  /** The full-form TTY row floor — worst-case furniture + full deadline. See {@link computeFitFloors}. */
@@ -104,12 +112,28 @@ export declare function uuidDisplayWidth(items: Array<{
104
112
  export declare function uuidCol(uuid: string, width: number): string;
105
113
  export declare function renderList(items: ListItem[]): string[];
106
114
  /**
107
- * The `things today` split. The membership glyph lives in the SECTION HEADER,
108
- * not on every row a yellow in the Today header (which also carries the
109
- * sidebar badge split) and a blue ⏾ in the This Evening header — so the rows
110
- * drop the redundant per-item marker (the same convention that suppresses a
111
- * `(project)` context inside that project's own view). Every OTHER view keeps
112
- * the per-row ★/⏾, where the marker still carries information.
115
+ * The `things today` view. The wire is one flat `items[]` of Today members; the
116
+ * TTY re-projects the GUI's two render sections from each row's `when` a
117
+ * Today-proper block (`when: "today"`) and a This-Evening block
118
+ * (`when: "evening"`). The whole-view `counts` aggregate (the app's sidebar
119
+ * count) renders at the TOP as card-style metadata lines (indented `key: value`,
120
+ * the same convention `things project show` / `things area show` use), so the
121
+ * section header itself stays clean (`── ★ Today ──`).
122
+ *
123
+ * The membership glyph lives in the SECTION HEADER, not on every row — a yellow ★
124
+ * in the Today header and a blue ⏾ in the This Evening header — so the rows drop
125
+ * the redundant per-item marker (the same convention that suppresses a
126
+ * `(project)` context inside that project's own view). Every OTHER view keeps the
127
+ * per-row ★/⏾, where the marker still carries information.
128
+ *
129
+ * A PROVISIONAL Today member (the wire's presence-keyed `provisional`, BANNER1
130
+ * law — a Today entrant the app has not yet materialized, banner-counted until
131
+ * acknowledged) gets a yellow `•` in the freed mark slot, mirroring the GUI's
132
+ * yellow "new item" pip. It is per-row (it distinguishes rows within a section,
133
+ * so it is NOT header-deduped like the ★) and — per the GUI — renders ONLY here,
134
+ * never in anytime or any other view. Derived through {@link entityProvisional},
135
+ * the SAME law the wire emit boundary uses, so the pip can never disagree with
136
+ * the emitted `provisional`.
113
137
  *
114
138
  * This Evening mirrors the GUI: it renders ONLY when evening items exist —
115
139
  * a truly-empty evening has no header at all. `view` is the rows that survived
@@ -131,10 +155,12 @@ export declare function renderToday(view: TodayView, sections: SectionCount[] |
131
155
  eveningOnly?: boolean;
132
156
  }): string[];
133
157
  /**
134
- * Search rows: a standard list row, plus — for a project surfaced by a HEADING
135
- * title match a muted `(via heading "…")` suffix crediting the heading whose
136
- * text matched (the parent project row stands in for the heading; the GUI has
137
- * no bare heading row). Ordinary title/notes matches render as plain rows.
158
+ * Search rows: a standard list row, plus — for a hit surfaced by something OTHER
159
+ * than its title — an indented muted matched-on line crediting WHERE the query
160
+ * matched (` ⤷ heading: "…"` / ` ⤷ notes: "…snippet…"` / ` ⤷ checklist: "…"`).
161
+ * A title match renders as a plain row with no indicator (matched where you'd
162
+ * expect). A heading match credits the parent project, a checklist match the
163
+ * parent to-do (the GUI has no bare heading/checklist row).
138
164
  */
139
165
  export declare function renderSearch(items: ListItem[]): string[];
140
166
  /** Hidden-later counts per sidebar group (null area = the loose block). */
@@ -230,7 +256,7 @@ export declare function disclosureHint(count: number, noun: string | {
230
256
  * (`limits` supplies the doubling). Today members are starred. Mirrors
231
257
  * renderSections' layout exactly.
232
258
  */
233
- export declare function renderAnytimePreview(sections: SidebarSection[], grouped: GroupedTruncation, limits: GroupedLimits, base: string): string[];
259
+ export declare function renderAnytimePreview(sections: SidebarSection[], grouped: Truncation, limits: GroupedLimits, base: string): string[];
234
260
  /**
235
261
  * The someday preview, mirroring the GUI (side-by-side, 2026-07-12): inside
236
262
  * each group the project rows render as PLAIN items — `(~)` circle, count
@@ -243,4 +269,4 @@ export declare function renderAnytimePreview(sections: SidebarSection[], grouped
243
269
  * When the toggle is off and such items exist, a muted bottom hint counts
244
270
  * them and names the flag.
245
271
  */
246
- export declare function renderSomedayPreview(sections: SidebarSection[], grouped: GroupedTruncation, limits: GroupedLimits, base: string, showActive: boolean, hiddenActiveItems: number): string[];
272
+ export declare function renderSomedayPreview(sections: SidebarSection[], grouped: Truncation, limits: GroupedLimits, base: string, showActive: boolean, hiddenActiveItems: number): string[];
@@ -7,10 +7,11 @@
7
7
  * (agents and humans both need stable references); colors engage on a TTY only
8
8
  * (../cli/style.ts).
9
9
  */
10
- import { isTodayMember, localToday, partitionSomedaySection, splitSectionBlocks, templateStatus, } from "../index.js";
10
+ import { entityProvisional, entityWhen, localToday, partitionSomedaySection, splitSectionBlocks, templateStatus, REF_PREFIX_LEN, } from "../index.js";
11
11
  import { renderNow, renderZone } from "./clock.js";
12
+ import { renderRefPromoter } from "./ref-render.js";
12
13
  import { bold, dim, strike, underline } from "./style.js";
13
- import { areaMark, CHECKLIST_MARK, containerLabel, countChip, dateChip, deadlineToken, eveningMoon, LEGEND, LEGEND_GROUPS, loggedDate, NOTES_MARK, projectCircle, projectTitleAccent, REMINDER_MARK, todayStar, todoBox, } from "./glyphs.js";
14
+ import { areaMark, CHECKLIST_MARK, containerLabel, countChip, dateChip, deadlineToken, eveningMoon, LEGEND, LEGEND_GROUPS, loggedDate, NOTES_MARK, projectCircle, projectTitleAccent, provisionalPip, REMINDER_MARK, todayStar, todoBox, } from "./glyphs.js";
14
15
  import { FULL_MONTHS, upcomingBucket } from "./period.js";
15
16
  import { fitRow, getFitWidth, resolveFit, stripSgr, TITLE_MIN, visibleWidth, } from "./width.js";
16
17
  /**
@@ -52,6 +53,19 @@ export function renderLegend() {
52
53
  }
53
54
  /** Wraps a `#a #b` tag form in the row's dim styling (incl. its leading space). */
54
55
  const styleTags = (form) => ` ${dim(form)}`;
56
+ /**
57
+ * The inline `[8charPrefix]` a container hint promotes when its bare title would
58
+ * NOT round-trip — the SAME predicate the JSON `*Uuid` promotion uses (the render
59
+ * promoter, ./ref-render.ts). Empty (bare `(title)`) when the promoter is unset
60
+ * (non-TTY / tests / no DB) or the title resolves back cleanly. A project/area
61
+ * container never carries a heading scope, so `projectUuid` stays undefined.
62
+ */
63
+ function promotedRefBracket(ref, kind) {
64
+ const p = renderRefPromoter();
65
+ if (p === null || p.roundTrips(kind, ref.title, ref.uuid))
66
+ return "";
67
+ return ` [${ref.uuid.slice(0, REF_PREFIX_LEN)}]`;
68
+ }
55
69
  /**
56
70
  * One item line:
57
71
  * `<uuid-prefix> <box> [★|⏾] [logged-date] [‹chip›] <title> [‹n›] [⍾] [≡] [≔] (container) #tags [⚑ deadline]`.
@@ -127,18 +141,27 @@ export function formatItem(item, uuidWidth = 0, opts = {}) {
127
141
  ? ` ${bold(dim("⚑"))}`
128
142
  : "";
129
143
  const container = item.type === "to-do" ? (item.project ?? item.headingProject ?? null) : null;
130
- const context = container !== null
131
- ? container.uuid === opts.suppressProject
132
- ? ""
133
- : // The ↻ prefix (containerLabel) marks a container that is a repeating
134
- // TEMPLATE project — the whole `(…)` run is dimmed below, so the mark
135
- // rides the muted container styling. Areas never carry the flag.
136
- ` (${containerLabel(container.title, container.isRepeatingTemplate === true)})`
137
- : item.area
138
- ? item.area.uuid === opts.suppressArea
144
+ // A project-view LOGBOOK row hints its HEADING (the in-project logged toggle
145
+ // labels the heading — HEADARC2-B) rather than the suppressed project.
146
+ const headingHint = opts.headingContext === true && item.type === "to-do" && item.heading !== null
147
+ ? ` (${item.heading.title})`
148
+ : null;
149
+ const context = headingHint !== null
150
+ ? headingHint
151
+ : container !== null
152
+ ? container.uuid === opts.suppressProject
139
153
  ? ""
140
- : ` (${item.area.title})`
141
- : "";
154
+ : // The ↻ prefix (containerLabel) marks a container that is a repeating
155
+ // TEMPLATE project — the whole `(…)` run is dimmed below, so the mark
156
+ // rides the muted container styling. Areas never carry the flag. The
157
+ // fused uuid-prefix rides when the title would not round-trip (shared
158
+ // promotion predicate — the same one JSON `*Uuid` promotion uses).
159
+ ` (${containerLabel(container.title, container.isRepeatingTemplate === true)}${promotedRefBracket(container, "project")})`
160
+ : item.area
161
+ ? item.area.uuid === opts.suppressArea
162
+ ? ""
163
+ : ` (${item.area.title}${promotedRefBracket(item.area, "area")})`
164
+ : "";
142
165
  // width 0 (the default) means "no column" — show the full uuid untouched.
143
166
  const shownUuid = uuidWidth > 0 ? uuidCol(item.uuid, uuidWidth) : item.uuid;
144
167
  // Title styling composes four independent channels (docs/design/render-
@@ -167,10 +190,13 @@ export function formatItem(item, uuidWidth = 0, opts = {}) {
167
190
  t = underline(t);
168
191
  return t;
169
192
  };
170
- // GUI indicator order after the title: bell, document, checklist.
193
+ // GUI indicator order after the title: bell, document, checklist. The bell
194
+ // rides the presence-keyed `reminderLive` marker (§9n) — the SAME materialize-
195
+ // time gate the JSON wire's `reminder` key uses, so a stale reminder (past
196
+ // startDate, bell hidden in the GUI) shows no chip here either.
171
197
  const tail = [
172
198
  ...(item.type === "project" ? [countChip(item)] : []),
173
- ...(item.reminder !== null ? [dim(REMINDER_MARK)] : []),
199
+ ...(item.reminderLive === true ? [dim(REMINDER_MARK)] : []),
174
200
  ...(item.notes !== "" ? [dim(NOTES_MARK)] : []),
175
201
  ...(item.type === "to-do" && item.checklistItemsCount > 0 ? [dim(CHECKLIST_MARK)] : []),
176
202
  ];
@@ -208,13 +234,17 @@ export function formatItem(item, uuidWidth = 0, opts = {}) {
208
234
  * effective This-Evening members (raw evening assignment counts only while
209
235
  * startDate is exactly today — the UI's daily expiry), null otherwise.
210
236
  */
211
- export function todayMark(item, now) {
212
- const instant = now ?? renderNow();
213
- const zone = renderZone();
214
- if (!isTodayMember(item, instant, zone))
215
- return null;
216
- const evening = item.todaySection === "evening" && item.startDate === localToday(instant, zone);
217
- return evening ? eveningMoon() : todayStar();
237
+ export function todayMark(item) {
238
+ // Consume the ONE derived `when` (the same value the wire emits) so a row's
239
+ // ★/⏾ can never disagree with the emitted `when` — never re-derive membership
240
+ // or evening from `todaySection`/`startBucket`/`startDate`. Projects carry the
241
+ // Today markers exactly like to-dos (probe O12), so they pip identically.
242
+ const when = entityWhen(item);
243
+ if (when === "evening")
244
+ return eveningMoon();
245
+ if (when === "today")
246
+ return todayStar();
247
+ return null;
218
248
  }
219
249
  /** Minimum displayed-prefix length: shorter prefixes collide across the DB. */
220
250
  export const UUID_DISPLAY_MIN = 8;
@@ -319,12 +349,36 @@ export function renderList(items) {
319
349
  return items.length === 0 ? ["(empty)"] : items.map((i) => formatItem(i, w));
320
350
  }
321
351
  /**
322
- * The `things today` split. The membership glyph lives in the SECTION HEADER,
323
- * not on every row — a yellow in the Today header (which also carries the
324
- * sidebar badge split) and a blue ⏾ in the This Evening header — so the rows
325
- * drop the redundant per-item marker (the same convention that suppresses a
326
- * `(project)` context inside that project's own view). Every OTHER view keeps
327
- * the per-row ★/⏾, where the marker still carries information.
352
+ * The Today-view per-row mark: a provisional Today member fills the after-the-box
353
+ * mark slot with a yellow `•` (see {@link renderToday}). Derived through
354
+ * {@link entityProvisional}, the SAME law the wire emit boundary uses.
355
+ */
356
+ const provisionalRowOpts = (i) => entityProvisional(i) ? { mark: provisionalPip() } : {};
357
+ /** A today row's This-Evening membership the SAME `when` axis the wire carries. */
358
+ const isEveningRow = (i) => entityWhen(i) === "evening";
359
+ /**
360
+ * The `things today` view. The wire is one flat `items[]` of Today members; the
361
+ * TTY re-projects the GUI's two render sections from each row's `when` — a
362
+ * Today-proper block (`when: "today"`) and a This-Evening block
363
+ * (`when: "evening"`). The whole-view `counts` aggregate (the app's sidebar
364
+ * count) renders at the TOP as card-style metadata lines (indented `key: value`,
365
+ * the same convention `things project show` / `things area show` use), so the
366
+ * section header itself stays clean (`── ★ Today ──`).
367
+ *
368
+ * The membership glyph lives in the SECTION HEADER, not on every row — a yellow ★
369
+ * in the Today header and a blue ⏾ in the This Evening header — so the rows drop
370
+ * the redundant per-item marker (the same convention that suppresses a
371
+ * `(project)` context inside that project's own view). Every OTHER view keeps the
372
+ * per-row ★/⏾, where the marker still carries information.
373
+ *
374
+ * A PROVISIONAL Today member (the wire's presence-keyed `provisional`, BANNER1
375
+ * law — a Today entrant the app has not yet materialized, banner-counted until
376
+ * acknowledged) gets a yellow `•` in the freed mark slot, mirroring the GUI's
377
+ * yellow "new item" pip. It is per-row (it distinguishes rows within a section,
378
+ * so it is NOT header-deduped like the ★) and — per the GUI — renders ONLY here,
379
+ * never in anytime or any other view. Derived through {@link entityProvisional},
380
+ * the SAME law the wire emit boundary uses, so the pip can never disagree with
381
+ * the emitted `provisional`.
328
382
  *
329
383
  * This Evening mirrors the GUI: it renders ONLY when evening items exist —
330
384
  * a truly-empty evening has no header at all. `view` is the rows that survived
@@ -343,30 +397,39 @@ export function renderList(items) {
343
397
  * because that section is deliberately filtered out, not merely empty.
344
398
  */
345
399
  export function renderToday(view, sections, base, options) {
346
- // Pre-cap totals from the truncation metadata; fall back to the shown view's
400
+ // The two render sections are re-projected from each row's `when` (the SAME
401
+ // axis the wire carries), so the TTY split can never disagree with the JSON.
402
+ const todayRows = view.items.filter((i) => !isEveningRow(i));
403
+ const eveningRows = view.items.filter(isEveningRow);
404
+ // Pre-cap totals from the truncation metadata; fall back to the shown rows'
347
405
  // own lengths when a caller hands an unbounded view with no section counts.
348
- const todayTotal = sections?.find((s) => s.key === "today")?.total ?? view.today.length;
349
- const eveningTotal = sections?.find((s) => s.key === "evening")?.total ?? view.evening.length;
350
- const w = uuidDisplayWidth([...view.today, ...view.evening]);
406
+ const todayTotal = sections?.find((s) => s.key === "today")?.total ?? todayRows.length;
407
+ const eveningTotal = sections?.find((s) => s.key === "evening")?.total ?? eveningRows.length;
408
+ const w = uuidDisplayWidth(view.items);
351
409
  const eveningOnly = options?.eveningOnly === true;
352
- const lines = eveningOnly
353
- ? []
354
- : [
355
- `${bold("──")} ${todayStar()} ${bold(`Today (badge: ${view.badge.dueOrOverdue} due/overdue · ${view.badge.other} other) ──`)}`,
356
- ...(view.today.length === 0 ? ["(empty)"] : view.today.map((i) => formatItem(i, w))),
357
- ];
410
+ // The whole-view counts, at the TOP as card-style metadata lines (the
411
+ // project/area-show header convention). A `0` is meaningful, so both always show.
412
+ const lines = [
413
+ ` ${dim("due/overdue:")} ${view.counts.dueOrOverdue}`,
414
+ ` ${dim("other:")} ${view.counts.other}`,
415
+ ];
416
+ if (!eveningOnly) {
417
+ lines.push(`${bold("──")} ${todayStar()} ${bold("Today ──")}`, ...(todayRows.length === 0
418
+ ? ["(empty)"]
419
+ : todayRows.map((i) => formatItem(i, w, provisionalRowOpts(i)))));
420
+ }
358
421
  if (eveningTotal > 0) {
359
422
  // A blank line before the header matches every other grouped renderer's
360
423
  // section spacing — but only when the Today section rendered above it. In
361
- // --evening mode the header is the first line, so no leading blank.
424
+ // --evening mode the header follows the count lines directly, no blank.
362
425
  if (!eveningOnly)
363
426
  lines.push("");
364
427
  lines.push(`${bold("──")} ${eveningMoon()} ${bold("This Evening ──")}`);
365
- for (const i of view.evening)
366
- lines.push(formatItem(i, w));
367
- const hidden = eveningTotal - view.evening.length;
428
+ for (const i of eveningRows)
429
+ lines.push(formatItem(i, w, provisionalRowOpts(i)));
430
+ const hidden = eveningTotal - eveningRows.length;
368
431
  if (hidden > 0) {
369
- const more = view.evening.length > 0 ? "more " : "";
432
+ const more = eveningRows.length > 0 ? "more " : "";
370
433
  const count = `${hidden} ${more}evening item${hidden === 1 ? "" : "s"}`;
371
434
  // Normal Today view: the global truncation footer already carries the
372
435
  // quantity levers (a bigger --limit / --all), so this hint is a pure
@@ -390,20 +453,25 @@ export function renderToday(view, sections, base, options) {
390
453
  return lines;
391
454
  }
392
455
  /**
393
- * Search rows: a standard list row, plus — for a project surfaced by a HEADING
394
- * title match a muted `(via heading "…")` suffix crediting the heading whose
395
- * text matched (the parent project row stands in for the heading; the GUI has
396
- * no bare heading row). Ordinary title/notes matches render as plain rows.
456
+ * Search rows: a standard list row, plus — for a hit surfaced by something OTHER
457
+ * than its title — an indented muted matched-on line crediting WHERE the query
458
+ * matched (` ⤷ heading: "…"` / ` ⤷ notes: "…snippet…"` / ` ⤷ checklist: "…"`).
459
+ * A title match renders as a plain row with no indicator (matched where you'd
460
+ * expect). A heading match credits the parent project, a checklist match the
461
+ * parent to-do (the GUI has no bare heading/checklist row).
397
462
  */
398
463
  export function renderSearch(items) {
399
464
  if (items.length === 0)
400
465
  return ["(empty)"];
401
466
  const w = uuidDisplayWidth(items);
402
- return items.map((i) => {
403
- const via = i.matchedVia;
404
- const row = formatItem(i, w);
405
- return via === undefined ? row : `${row} ${dim(`(via heading "${via.title}")`)}`;
406
- });
467
+ const lines = [];
468
+ for (const i of items) {
469
+ lines.push(formatItem(i, w));
470
+ const match = i.match;
471
+ if (match !== undefined)
472
+ lines.push(` ${dim(`⤷ ${match.field}: "${match.text}"`)}`);
473
+ }
474
+ return lines;
407
475
  }
408
476
  /**
409
477
  * The sidebar mirror for `things projects`: loose projects first (the GUI
@@ -445,7 +513,12 @@ export function renderProjectsSidebar(items, hints) {
445
513
  lines.push("");
446
514
  lines.push(`${bold("──")} ${areaMark()} ${bold(`${group.area.title} ──`)}`);
447
515
  }
448
- lines.push(...rows.map((item) => formatItem(item, w, { suppressArea: group.area?.uuid ?? null })));
516
+ lines.push(...rows.map((item) => formatItem(item, w, {
517
+ suppressArea: group.area?.uuid ?? null,
518
+ // Projects can live in Today/This-Evening (probe O12) — pip them
519
+ // exactly like a to-do row would be in a today-aware view.
520
+ mark: todayMark(item),
521
+ })));
449
522
  // A per-group locator count (not a standalone disclosure): it marks WHERE
450
523
  // the hidden later projects sit; the single reveal command rides the
451
524
  // whole-view placeholder below.
@@ -638,11 +711,11 @@ function mixedMoreLine(projects, todos, drill) {
638
711
  function areaBlockFor(grouped, area) {
639
712
  const kind = area === null ? "loose" : "area";
640
713
  const ref = area?.uuid ?? null;
641
- return grouped.blocks.find((b) => b.kind === kind && b.ref === ref);
714
+ return (grouped.blocks ?? []).find((b) => b.kind === kind && b.ref === ref);
642
715
  }
643
716
  /** A nested project block anywhere in the grouped metadata, matched by project uuid. */
644
717
  function projectBlockFor(grouped, projectUuid) {
645
- for (const b of grouped.blocks) {
718
+ for (const b of grouped.blocks ?? []) {
646
719
  const hit = b.children?.find((c) => c.kind === "project" && c.ref === projectUuid);
647
720
  if (hit !== undefined)
648
721
  return hit;