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.
Files changed (239) hide show
  1. package/README.md +50 -13
  2. package/dist/audit/schema.d.ts +7 -0
  3. package/dist/audit/schema.js.map +1 -1
  4. package/dist/cli/clock.d.ts +8 -0
  5. package/dist/cli/clock.js +24 -0
  6. package/dist/cli/clock.js.map +1 -0
  7. package/dist/cli/commands/area.d.ts +18 -11
  8. package/dist/cli/commands/area.js +61 -74
  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 +60 -0
  14. package/dist/cli/commands/install-skill.js +256 -0
  15. package/dist/cli/commands/install-skill.js.map +1 -0
  16. package/dist/cli/commands/mcp.js +9 -0
  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 +27 -34
  20. package/dist/cli/commands/project.js.map +1 -1
  21. package/dist/cli/commands/reads.d.ts +15 -2
  22. package/dist/cli/commands/reads.js +144 -44
  23. package/dist/cli/commands/reads.js.map +1 -1
  24. package/dist/cli/commands/setup.js +7 -2
  25. package/dist/cli/commands/setup.js.map +1 -1
  26. package/dist/cli/commands/show.js +38 -14
  27. package/dist/cli/commands/show.js.map +1 -1
  28. package/dist/cli/commands/todo.js +15 -9
  29. package/dist/cli/commands/todo.js.map +1 -1
  30. package/dist/cli/commands/writes.js +797 -174
  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 +26 -3
  34. package/dist/cli/did-you-mean.js.map +1 -1
  35. package/dist/cli/glyphs.d.ts +32 -2
  36. package/dist/cli/glyphs.js +83 -12
  37. package/dist/cli/glyphs.js.map +1 -1
  38. package/dist/cli/help.js +121 -16
  39. package/dist/cli/help.js.map +1 -1
  40. package/dist/cli/main.js +33 -2
  41. package/dist/cli/main.js.map +1 -1
  42. package/dist/cli/move-hint.d.ts +46 -0
  43. package/dist/cli/move-hint.js +196 -0
  44. package/dist/cli/move-hint.js.map +1 -0
  45. package/dist/cli/period.d.ts +2 -8
  46. package/dist/cli/period.js +44 -30
  47. package/dist/cli/period.js.map +1 -1
  48. package/dist/cli/read-driver.d.ts +43 -5
  49. package/dist/cli/read-driver.js +91 -15
  50. package/dist/cli/read-driver.js.map +1 -1
  51. package/dist/cli/render.d.ts +19 -8
  52. package/dist/cli/render.js +70 -27
  53. package/dist/cli/render.js.map +1 -1
  54. package/dist/cli/resolve-invocation.d.ts +2 -2
  55. package/dist/cli/resolve-invocation.js +3 -3
  56. package/dist/cli/resolve-invocation.js.map +1 -1
  57. package/dist/cli/skill-check.d.ts +27 -0
  58. package/dist/cli/skill-check.js +99 -0
  59. package/dist/cli/skill-check.js.map +1 -0
  60. package/dist/cli/skill.d.ts +70 -0
  61. package/dist/cli/skill.js +152 -0
  62. package/dist/cli/skill.js.map +1 -0
  63. package/dist/cli/tag-filters.d.ts +6 -2
  64. package/dist/cli/tag-filters.js +8 -6
  65. package/dist/cli/tag-filters.js.map +1 -1
  66. package/dist/cli/verb-hint.js +28 -3
  67. package/dist/cli/verb-hint.js.map +1 -1
  68. package/dist/cli/version.d.ts +4 -0
  69. package/dist/cli/version.js +18 -0
  70. package/dist/cli/version.js.map +1 -0
  71. package/dist/client.d.ts +171 -27
  72. package/dist/client.js +279 -40
  73. package/dist/client.js.map +1 -1
  74. package/dist/config.d.ts +66 -2
  75. package/dist/config.js +120 -12
  76. package/dist/config.js.map +1 -1
  77. package/dist/contracts.d.ts +186 -28
  78. package/dist/contracts.js +22 -1
  79. package/dist/contracts.js.map +1 -1
  80. package/dist/diagnose.d.ts +34 -2
  81. package/dist/diagnose.js +36 -1
  82. package/dist/diagnose.js.map +1 -1
  83. package/dist/index.d.ts +25 -9
  84. package/dist/index.js +22 -3
  85. package/dist/index.js.map +1 -1
  86. package/dist/mcp/server.d.ts +9 -0
  87. package/dist/mcp/server.js +1157 -684
  88. package/dist/mcp/server.js.map +1 -1
  89. package/dist/model/clock.d.ts +61 -0
  90. package/dist/model/clock.js +71 -0
  91. package/dist/model/clock.js.map +1 -0
  92. package/dist/model/dates.d.ts +26 -3
  93. package/dist/model/dates.js +84 -3
  94. package/dist/model/dates.js.map +1 -1
  95. package/dist/model/entities.d.ts +60 -3
  96. package/dist/model/entities.js.map +1 -1
  97. package/dist/model/mappers.d.ts +4 -2
  98. package/dist/model/mappers.js +66 -9
  99. package/dist/model/mappers.js.map +1 -1
  100. package/dist/model/recurrence.d.ts +8 -1
  101. package/dist/model/recurrence.js.map +1 -1
  102. package/dist/read/area-filter.d.ts +76 -0
  103. package/dist/read/area-filter.js +59 -0
  104. package/dist/read/area-filter.js.map +1 -0
  105. package/dist/read/area-view.d.ts +12 -12
  106. package/dist/read/area-view.js +58 -34
  107. package/dist/read/area-view.js.map +1 -1
  108. package/dist/read/detail.d.ts +1 -1
  109. package/dist/read/detail.js +26 -12
  110. package/dist/read/detail.js.map +1 -1
  111. package/dist/read/log-boundary.d.ts +1 -1
  112. package/dist/read/log-boundary.js +13 -3
  113. package/dist/read/log-boundary.js.map +1 -1
  114. package/dist/read/predicates.d.ts +18 -0
  115. package/dist/read/predicates.js +19 -0
  116. package/dist/read/predicates.js.map +1 -1
  117. package/dist/read/project-view.d.ts +32 -16
  118. package/dist/read/project-view.js +80 -45
  119. package/dist/read/project-view.js.map +1 -1
  120. package/dist/read/pseudo-area.d.ts +29 -0
  121. package/dist/read/pseudo-area.js +27 -0
  122. package/dist/read/pseudo-area.js.map +1 -0
  123. package/dist/read/queries.d.ts +108 -19
  124. package/dist/read/queries.js +212 -35
  125. package/dist/read/queries.js.map +1 -1
  126. package/dist/read/scope.d.ts +126 -0
  127. package/dist/read/scope.js +162 -0
  128. package/dist/read/scope.js.map +1 -0
  129. package/dist/read/search-rank.d.ts +2 -5
  130. package/dist/read/shape.d.ts +162 -0
  131. package/dist/read/shape.js +686 -0
  132. package/dist/read/shape.js.map +1 -0
  133. package/dist/read/show-target.d.ts +9 -1
  134. package/dist/read/show-target.js +45 -4
  135. package/dist/read/show-target.js.map +1 -1
  136. package/dist/read/snapshot.d.ts +1 -1
  137. package/dist/read/snapshot.js +9 -2
  138. package/dist/read/snapshot.js.map +1 -1
  139. package/dist/read/stage.d.ts +199 -0
  140. package/dist/read/stage.js +125 -0
  141. package/dist/read/stage.js.map +1 -0
  142. package/dist/read/truncation.d.ts +8 -6
  143. package/dist/read/truncation.js +35 -10
  144. package/dist/read/truncation.js.map +1 -1
  145. package/dist/read/views.d.ts +61 -20
  146. package/dist/read/views.js +240 -82
  147. package/dist/read/views.js.map +1 -1
  148. package/dist/surface-copy.d.ts +9 -0
  149. package/dist/surface-copy.js +9 -0
  150. package/dist/surface-copy.js.map +1 -1
  151. package/dist/write/accessibility-probe.d.ts +1 -1
  152. package/dist/write/accessibility-probe.js +8 -0
  153. package/dist/write/accessibility-probe.js.map +1 -1
  154. package/dist/write/automation-probe.d.ts +1 -1
  155. package/dist/write/automation-probe.js +8 -0
  156. package/dist/write/automation-probe.js.map +1 -1
  157. package/dist/write/batch.d.ts +49 -10
  158. package/dist/write/batch.js +423 -70
  159. package/dist/write/batch.js.map +1 -1
  160. package/dist/write/commands.d.ts +1 -1
  161. package/dist/write/commands.js +316 -66
  162. package/dist/write/commands.js.map +1 -1
  163. package/dist/write/guards.d.ts +1 -1
  164. package/dist/write/guards.js +94 -10
  165. package/dist/write/guards.js.map +1 -1
  166. package/dist/write/heading.d.ts +10 -1
  167. package/dist/write/heading.js +35 -5
  168. package/dist/write/heading.js.map +1 -1
  169. package/dist/write/make-repeating-project.d.ts +2 -2
  170. package/dist/write/make-repeating-project.js +9 -9
  171. package/dist/write/make-repeating-project.js.map +1 -1
  172. package/dist/write/move.d.ts +130 -0
  173. package/dist/write/move.js +1533 -0
  174. package/dist/write/move.js.map +1 -0
  175. package/dist/write/operations.d.ts +105 -19
  176. package/dist/write/operations.js +56 -7
  177. package/dist/write/operations.js.map +1 -1
  178. package/dist/write/opid.d.ts +31 -0
  179. package/dist/write/opid.js +30 -0
  180. package/dist/write/opid.js.map +1 -0
  181. package/dist/write/pipeline.d.ts +122 -3
  182. package/dist/write/pipeline.js +309 -52
  183. package/dist/write/pipeline.js.map +1 -1
  184. package/dist/write/planner.js +8 -1
  185. package/dist/write/planner.js.map +1 -1
  186. package/dist/write/pre-state.d.ts +197 -6
  187. package/dist/write/pre-state.js +427 -20
  188. package/dist/write/pre-state.js.map +1 -1
  189. package/dist/write/recurrence-rule-blob.d.ts +65 -0
  190. package/dist/write/recurrence-rule-blob.js +150 -0
  191. package/dist/write/recurrence-rule-blob.js.map +1 -0
  192. package/dist/write/reorder.d.ts +23 -3
  193. package/dist/write/reorder.js +1871 -85
  194. package/dist/write/reorder.js.map +1 -1
  195. package/dist/write/reversibility.js +19 -7
  196. package/dist/write/reversibility.js.map +1 -1
  197. package/dist/write/scope-guard.d.ts +31 -0
  198. package/dist/write/scope-guard.js +162 -0
  199. package/dist/write/scope-guard.js.map +1 -0
  200. package/dist/write/undo.js +120 -13
  201. package/dist/write/undo.js.map +1 -1
  202. package/dist/write/vectors/applescript.js +16 -7
  203. package/dist/write/vectors/applescript.js.map +1 -1
  204. package/dist/write/vectors/registry.d.ts +5 -7
  205. package/dist/write/vectors/registry.js +49 -2
  206. package/dist/write/vectors/registry.js.map +1 -1
  207. package/dist/write/vectors/shortcuts.js +1 -1
  208. package/dist/write/vectors/shortcuts.js.map +1 -1
  209. package/dist/write/vectors/simulator.d.ts +44 -0
  210. package/dist/write/vectors/simulator.js +1192 -0
  211. package/dist/write/vectors/simulator.js.map +1 -0
  212. package/dist/write/vectors/types.d.ts +46 -0
  213. package/dist/write/vectors/ui-certification.d.ts +10 -4
  214. package/dist/write/vectors/ui-certification.js +43 -10
  215. package/dist/write/vectors/ui-certification.js.map +1 -1
  216. package/dist/write/vectors/ui-drag.d.ts +21 -1
  217. package/dist/write/vectors/ui-drag.js +138 -27
  218. package/dist/write/vectors/ui-drag.js.map +1 -1
  219. package/dist/write/vectors/ui-recipes.d.ts +34 -1
  220. package/dist/write/vectors/ui-recipes.js +217 -6
  221. package/dist/write/vectors/ui-recipes.js.map +1 -1
  222. package/dist/write/vectors/ui.d.ts +40 -1
  223. package/dist/write/vectors/ui.js +196 -39
  224. package/dist/write/vectors/ui.js.map +1 -1
  225. package/dist/write/verify/delta.d.ts +127 -2
  226. package/dist/write/verify/delta.js +255 -16
  227. package/dist/write/verify/delta.js.map +1 -1
  228. package/dist/write/verify/poller.d.ts +7 -1
  229. package/dist/write/verify/poller.js +20 -1
  230. package/dist/write/verify/poller.js.map +1 -1
  231. package/package.json +24 -3
  232. package/schema/envelope.schema.json +383 -0
  233. package/skills/things-cli/SKILL.md +70 -0
  234. package/skills/things-cli/references/banner.md +35 -0
  235. package/skills/things-cli/references/contracts.md +62 -0
  236. package/skills/things-cli/references/errors.md +49 -0
  237. package/skills/things-cli/references/gui.md +11 -0
  238. package/skills/things-cli/references/model.md +60 -0
  239. package/skills/things-cli/references/ordering.md +71 -0
package/dist/client.d.ts CHANGED
@@ -4,7 +4,8 @@
4
4
  */
5
5
  import type { AuditWriter } from "./audit/log.ts";
6
6
  import { type ThingsApiConfig } from "./config.ts";
7
- import { type GroupedTruncation, type Truncation } from "./contracts.ts";
7
+ import { type ClockMeta } from "./model/clock.ts";
8
+ import { type Truncation } from "./contracts.ts";
8
9
  import { type FingerprintStatus, type SchemaStatus } from "./db/fingerprint.ts";
9
10
  import type { AnyTask, Area, Project, Tag } from "./model/entities.ts";
10
11
  import { type AreaView } from "./read/area-view.ts";
@@ -12,13 +13,16 @@ import { type ProjectView } from "./read/project-view.ts";
12
13
  import { type Snapshot } from "./read/snapshot.ts";
13
14
  import { type ShowTarget } from "./read/show-target.ts";
14
15
  import { type ChangedItem, type InboxFilter, type LiteSearchResult, type ListItem, type LogbookFilter, type SearchOptions, type SearchResultItem, type SidebarSection, type SomedayFilter, type TodayFilter, type TodayView, type UpcomingFilter, type ViewFilter } from "./read/views.ts";
15
- import type { AreaAddParams, AreaUpdateParams, ContainerRef, ProjectCancelParams, OperationKind, OperationParamsMap, ProjectAddParams, ProjectCompleteParams, ProjectCreateRepeatingParams, ProjectUpdateParams, RepeatRuleParams, ReorderParams, TagAddParams, TagUpdateParams, HeadingArchiveParams, HeadingUnarchiveParams, TodoAddLoggedParams, TodoAddParams, TodoBackdateParams, TodoMoveParams, TodoUpdateParams } from "./write/operations.ts";
16
+ import { type AreaScopedRead, type ViewFilterMeta } from "./read/area-filter.ts";
17
+ import { type ScopeMeta } from "./read/scope.ts";
18
+ import type { AreaAddParams, AreaUpdateParams, ContainerRef, ProjectCancelParams, OperationKind, OperationParamsMap, ProjectAddParams, ProjectCompleteParams, ProjectAddRepeatingParams, ProjectUpdateParams, RepeatRuleParams, ReorderParams, TagAddParams, TagUpdateParams, HeadingArchiveParams, HeadingUnarchiveParams, HeadingPlacement, TodoAddLoggedParams, TodoAddParams, TodoBackdateParams, TodoMoveParams, TodoUpdateParams } from "./write/operations.ts";
16
19
  import { type MutationResult, type WriteOptions } from "./write/pipeline.ts";
17
- import { type BatchItemResult, type BatchOp, type BatchOptions } from "./write/batch.ts";
20
+ import { type BatchItemResult, type BatchOp, type BatchOptions, type BatchResult } from "./write/batch.ts";
18
21
  import { type EnvironmentTracker } from "./write/environment.ts";
19
22
  import { type HeadingArchiveResult, type HeadingUnarchiveResult } from "./write/heading.ts";
20
23
  import type { ChecklistEdit } from "./write/checklist.ts";
21
24
  import { type ReorderResult } from "./write/reorder.ts";
25
+ import { type MoveResult, type ProjectMoveRequest, type ReorderRequest, type TodoMoveRequest } from "./write/move.ts";
22
26
  import { type UndoItemResult, type UndoOptions } from "./write/undo.ts";
23
27
  import { type ProjectReopenOptions, type ProjectReopenResult } from "./write/reopen.ts";
24
28
  import type { WriteVector } from "./write/vectors/types.ts";
@@ -27,10 +31,26 @@ export interface OpenOptions {
27
31
  dbPath?: string;
28
32
  /** Injectable clock (tests, pinned-clock lab runs). */
29
33
  now?: () => Date;
34
+ /**
35
+ * Default consumer IANA zone for every date boundary (tests / explicit
36
+ * embedding). Overrides `THINGS_TZ` from the environment; a per-read `zone`
37
+ * still overrides this. Absent uses `THINGS_TZ`, else the host zone.
38
+ */
39
+ zone?: string;
30
40
  /** Injectable write vectors (tests: FakeVector; lab: probe vectors). */
31
41
  vectors?: WriteVector[];
32
42
  /** Env for config/state-dir resolution (tests). */
33
43
  env?: NodeJS.ProcessEnv;
44
+ /**
45
+ * Container scope: a ref (uuid / uuid-prefix / unique area or project name)
46
+ * that jails this client to one container — reads see only in-scope rows,
47
+ * writes are refused (or redirected) outside it, and out-of-scope refs are
48
+ * indistinguishable from nonexistent ones. This is the MCP `--scope` flag's
49
+ * entry point and OUTRANKS `THINGS_API_SCOPE` / the stored `scope` config
50
+ * (the launcher's boundary must not be agent-overridable). Unresolvable →
51
+ * fail closed (ScopeResolutionError). See docs/design/container-scope.md.
52
+ */
53
+ scope?: string;
34
54
  /** Test seams for the mutation pipeline. */
35
55
  writeOverrides?: {
36
56
  ensureRunning?: (alreadyRunning: boolean) => Promise<boolean>;
@@ -50,6 +70,15 @@ export interface ListBound {
50
70
  limit?: number | null;
51
71
  all?: boolean;
52
72
  }
73
+ /**
74
+ * Per-read consumer-zone override (the MCP `tz` argument). Overrides the
75
+ * process default (`THINGS_TZ` / the `OpenOptions.zone` embedding / the host)
76
+ * for THIS read only. Absent uses that default; an invalid zone is rejected by
77
+ * the calling surface before it reaches here.
78
+ */
79
+ export interface ClockScopedRead {
80
+ zone?: string;
81
+ }
53
82
  /**
54
83
  * Per-block caps for a bounded GROUPED view (anytime/someday) or the composite
55
84
  * area card. Each omitted cap falls back to the view's own default (anytime:
@@ -65,6 +94,8 @@ export interface GroupedBound {
65
94
  export interface BoundedList<T> {
66
95
  items: T[];
67
96
  truncation: Truncation;
97
+ /** The active `area` scope, when one was applied (surfaced as `meta.filter`). */
98
+ filter?: ViewFilterMeta;
68
99
  }
69
100
  /**
70
101
  * A bounded Today view: `view` is the shown split (capped in render order —
@@ -74,24 +105,49 @@ export interface BoundedList<T> {
74
105
  export interface BoundedTodayView {
75
106
  view: TodayView;
76
107
  truncation: Truncation;
108
+ /** The active `area` scope, when one was applied (surfaced as `meta.filter`). */
109
+ filter?: ViewFilterMeta;
77
110
  }
78
111
  /**
79
112
  * A bounded sidebar catalogue (anytime/someday): `view` is the
80
- * per-block-capped sections and `grouped` the per-block counts (identity-
81
- * carrying, project blocks nested under their area/loose block).
113
+ * per-block-capped sections and `truncation` the unified completeness metadata
114
+ * whose `blocks` carry the identity-bearing per-block counts (project blocks
115
+ * nested under their area/loose block).
82
116
  */
83
117
  export interface BoundedSectionsView {
84
118
  view: SidebarSection[];
85
- grouped: GroupedTruncation;
119
+ truncation: Truncation;
120
+ /** The active `area` scope, when one was applied (surfaced as `meta.filter`). */
121
+ filter?: ViewFilterMeta;
86
122
  }
87
- /** A bounded composite area card: the per-section-capped view and the per-block counts. */
123
+ /** A bounded composite area card: the per-section-capped view and the per-block truncation. */
88
124
  export interface BoundedAreaView {
89
125
  view: AreaView;
90
- grouped: GroupedTruncation;
126
+ truncation: Truncation;
127
+ /**
128
+ * A resolution disclosure — present ONLY on the `loose` pseudo-area read when
129
+ * a real area shadows the reserved word (names it, by uuid, for targeting).
130
+ * Surfaced by the consumers as a `meta.warnings` advisory.
131
+ */
132
+ notice?: string;
133
+ /**
134
+ * The live count of the area's logged rows (subtree-inclusive, past the
135
+ * log-move boundary — the population `things logbook --area <ref>` returns).
136
+ * Present for a real area, absent for the `loose` pseudo-area. A DISPLAY
137
+ * sibling of `view`: it feeds the TTY card's logbook footer and never enters
138
+ * the JSON area-view `data`.
139
+ */
140
+ loggedCount?: number;
91
141
  }
92
142
  export interface ThingsClient {
93
143
  dbPath: string;
94
144
  config: ThingsApiConfig;
145
+ /**
146
+ * The active container scope (pinned at open), or undefined when unscoped.
147
+ * The consumer surfaces surface it as the additive `meta.scope` and the
148
+ * one-line "scoped to …" banner so the jail is never silently on.
149
+ */
150
+ scope?: ScopeMeta;
95
151
  fingerprint(): FingerprintStatus;
96
152
  /**
97
153
  * The read-path schema check: the cached fingerprint comparison reduced to a
@@ -100,6 +156,30 @@ export interface ThingsClient {
100
156
  * once per client, so it costs nothing after the first read.
101
157
  */
102
158
  schemaStatus(): SchemaStatus;
159
+ /**
160
+ * The additive `meta.clock` honesty field for this client's effective clock,
161
+ * or undefined when the host clock is in force (no `THINGS_TZ`/`THINGS_NOW`
162
+ * and no per-read override). `zoneOverride` reflects a per-read zone (the MCP
163
+ * `tz` argument) so the reported `today` matches what that read computed.
164
+ */
165
+ clockMeta(zoneOverride?: string): ClockMeta | undefined;
166
+ /**
167
+ * Reference resolvers the consumer surfaces (CLI/MCP) call to turn a project
168
+ * ref + heading selector into uuids before invoking a heading verb. Both
169
+ * throw {@link ReferenceResolutionError} (uuid candidates on ambiguity),
170
+ * scope-aware when a container scope is active. `heading` shares the one
171
+ * heading-selector core (title | uuid | empty-string literal; no ordinal).
172
+ */
173
+ resolve: {
174
+ project(ref: string): {
175
+ uuid: string;
176
+ title: string;
177
+ };
178
+ heading(projectUuid: string, sel: string): {
179
+ uuid: string;
180
+ title: string;
181
+ };
182
+ };
103
183
  read: {
104
184
  /**
105
185
  * The Today list (Today + This Evening split) with the sidebar badge,
@@ -107,27 +187,29 @@ export interface ThingsClient {
107
187
  * first, then This Evening. `all`/`limit: null` returns every row; the
108
188
  * `truncation` metadata carries the per-section (`today`/`evening`) counts.
109
189
  */
110
- today(options?: TodayFilter & ListBound): BoundedTodayView;
190
+ today(options?: TodayFilter & ListBound & ClockScopedRead & AreaScopedRead): BoundedTodayView;
111
191
  /** Inbox captures, bounded (default 50). */
112
- inbox(options?: InboxFilter & ListBound): BoundedList<ListItem>;
192
+ inbox(options?: InboxFilter & ListBound & ClockScopedRead): BoundedList<ListItem>;
113
193
  /**
114
194
  * Anytime catalogue: every area header and project row is always present;
115
195
  * `areaLimit` (default 30) caps each area/loose block, `projectLimit`
116
- * (default 3) each project block. `all` lifts both.
196
+ * (default 3) each project block. `all` lifts both. `area` restricts the
197
+ * catalogue to one area (its rows survive; the rest drop).
117
198
  */
118
- anytime(options?: ViewFilter & GroupedBound): BoundedSectionsView;
199
+ anytime(options?: ViewFilter & GroupedBound & ClockScopedRead & AreaScopedRead): BoundedSectionsView;
119
200
  /** Future-scheduled items in date order, bounded (default 50). */
120
- upcoming(options?: UpcomingFilter & ListBound): BoundedList<ListItem>;
201
+ upcoming(options?: UpcomingFilter & ListBound & ClockScopedRead & AreaScopedRead): BoundedList<ListItem>;
121
202
  /**
122
203
  * Someday catalogue: `areaLimit` (default 30) caps each group; with
123
204
  * `activeProjectItems`, `projectLimit` (default: every item) caps each
124
- * active project's trailing child list. `all` lifts both.
205
+ * active project's trailing child list. `all` lifts both. `area` restricts
206
+ * the catalogue to one area.
125
207
  */
126
- someday(options?: SomedayFilter & GroupedBound): BoundedSectionsView;
208
+ someday(options?: SomedayFilter & GroupedBound & ClockScopedRead & AreaScopedRead): BoundedSectionsView;
127
209
  /** Logbook entries (most recent first), bounded (default 50). */
128
- logbook(options?: Omit<LogbookFilter, "limit"> & ListBound): BoundedList<ListItem>;
210
+ logbook(options?: Omit<LogbookFilter, "limit"> & ListBound & ClockScopedRead): BoundedList<ListItem>;
129
211
  /** Trashed items (most recently modified first), bounded (default 50). */
130
- trash(options?: ListBound): BoundedList<ListItem>;
212
+ trash(options?: ListBound & ClockScopedRead): BoundedList<ListItem>;
131
213
  /**
132
214
  * Projects in sidebar order. LATER (someday + future-scheduled) projects
133
215
  * are excluded by default — `later: true` appends them after the active
@@ -137,7 +219,7 @@ export interface ThingsClient {
137
219
  areaUuid?: string;
138
220
  later?: boolean;
139
221
  overdue?: boolean;
140
- } & ViewFilter): Project[];
222
+ } & ViewFilter & ClockScopedRead): Project[];
141
223
  /**
142
224
  * Composite project view. Targets by uuid, unique name, or uuid prefix.
143
225
  * `overdue: true` keeps only child to-dos whose own deadline is overdue
@@ -146,7 +228,7 @@ export interface ThingsClient {
146
228
  * inherited from this project are ignored). Any content scope collapses
147
229
  * headings left with no surviving child.
148
230
  */
149
- projectView(ref: string, options?: ViewFilter): ProjectView;
231
+ projectView(ref: string, options?: ViewFilter & ClockScopedRead): ProjectView;
150
232
  /**
151
233
  * Composite area view: direct to-dos, projects in sidebar order, later,
152
234
  * logged. `overdue: true` keeps only the loose to-dos AND child projects
@@ -157,11 +239,11 @@ export interface ThingsClient {
157
239
  * always survive, routed to the card's later sections); `all` lifts both.
158
240
  * The `grouped` metadata carries the per-section counts.
159
241
  */
160
- areaView(ref: string, options?: ViewFilter & GroupedBound): BoundedAreaView;
242
+ areaView(ref: string, options?: ViewFilter & GroupedBound & ClockScopedRead): BoundedAreaView;
161
243
  areas(): Area[];
162
244
  tags(): Tag[];
163
245
  /** Title/notes substring search, ranked, bounded (default 50). */
164
- search(query: string, options?: SearchOptions): BoundedList<SearchResultItem>;
246
+ search(query: string, options?: SearchOptions & ClockScopedRead): BoundedList<SearchResultItem>;
165
247
  /**
166
248
  * Did-you-mean fallback: case-insensitive title-only substring match over
167
249
  * areas/projects/to-dos (open + untrashed), ordered and capped. `type`
@@ -174,7 +256,7 @@ export interface ThingsClient {
174
256
  /** Rows created/modified since a moment — incl. trashed/logged/templates — bounded (default 50). */
175
257
  changes(options: {
176
258
  since: Date;
177
- } & ListBound): BoundedList<ChangedItem>;
259
+ } & ListBound & ClockScopedRead): BoundedList<ChangedItem>;
178
260
  byUuid(uuid: string): AnyTask | null;
179
261
  /**
180
262
  * Classify a loose reference (uuid, >=6-char prefix, share link, or
@@ -193,6 +275,23 @@ export interface ThingsClient {
193
275
  cancelTodo(uuid: string, options?: WriteOptions): Promise<MutationResult>;
194
276
  reopenTodo(uuid: string, options?: WriteOptions): Promise<MutationResult>;
195
277
  moveTodo(uuid: string, dest: Omit<TodoMoveParams, "uuid">, options?: WriteOptions): Promise<MutationResult>;
278
+ /**
279
+ * Move one or more to-dos as an ordered block (spec §4). Give a destination
280
+ * (--to-project / --to-heading / --to-area / --no-heading / --loose) and an
281
+ * optional position (first/last/before/after), or a position alone to
282
+ * reposition items already sharing a container. Membership always succeeds;
283
+ * placement is guaranteed top-of-bucket only where a reorder protocol exists
284
+ * (the result states the placement class). Compiles onto the todo.move +
285
+ * reorder wire primitives — no new op kind.
286
+ */
287
+ moveTodos(request: TodoMoveRequest, options?: WriteOptions): Promise<MoveResult>;
288
+ /**
289
+ * Reorder to-dos IN PLACE within their shared container+bucket (spec §4).
290
+ * Bare (no position) assembles the movees as a contiguous block at the
291
+ * earliest movee's current slot, in argument order. Cross-container operands
292
+ * fail closed.
293
+ */
294
+ reorderTodos(request: ReorderRequest, options?: WriteOptions): Promise<MoveResult>;
196
295
  /** Replace the full tag set (an empty list clears all tags). */
197
296
  setTags(uuid: string, tags: string[], options?: WriteOptions): Promise<MutationResult>;
198
297
  /** Merge: current direct tags + new ones, then replace. */
@@ -225,11 +324,43 @@ export interface ThingsClient {
225
324
  /**
226
325
  * Create a heading inside an EXISTING project; the new heading's uuid is
227
326
  * on the result. Delivered through the Things proxy shortcuts (run
228
- * `things setup shortcuts` once first).
327
+ * `things setup shortcuts` once first). A `placement` positions the new
328
+ * heading among the project's headings via a native `move-heading` leg
329
+ * (requires allow-experimental); omitted, it appends. Anchor uuids in the
330
+ * placement are resolved by the caller.
229
331
  */
230
- createHeading(project: ContainerRef, title: string, options?: WriteOptions): Promise<MutationResult>;
332
+ addHeading(project: ContainerRef, title: string, placement?: HeadingPlacement, options?: WriteOptions): Promise<MutationResult>;
231
333
  /** Rename a heading in place (works on archived headings too). */
232
334
  renameHeading(uuid: string, title: string, options?: WriteOptions): Promise<MutationResult>;
335
+ /**
336
+ * Reposition one or more of a project's headings as an ordered block
337
+ * (selection order = resulting order; children follow). `headings` and the
338
+ * placement anchors are resolved heading uuids. Native reorder wire
339
+ * (requires allow-experimental).
340
+ */
341
+ moveHeading(project: ContainerRef, headings: string[], placement: HeadingPlacement, options?: WriteOptions): Promise<MutationResult>;
342
+ /**
343
+ * Relocate ONE heading (with its children) to a DIFFERENT project — the
344
+ * cross-project move the within-project `moveHeading` reorder cannot express
345
+ * (HEADXPROJ). GUI-only: drives the heading row's `…` ellipsis → Move… →
346
+ * keyboard-driven project picker, so it needs `ui.enabled` + the
347
+ * `dangerouslyDriveGui` acknowledgement. `heading` is an exact title or uuid
348
+ * within `project`; both same-titled source headings AND a same-titled
349
+ * destination project fail closed (the drive addresses by title). No wired
350
+ * undo — it is app-reversible by moving it back.
351
+ */
352
+ moveHeadingToProject(project: ContainerRef, heading: string, toProject: ContainerRef, options?: WriteOptions): Promise<MutationResult>;
353
+ /**
354
+ * Dissolve a heading: remove it while its to-dos SURVIVE as direct children
355
+ * of the project (heading→NULL, keeping their order) — NOT trashed (DISS1).
356
+ * This is the OPPOSITE of a delete cascade (contrast the Shortcuts heading
357
+ * delete, P12, which trashes the children). GUI-only (heading row's `…`
358
+ * ellipsis → Delete), so it needs `ui.enabled` + `dangerouslyDriveGui`. Fails
359
+ * closed on a title shared by another heading in the project. No wired undo —
360
+ * the children are kept, so re-create the heading and move them back to
361
+ * reverse. `uuid` is the heading.
362
+ */
363
+ dissolveHeading(uuid: string, options?: WriteOptions): Promise<MutationResult>;
233
364
  /**
234
365
  * Archive a heading (the UI's Archive — it leaves the active project
235
366
  * view, reversibly). With open children the policy is mandatory:
@@ -255,6 +386,14 @@ export interface ThingsClient {
255
386
  moveProject(uuid: string, area: ContainerRef, options?: WriteOptions): Promise<MutationResult>;
256
387
  /** Detach a project from its current area. */
257
388
  detachProject(uuid: string, options?: WriteOptions): Promise<MutationResult>;
389
+ /**
390
+ * Move one or more projects as an ordered block (spec §4/§5): --to-area, or
391
+ * --no-area to leave the area, plus an optional position — or a position
392
+ * alone to reorder them among their siblings.
393
+ */
394
+ moveProjects(request: ProjectMoveRequest, options?: WriteOptions): Promise<MoveResult>;
395
+ /** Reorder projects IN PLACE among their siblings (spec §4). */
396
+ reorderProjects(request: ReorderRequest, options?: WriteOptions): Promise<MoveResult>;
258
397
  /** Cancel a project — open children are canceled with it, so the children policy is mandatory. */
259
398
  cancelProject(uuid: string, policy: Pick<ProjectCancelParams, "children">, options?: WriteOptions): Promise<MutationResult>;
260
399
  /**
@@ -284,7 +423,7 @@ export interface ThingsClient {
284
423
  * two-key gated, same as makeRepeatingProject). Give an `area` to place it,
285
424
  * or omit it to create in Someday. The new template's uuid is on the result.
286
425
  */
287
- createRepeatingProject(params: ProjectCreateRepeatingParams, options?: WriteOptions): Promise<MutationResult>;
426
+ addRepeatingProject(params: ProjectAddRepeatingParams, options?: WriteOptions): Promise<MutationResult>;
288
427
  /** Replace a project's full tag set (an empty list clears all tags). */
289
428
  setProjectTags(uuid: string, tags: string[], options?: WriteOptions): Promise<MutationResult>;
290
429
  /** Merge: current project tags + new ones, then replace. */
@@ -303,9 +442,14 @@ export interface ThingsClient {
303
442
  reorder(params: ReorderParams, options?: WriteOptions): Promise<ReorderResult>;
304
443
  /**
305
444
  * Run N ops sequentially and independently — no transactions, a failure
306
- * does not roll back earlier ops. Per-op results.
445
+ * does not roll back earlier ops. Per-op results stream through `onResult`;
446
+ * the resolved {@link BatchResult} adds the temp-id → uuid mapping and the
447
+ * batch-level undo token (undo the whole submission as one unit). An op may
448
+ * carry a `tempId` (a handle bound to its created uuid, referenceable as
449
+ * `"$name"` by a later op) and/or an `opId` (idempotency id — a resubmitted
450
+ * op with a matching applied id is skipped, not re-created).
307
451
  */
308
- batch(ops: BatchOp[], options?: BatchOptions, onResult?: (result: BatchItemResult) => void): Promise<BatchItemResult[]>;
452
+ batch(ops: BatchOp[], options?: BatchOptions, onResult?: (result: BatchItemResult) => void): Promise<BatchResult>;
309
453
  /**
310
454
  * Undo changes made through this client, newest first, by applying the
311
455
  * inverse change. Selection: `last` trailing changes (default 1), narrowed