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
package/dist/config.js CHANGED
@@ -13,6 +13,41 @@ const PROFILE_DEFAULT_TIER = {
13
13
  workstation: 1,
14
14
  "dedicated-server": 2,
15
15
  };
16
+ /**
17
+ * A THINGS_API_* boolean override. Returns the forced value when the env var
18
+ * holds a recognized token, or undefined when unset/unrecognized (so the
19
+ * caller falls through to stored config, then the built-in default). The
20
+ * override is BIDIRECTIONAL — a recognized value always wins over stored
21
+ * config, so an env var can force a vector off as well as on. `trueToken` /
22
+ * `falseToken` let THINGS_API_AUDIT keep its legacy on/off vocabulary while
23
+ * the vectors use true/false.
24
+ */
25
+ function boolEnvOverride(raw, trueToken, falseToken) {
26
+ if (raw === trueToken)
27
+ return true;
28
+ if (raw === falseToken)
29
+ return false;
30
+ return undefined;
31
+ }
32
+ /** THINGS_API_PROFILE override, or undefined when unset/unrecognized. */
33
+ function profileEnvOverride(raw) {
34
+ return raw === "workstation" || raw === "dedicated-server" ? raw : undefined;
35
+ }
36
+ /** THINGS_API_MAX_DISRUPTION override, or undefined when unset/unrecognized. */
37
+ function tierEnvOverride(raw) {
38
+ return raw !== undefined && /^[0-3]$/.test(raw) ? Number(raw) : undefined;
39
+ }
40
+ /**
41
+ * A THINGS_API_BOUNCE_MAX_ITEMS override, or undefined when unset/unrecognized.
42
+ * Only a positive integer is accepted (a bounce touches at least one item);
43
+ * anything else falls through to stored config, then the built-in default.
44
+ */
45
+ function positiveIntEnvOverride(raw) {
46
+ if (raw === undefined || !/^[0-9]+$/.test(raw))
47
+ return undefined;
48
+ const n = Number(raw);
49
+ return Number.isInteger(n) && n > 0 ? n : undefined;
50
+ }
16
51
  function configFilePath(env) {
17
52
  return join(configDir(env), "config.json");
18
53
  }
@@ -27,13 +62,12 @@ export function loadConfig(env = process.env) {
27
62
  // Malformed config falls back to defaults; doctor reports it.
28
63
  }
29
64
  }
30
- const profile = env["THINGS_API_PROFILE"] === "dedicated-server" || file.profile === "dedicated-server"
31
- ? "dedicated-server"
32
- : "workstation";
33
- const envTier = env["THINGS_API_MAX_DISRUPTION"];
34
- const maxDisruption = (envTier !== undefined && /^[0-3]$/.test(envTier)
35
- ? Number(envTier)
36
- : (file.maxDisruption ?? PROFILE_DEFAULT_TIER[profile]));
65
+ // Precedence for every key: env > stored > default. A recognized env value
66
+ // always wins over stored config; an unset/unrecognized one falls through.
67
+ const profile = profileEnvOverride(env["THINGS_API_PROFILE"]) ?? file.profile ?? "workstation";
68
+ const maxDisruption = tierEnvOverride(env["THINGS_API_MAX_DISRUPTION"]) ??
69
+ file.maxDisruption ??
70
+ PROFILE_DEFAULT_TIER[profile];
37
71
  let username = "unknown";
38
72
  try {
39
73
  username = userInfo().username;
@@ -41,16 +75,32 @@ export function loadConfig(env = process.env) {
41
75
  catch {
42
76
  // leave "unknown"
43
77
  }
78
+ const auditEnv = boolEnvOverride(env["THINGS_API_AUDIT"], "on", "off");
79
+ const experimentalEnv = boolEnvOverride(env["THINGS_API_ALLOW_EXPERIMENTAL"], "true", "false");
80
+ const bounceEnabledEnv = boolEnvOverride(env["THINGS_API_BOUNCE_ENABLED"], "true", "false");
81
+ const bounceMaxItemsEnv = positiveIntEnvOverride(env["THINGS_API_BOUNCE_MAX_ITEMS"]);
82
+ const uiEnv = boolEnvOverride(env["THINGS_API_UI_ENABLED"], "true", "false");
83
+ // Scope precedence within the config layer: THINGS_API_SCOPE env > stored
84
+ // `scope` key. The MCP `--scope` flag outranks BOTH and is applied above this
85
+ // layer, at openThings(). Fail-closed resolution to a container happens there.
86
+ const scopeEnv = env["THINGS_API_SCOPE"];
87
+ const scope = scopeEnv !== undefined && scopeEnv !== ""
88
+ ? { ref: scopeEnv, source: "env" }
89
+ : file.scope !== undefined && file.scope !== ""
90
+ ? { ref: file.scope, source: "config" }
91
+ : null;
44
92
  return {
45
93
  profile,
46
94
  maxDisruption,
47
95
  actor: env["THINGS_API_ACTOR"] ?? file.actor ?? `${username}@cli`,
48
- auditEnabled: env["THINGS_API_AUDIT"] === "off" ? false : (file.auditEnabled ?? true),
96
+ auditEnabled: auditEnv ?? file.auditEnabled ?? true,
49
97
  acceptedFingerprint: file.acceptedFingerprint ?? null,
50
- allowExperimental: env["THINGS_API_ALLOW_EXPERIMENTAL"] === "true" || file.allowExperimental === true,
51
- ui: {
52
- enabled: env["THINGS_API_UI_ENABLED"] === "true" || file.uiEnabled === true,
53
- },
98
+ certifiedAppVersion: file.certifiedAppVersion ?? null,
99
+ allowExperimental: experimentalEnv ?? file.allowExperimental ?? true,
100
+ bounceEnabled: bounceEnabledEnv ?? file.bounceEnabled ?? true,
101
+ bounceMaxItems: bounceMaxItemsEnv ?? file.bounceMaxItems ?? 30,
102
+ ui: { enabled: uiEnv ?? file.uiEnabled ?? false },
103
+ scope,
54
104
  host: hostname(),
55
105
  };
56
106
  }
@@ -76,4 +126,62 @@ export function saveConfigKey(key, value, env = process.env) {
76
126
  }
77
127
  writeFileSync(path, `${JSON.stringify(file, null, 2)}\n`);
78
128
  }
129
+ function readConfigFile(env) {
130
+ const path = configFilePath(env);
131
+ if (existsSync(path)) {
132
+ try {
133
+ return JSON.parse(readFileSync(path, "utf8"));
134
+ }
135
+ catch {
136
+ // Malformed config → treated as no stored keys (doctor reports it).
137
+ }
138
+ }
139
+ return {};
140
+ }
141
+ /**
142
+ * The effective value + provenance of every config key, in a stable order —
143
+ * backing `things config get`. Env/stored/default detection mirrors
144
+ * {@link loadConfig} exactly, so a key reads `env` only when an env var actually
145
+ * overrode it (a THINGS_API_* value that loadConfig honors), `stored` when the
146
+ * on-disk config supplied it, `derived` for a read-only value computed from the
147
+ * environment or another key, and `default` otherwise.
148
+ */
149
+ function configKeyView(key, value, stored, fromEnv) {
150
+ return { key, value, source: fromEnv ? "env" : stored ? "stored" : "default" };
151
+ }
152
+ export function describeConfig(env = process.env) {
153
+ const file = readConfigFile(env);
154
+ const cfg = loadConfig(env);
155
+ const view = configKeyView;
156
+ const tierFromEnv = tierEnvOverride(env["THINGS_API_MAX_DISRUPTION"]) !== undefined;
157
+ const maxDisruption = {
158
+ key: "maxDisruption",
159
+ value: cfg.maxDisruption,
160
+ // env > stored > profile-derived default (the built-in fallback is
161
+ // computed from `profile`, so it reports `derived`, not `default`).
162
+ source: tierFromEnv ? "env" : file.maxDisruption !== undefined ? "stored" : "derived",
163
+ };
164
+ return [
165
+ view("profile", cfg.profile, file.profile !== undefined, profileEnvOverride(env["THINGS_API_PROFILE"]) !== undefined),
166
+ maxDisruption,
167
+ view("actor", cfg.actor, file.actor !== undefined, env["THINGS_API_ACTOR"] !== undefined),
168
+ view("auditEnabled", cfg.auditEnabled, file.auditEnabled !== undefined, boolEnvOverride(env["THINGS_API_AUDIT"], "on", "off") !== undefined),
169
+ view("accepted-fingerprint", cfg.acceptedFingerprint, file.acceptedFingerprint !== undefined, false),
170
+ view("certified-app-version", cfg.certifiedAppVersion, file.certifiedAppVersion !== undefined, false),
171
+ view("allow-experimental", cfg.allowExperimental, file.allowExperimental !== undefined, boolEnvOverride(env["THINGS_API_ALLOW_EXPERIMENTAL"], "true", "false") !== undefined),
172
+ view("bounce-enabled", cfg.bounceEnabled, file.bounceEnabled !== undefined, boolEnvOverride(env["THINGS_API_BOUNCE_ENABLED"], "true", "false") !== undefined),
173
+ view("bounce-max-items", cfg.bounceMaxItems, file.bounceMaxItems !== undefined, positiveIntEnvOverride(env["THINGS_API_BOUNCE_MAX_ITEMS"]) !== undefined),
174
+ view("ui-enabled", cfg.ui.enabled, file.uiEnabled !== undefined, boolEnvOverride(env["THINGS_API_UI_ENABLED"], "true", "false") !== undefined),
175
+ // The container scope's RAW ref (resolved to a container at open); env >
176
+ // stored. A stored value jails every process on this host — see the
177
+ // trust-model note in docs/design/container-scope.md.
178
+ view("scope", cfg.scope?.ref ?? null, file.scope !== undefined, env["THINGS_API_SCOPE"] !== undefined && env["THINGS_API_SCOPE"] !== ""),
179
+ // Read-only, computed from the environment; not settable via `config set`.
180
+ { key: "host", value: cfg.host, source: "derived" },
181
+ ];
182
+ }
183
+ /** One key's effective view, or undefined for an unknown key (`config get <key>`). */
184
+ export function getConfigKey(key, env = process.env) {
185
+ return describeConfig(env).find((v) => v.key === key);
186
+ }
79
187
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -13,7 +13,7 @@ export declare const API_VERSION = 1;
13
13
  * Package version, surfaced by `things --version` and the MCP serverInfo.
14
14
  * Kept in lockstep with package.json by a contract test.
15
15
  */
16
- export declare const PKG_VERSION = "0.11.0";
16
+ export declare const PKG_VERSION = "0.13.0";
17
17
  /**
18
18
  * Stable exit-code contract for the `things` CLI (mirrored by MCP error
19
19
  * codes). Part of the public API surface consumed by agents and scripts —
@@ -51,21 +51,29 @@ export interface SectionCount {
51
51
  total: number;
52
52
  }
53
53
  /**
54
- * List-view truncation metadata (ADDITIVE). Present on the meta of any read
55
- * command that applies a row limit; absent on unbounded/structured views.
56
- * `shown` items were returned of `total` that matched after all filters;
57
- * `limit` is the effective cap (null when the caller asked for all rows);
58
- * `truncated` is true exactly when `shown < total`. The dropped remainder is
59
- * `total - shown`. `sections` is present only on a split flat view (the Today
60
- * split), breaking the whole-view counts down per render section.
54
+ * The single truncation-metadata shape for every read (the `meta.truncation`
55
+ * field). `shown` items were returned of `total` that matched after all
56
+ * filters; `limit` is the effective cap (null when the caller asked for all
57
+ * rows, and always null on a grouped view whose caps are per-block); `truncated`
58
+ * is the UNIVERSAL completeness check — true exactly when anything was dropped
59
+ * (`shown < total`, or any block hid rows). The dropped remainder is
60
+ * `total - shown`.
61
+ *
62
+ * Two optional per-shape breakdowns hang off it: `sections` for a split flat
63
+ * view (the Today split — per render-section shown/total), and `blocks` for a
64
+ * grouped view (anytime/someday/`area show` — the identity-carrying per-block
65
+ * nesting). Exactly one of them is present on the shapes that have it; both are
66
+ * absent on a plain flat view.
61
67
  */
62
68
  export interface Truncation {
63
69
  shown: number;
64
70
  total: number;
65
71
  limit: number | null;
66
72
  truncated: boolean;
67
- /** Per-section shown/total breakdown for a split flat view; absent otherwise. */
73
+ /** Per-section shown/total breakdown for a split flat view (Today); absent otherwise. */
68
74
  sections?: SectionCount[];
75
+ /** Per-block nesting for a grouped view (anytime/someday/area card); absent otherwise. */
76
+ blocks?: GroupBlock[];
69
77
  }
70
78
  /**
71
79
  * One identity-carrying block of a grouped catalogue (anytime/someday) or a
@@ -103,12 +111,6 @@ export interface GroupBlock {
103
111
  /** Nested project blocks (anytime item-lists / someday active-project groups). Absent when none. */
104
112
  children?: GroupBlock[];
105
113
  }
106
- /** Grouped-view truncation metadata (ADDITIVE); the per-block counterpart of {@link Truncation}. */
107
- export interface GroupedTruncation {
108
- /** True when any block hid items. */
109
- truncated: boolean;
110
- blocks: GroupBlock[];
111
- }
112
114
  export interface EnvelopeMeta {
113
115
  /** Things database schema version (`Meta.databaseVersion`), null when no DB was opened. */
114
116
  dbVersion: number | null;
@@ -116,10 +118,13 @@ export interface EnvelopeMeta {
116
118
  fingerprint: "ok" | "drift" | "user-accepted" | "unknown";
117
119
  /** Wall-clock duration of the command in milliseconds. */
118
120
  elapsedMs: number;
119
- /** List-view truncation metadata; present only on limited flat read views. */
121
+ /**
122
+ * The read's completeness metadata (the single truncation shape). Present on
123
+ * any read that could drop rows — flat views (row `limit`), the Today split
124
+ * (`sections`), and grouped views (anytime/someday/`area show`, `blocks`).
125
+ * `meta.truncation.truncated` is the universal "did I see everything" check.
126
+ */
120
127
  truncation?: Truncation;
121
- /** Per-block truncation metadata; present only on grouped views (anytime/someday). */
122
- grouped?: GroupedTruncation;
123
128
  /**
124
129
  * The canonical `things …` command a sugar invocation normalized to (bare
125
130
  * noun, keyword-in-show, uuid/share-link routing). Present only on routed
@@ -143,6 +148,43 @@ export interface EnvelopeMeta {
143
148
  timezone: string;
144
149
  today: string;
145
150
  };
151
+ /**
152
+ * The active content filter this response was scoped to (ADDITIVE). Present
153
+ * ONLY when a scope was applied — currently `area` (the `--area` view filter),
154
+ * carrying the resolved area's uuid + title; ABSENT otherwise, so the wire
155
+ * shape is unchanged for unscoped reads (the `meta.clock` precedent).
156
+ */
157
+ filter?: {
158
+ area: {
159
+ uuid: string;
160
+ title: string;
161
+ };
162
+ };
163
+ /**
164
+ * Whole-view aggregate counts (ADDITIVE). Present ONLY on the `today` view: the
165
+ * app's sidebar count split — `dueOrOverdue` (open members whose deadline is
166
+ * due or overdue) vs. `other` (the rest). A convenience aggregate an agent
167
+ * would otherwise recompute over the rows; it lives here so `data` stays pure
168
+ * domain rows. Both counts are OPEN members only, and a `0` is meaningful.
169
+ */
170
+ counts?: {
171
+ dueOrOverdue: number;
172
+ other: number;
173
+ };
174
+ /**
175
+ * The active container scope this response was jailed to (ADDITIVE). Present
176
+ * ONLY when a scope is in force (the MCP `--scope` flag / `THINGS_API_SCOPE` /
177
+ * a stored `scope`), naming the container + where the scope came from; ABSENT
178
+ * otherwise, so the wire shape is unchanged for unscoped reads. Lets an agent
179
+ * know its own jail — which is not an oracle for what lies outside it (the
180
+ * `meta.clock` / `meta.filter` additive precedent).
181
+ */
182
+ scope?: {
183
+ kind: "area" | "project";
184
+ uuid: string;
185
+ title: string;
186
+ source: "flag" | "env" | "config";
187
+ };
146
188
  }
147
189
  export interface OkEnvelope<T> {
148
190
  apiVersion: typeof API_VERSION;
@@ -152,13 +194,38 @@ export interface OkEnvelope<T> {
152
194
  data: T;
153
195
  meta: EnvelopeMeta;
154
196
  }
197
+ /**
198
+ * The registry of stable machine-readable error codes an error envelope can
199
+ * carry — the compiler IS the registry. Every `error.code` value the surfaces
200
+ * emit is a member of this union, and the human-readable meaning of each is
201
+ * frozen at v1.0 (new codes may still be ADDED after v1.0 — that is
202
+ * non-breaking; a documented code's MEANING never changes). The canonical
203
+ * per-code table (meaning + the `detail` keys each may carry) lives in
204
+ * `docs/contract.md` (The error-code registry).
205
+ *
206
+ * Two members are template-literal families rather than fixed strings, because
207
+ * their suffix is minted in the write layer and the core deliberately never
208
+ * depends on it (see {@link blockedCode} / {@link verifyFailedCode}):
209
+ * - `verify-failed:${reason}` — a single mutation executed but read-after-write
210
+ * verification failed; the suffix is the reason (`timeout` | `mismatch` |
211
+ * `silent-noop`). The bare `verify-failed` (no suffix) is the multi-leg
212
+ * move/reorder failure.
213
+ * - `blocked:${suffix}` — a mutation refused before touching the app; the
214
+ * suffix is the specific hazard id (`H-…`) when one is named, else the block
215
+ * reason (`drift` | `disruption-tier` | `lock` | `environment` | `clock` |
216
+ * `scope`). The bare `blocked` is a policy refusal from the move planner.
217
+ *
218
+ * `blocked:drift` maps to exit code 5 (DriftBlocked); every other `blocked:*`
219
+ * maps to exit code 4 (Blocked).
220
+ */
221
+ export type ErrorCode = "usage" | "not-found" | "ambiguous" | "unsupported" | "environment" | "unexpected" | "bounce-aborted" | "verify-failed" | "blocked" | `verify-failed:${string}` | `blocked:${string}`;
155
222
  export interface ErrorEnvelope {
156
223
  apiVersion: typeof API_VERSION;
157
224
  ok: false;
158
225
  kind: "error";
159
226
  error: {
160
- /** Stable machine-readable code, mirrors the exit-code family (e.g. "verify-failed", "blocked"). */
161
- code: string;
227
+ /** Stable machine-readable code from the {@link ErrorCode} registry (mirrors the exit-code family, e.g. "verify-failed", "blocked:H-UNKNOWN-TAG"). */
228
+ code: ErrorCode;
162
229
  message: string;
163
230
  /**
164
231
  * Advisory attribution when failure signals point somewhere: e.g.
@@ -168,25 +235,117 @@ export interface ErrorEnvelope {
168
235
  likelyCause?: string;
169
236
  /** Actionable next step for the caller, when one exists. */
170
237
  remediation?: string;
171
- detail?: unknown;
172
238
  /**
173
- * Structured, machine-readable failure context (ADDITIVE). For an
174
- * unresolved show/bare-noun subject it carries `candidates` — the
175
- * did-you-mean title matches (standard item shapes, capped) so an agent
176
- * can self-correct without a second round-trip. For a bare mutation verb
177
- * (`things update <ref>`) it carries `suggestions` — the concrete
178
- * namespaced command(s) to run instead.
239
+ * The SINGLE structured, machine-readable failure-context object (there is
240
+ * no separate `details` field — the two were reconciled into this one). Each
241
+ * key is present only for the failures that produce it:
242
+ * - `expected` / `observed` a verify-failed mutation's expected delta and
243
+ * the observed post-write state.
244
+ * - `candidates` the disambiguation list for a not-found / ambiguous
245
+ * resolution (or a show/bare-noun did-you-mean): the ONE fixed, flag-
246
+ * invariant candidate shape (`CandidateRef`; see docs/contract.md), a
247
+ * LIVE-scoped pool capped at 8, so an agent can self-correct without
248
+ * another round-trip.
249
+ * - `suggestions` — for a bare mutation verb (`things update <ref>`), the
250
+ * concrete namespaced command(s) to run instead.
251
+ * - `considered` — the vectors weighed (and why each was rejected) for an
252
+ * unsupported operation.
253
+ * - `placed` / `remaining` / `cause` — a bounce reorder that aborted
254
+ * part-way: the items already placed, those not yet placed, and the cause.
255
+ * - `failed` / `completed` — a multi-leg move that failed mid-way: the leg
256
+ * that failed and the legs already completed before it.
179
257
  */
180
- details?: {
258
+ detail?: {
259
+ expected?: unknown;
260
+ observed?: Record<string, unknown> | null;
181
261
  candidates?: unknown[];
182
262
  suggestions?: string[];
263
+ considered?: {
264
+ vector: string;
265
+ why: string;
266
+ }[];
267
+ placed?: string[];
268
+ remaining?: string[];
269
+ cause?: unknown;
270
+ failed?: unknown;
271
+ completed?: unknown[];
183
272
  };
184
273
  };
185
274
  meta: EnvelopeMeta;
186
275
  }
187
276
  export type Envelope<T> = OkEnvelope<T> | ErrorEnvelope;
277
+ /**
278
+ * The envelope `kind` discriminators a SUCCESSFUL response carries today (the
279
+ * error envelope's `kind` is always the literal `"error"`). This union is the
280
+ * schema's record of the known payload classes — the flat-list reads
281
+ * (`data.items`), the sectioned reads (`data.sections`), the composite cards
282
+ * (`data.view`), the single-entity detail (`data.item`), the mutations/plans
283
+ * (flat `data` fields), and the diagnostic payloads.
284
+ *
285
+ * Per the compatibility covenant (docs/contract.md) a consumer MUST tolerate an
286
+ * UNKNOWN `kind`: adding a new kind is additive / non-breaking. So this union is
287
+ * "the kinds known to THIS build", not a closed set a generic reader may assume
288
+ * complete — the JSON Schema pins it as an enum so drift is caught, but a
289
+ * forward-compatible consumer routes on the wrapper it finds in `data`.
290
+ */
291
+ export type WireOkKind = "inbox" | "upcoming" | "logbook" | "trash" | "changes" | "search" | "projects" | "areas" | "tags" | "today" | "anytime" | "someday" | "area-view" | "project-view" | "detail" | "mutation-result" | "move-result" | "mutation-plan" | "move-plan" | "project-reopen" | "doctor" | "capabilities" | "config" | "legend" | "setup-shortcuts" | "install-skill";
292
+ /**
293
+ * The `data` payload of a successful envelope. Its CONCRETE shape is
294
+ * command-specific — one of the R1/R2 read wrappers (`item` | `view` | `items` |
295
+ * `sections`) or a mutation's flat result fields — and, crucially, entity
296
+ * payloads are omit-empty pruned on the wire (docs/design/contracts.md).
297
+ *
298
+ * COVERAGE BOUNDARY: this schema does NOT model the per-kind payload shapes. It
299
+ * pins the ENVELOPE layer exactly (`apiVersion`, `ok`, `kind`, `meta`, and the
300
+ * whole `error` object) and treats `data` as an open JSON object. Fully typing
301
+ * every kind's payload against the omit-empty wire shape is a separate, larger
302
+ * effort; until then `src/contracts.ts` and `docs/contract.md` remain the
303
+ * authoritative description of what each `kind`'s `data` contains.
304
+ */
305
+ export type WireData = Record<string, unknown>;
306
+ /** A successful `--json` envelope, exactly as emitted on stdout. */
307
+ export interface WireOkEnvelope {
308
+ apiVersion: typeof API_VERSION;
309
+ ok: true;
310
+ /** The payload class — see {@link WireOkKind}. */
311
+ kind: WireOkKind;
312
+ /** Command-specific payload; open at the schema layer (see {@link WireData}). */
313
+ data: WireData;
314
+ meta: EnvelopeMeta;
315
+ }
316
+ /**
317
+ * The machine-readable ROOT the envelope JSON Schema is generated from
318
+ * (`schema/envelope.schema.json`, produced by `npm run schema:gen`): the
319
+ * discriminated union — on the boolean `ok` — of a successful envelope and an
320
+ * {@link ErrorEnvelope}, exactly as written to stdout by the CLI `--json`
321
+ * surface and inherited by the MCP server. This is the same grammar
322
+ * docs/contract.md describes in prose; the schema is its generated, testable
323
+ * rendering. NB: the streaming commands (`batch`, `undo`) emit JSON Lines, a
324
+ * documented exception NOT covered by this envelope type.
325
+ */
326
+ export type WireEnvelope = WireOkEnvelope | ErrorEnvelope;
188
327
  export declare function okEnvelope<T>(kind: string, data: T, meta: EnvelopeMeta): OkEnvelope<T>;
189
328
  export declare function errorEnvelope(error: ErrorEnvelope["error"], meta: EnvelopeMeta): ErrorEnvelope;
329
+ /**
330
+ * Project a successful mutation/reorder/move outcome to its ENVELOPE `data`
331
+ * shape. The wire's mutation-success discriminator is REDUNDANT and is not
332
+ * emitted: the envelope already carries call success (`ok: true`, and the
333
+ * envelope `kind` names the payload class — `mutation-result` / `move-result`).
334
+ * So the result's internal `kind` discriminator is STRIPPED here — the emitted
335
+ * `data` has no `result` and no `kind`, just the payload fields (`op`, `uuid`,
336
+ * `title`, `undoToken`, `observed`, `vector`, `tier`, `touched`, notes, …).
337
+ * Only the internal tags `"ok"` / `"move-ok"` ever reach this boundary
338
+ * (failures route to error envelopes, dry-runs to the `mutation-plan` /
339
+ * `move-plan` kinds), so nothing is lost by dropping it. The library keeps the
340
+ * idiomatic `kind` discriminator on its in-memory
341
+ * `MutationResult`/`ReorderResult`/`MoveResult` unions; it simply never appears
342
+ * on the wire. BOTH consumer surfaces emit through it: the CLI (`mutation-result`
343
+ * / `move-result` envelopes) and the MCP mutation/move content block (phase-2
344
+ * framing sweep, 2026-07-31) — a dry-run routes to the bare `plan` on both.
345
+ */
346
+ export declare function mutationWireData<T extends {
347
+ kind: string;
348
+ }>(ok: T): Omit<T, "kind">;
190
349
  /**
191
350
  * Canonical machine-readable error CODE for a refused ("blocked") mutation: the
192
351
  * specific hazard id when one is named, else the block reason. Every surface —
package/dist/contracts.js CHANGED
@@ -13,7 +13,7 @@ export const API_VERSION = 1;
13
13
  * Package version, surfaced by `things --version` and the MCP serverInfo.
14
14
  * Kept in lockstep with package.json by a contract test.
15
15
  */
16
- export const PKG_VERSION = "0.11.0";
16
+ export const PKG_VERSION = "0.13.0";
17
17
  /**
18
18
  * Stable exit-code contract for the `things` CLI (mirrored by MCP error
19
19
  * codes). Part of the public API surface consumed by agents and scripts —
@@ -43,6 +43,27 @@ export function okEnvelope(kind, data, meta) {
43
43
  export function errorEnvelope(error, meta) {
44
44
  return { apiVersion: API_VERSION, ok: false, kind: "error", error, meta };
45
45
  }
46
+ /**
47
+ * Project a successful mutation/reorder/move outcome to its ENVELOPE `data`
48
+ * shape. The wire's mutation-success discriminator is REDUNDANT and is not
49
+ * emitted: the envelope already carries call success (`ok: true`, and the
50
+ * envelope `kind` names the payload class — `mutation-result` / `move-result`).
51
+ * So the result's internal `kind` discriminator is STRIPPED here — the emitted
52
+ * `data` has no `result` and no `kind`, just the payload fields (`op`, `uuid`,
53
+ * `title`, `undoToken`, `observed`, `vector`, `tier`, `touched`, notes, …).
54
+ * Only the internal tags `"ok"` / `"move-ok"` ever reach this boundary
55
+ * (failures route to error envelopes, dry-runs to the `mutation-plan` /
56
+ * `move-plan` kinds), so nothing is lost by dropping it. The library keeps the
57
+ * idiomatic `kind` discriminator on its in-memory
58
+ * `MutationResult`/`ReorderResult`/`MoveResult` unions; it simply never appears
59
+ * on the wire. BOTH consumer surfaces emit through it: the CLI (`mutation-result`
60
+ * / `move-result` envelopes) and the MCP mutation/move content block (phase-2
61
+ * framing sweep, 2026-07-31) — a dry-run routes to the bare `plan` on both.
62
+ */
63
+ export function mutationWireData(ok) {
64
+ const { kind: _kind, ...rest } = ok;
65
+ return rest;
66
+ }
46
67
  /**
47
68
  * Canonical machine-readable error CODE for a refused ("blocked") mutation: the
48
69
  * specific hazard id when one is named, else the block reason. Every surface —
@@ -1 +1 @@
1
- {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC;AAE7B;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC;AAEpC;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,eAAe;IACf,EAAE,EAAE,CAAC;IACL,4DAA4D;IAC5D,UAAU,EAAE,CAAC;IACb,kEAAkE;IAClE,KAAK,EAAE,CAAC;IACR,uGAAuG;IACvG,YAAY,EAAE,CAAC;IACf,wFAAwF;IACxF,OAAO,EAAE,CAAC;IACV,gGAAgG;IAChG,YAAY,EAAE,CAAC;IACf,6DAA6D;IAC7D,WAAW,EAAE,CAAC;IACd,kFAAkF;IAClF,WAAW,EAAE,CAAC;CACN,CAAC;AAyJX,MAAM,UAAU,UAAU,CAAI,IAAY,EAAE,IAAO,EAAE,IAAkB;IACrE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAA6B,EAAE,IAAkB;IAC7E,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC5E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,OAA4C;IACtE,OAAO,WAAW,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;AACvD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAmB,OAAsB;IACvE,OAAO,iBAAiB,OAAO,CAAC,MAAM,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAsD;IAEtD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC,EAAE,CAAC;IAC9C,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACnD,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,EAAE,CAAC;QACvE,OAAO,QAAQ,CAAC,YAAY,CAAC;IAC/B,CAAC;IACD,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;QAAE,OAAO,QAAQ,CAAC,OAAO,CAAC;IAClD,IAAI,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC;QAAE,OAAO,QAAQ,CAAC,WAAW,CAAC;IAC1D,OAAO,QAAQ,CAAC,YAAY,CAAC;AAC/B,CAAC"}
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC;AAE7B;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC;AAEpC;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,eAAe;IACf,EAAE,EAAE,CAAC;IACL,4DAA4D;IAC5D,UAAU,EAAE,CAAC;IACb,kEAAkE;IAClE,KAAK,EAAE,CAAC;IACR,uGAAuG;IACvG,YAAY,EAAE,CAAC;IACf,wFAAwF;IACxF,OAAO,EAAE,CAAC;IACV,gGAAgG;IAChG,YAAY,EAAE,CAAC;IACf,6DAA6D;IAC7D,WAAW,EAAE,CAAC;IACd,kFAAkF;IAClF,WAAW,EAAE,CAAC;CACN,CAAC;AA2UX,MAAM,UAAU,UAAU,CAAI,IAAY,EAAE,IAAO,EAAE,IAAkB;IACrE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAA6B,EAAE,IAAkB;IAC7E,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC5E,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,gBAAgB,CAA6B,EAAK;IAChE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,CAAC;IACpC,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,OAA4C;IACtE,OAAO,WAAW,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;AACvD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAmB,OAAsB;IACvE,OAAO,iBAAiB,OAAO,CAAC,MAAM,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAsD;IAEtD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC,EAAE,CAAC;IAC9C,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACnD,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,EAAE,CAAC;QACvE,OAAO,QAAQ,CAAC,YAAY,CAAC;IAC/B,CAAC;IACD,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;QAAE,OAAO,QAAQ,CAAC,OAAO,CAAC;IAClD,IAAI,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC;QAAE,OAAO,QAAQ,CAAC,WAAW,CAAC;IAC1D,OAAO,QAAQ,CAAC,YAAY,CAAC;AAC/B,CAAC"}
@@ -13,6 +13,9 @@ export const DB_V26 = {
13
13
  // deadlineSuppressionDate):
14
14
  // sha256:5526059b10ffffe1b67f796d031857d030403bd5b747374646a2803a55c0e5c3
15
15
  fingerprint: "sha256:784bd2f6533e6f85e053b0ec68958083d4ebca11c152ad1d2935178240d4c52b",
16
- knownThingsAppVersions: ["3.22.11"],
16
+ // Things 3.22.12 (build 32212016) ships the IDENTICAL DB v26 schema (fingerprint
17
+ // byte-identical) and an identical Things.sdef — a behavioral-only update, re-certified
18
+ // 2026-08-03 against golden-v2 (drift-runbook step 3; assumption-register *Confirmed under*).
19
+ knownThingsAppVersions: ["3.22.11", "3.22.12"],
17
20
  };
18
21
  //# sourceMappingURL=db-v26.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"db-v26.js","sourceRoot":"","sources":["../../../src/db/baselines/db-v26.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAa;IAC9B,eAAe,EAAE,EAAE;IACnB,oEAAoE;IACpE,0EAA0E;IAC1E,yEAAyE;IACzE,kEAAkE;IAClE,4BAA4B;IAC5B,4EAA4E;IAC5E,WAAW,EAAE,yEAAyE;IACtF,sBAAsB,EAAE,CAAC,SAAS,CAAC;CACpC,CAAC"}
1
+ {"version":3,"file":"db-v26.js","sourceRoot":"","sources":["../../../src/db/baselines/db-v26.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAa;IAC9B,eAAe,EAAE,EAAE;IACnB,oEAAoE;IACpE,0EAA0E;IAC1E,yEAAyE;IACzE,kEAAkE;IAClE,4BAA4B;IAC5B,4EAA4E;IAC5E,WAAW,EAAE,yEAAyE;IACtF,iFAAiF;IACjF,wFAAwF;IACxF,8FAA8F;IAC9F,sBAAsB,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;CAC/C,CAAC"}
@@ -4,7 +4,7 @@ import { type CertificationStatus } from "./write/vectors/ui-certification.ts";
4
4
  import { type AvailabilityDeps, type ShortcutsState, type UrlSchemeState } from "./write/availability.ts";
5
5
  import { type EnvironmentChange, type EnvironmentTracker, type EnvironmentTuple } from "./write/environment.ts";
6
6
  import { type SyncHealth, type SyncHealthDeps } from "./sync-health.ts";
7
- import { ExitCode, type EnvelopeMeta } from "./contracts.ts";
7
+ import { ExitCode, type EnvelopeMeta, type ErrorCode } from "./contracts.ts";
8
8
  export interface DiagnoseReport {
9
9
  db: {
10
10
  path: string;
@@ -21,11 +21,43 @@ export interface DiagnoseReport {
21
21
  };
22
22
  app: {
23
23
  installed: boolean;
24
+ /** Installed app version (CFBundleShortVersionString); null when unreadable. */
25
+ version: string | null;
26
+ /**
27
+ * The app version the behavioral LAWS were last certified against
28
+ * (config `certified-app-version`); null when never set.
29
+ */
30
+ certifiedVersion: string | null;
31
+ /**
32
+ * True when the installed version is known, a certified version is set, and
33
+ * they differ — a PASSIVE signal that the behavioral laws
34
+ * (docs/reference/assumption-register.md) may have moved with zero schema
35
+ * delta. Non-blocking: writes stay enabled; doctor emits a notice pointing
36
+ * at the drift suite. False when unset/unknown/matching.
37
+ */
38
+ behavioralDrift: boolean;
24
39
  };
25
40
  writes: {
26
41
  enabled: boolean;
27
42
  reason: string;
28
43
  };
44
+ /**
45
+ * The active container scope (from THINGS_API_SCOPE / the stored `scope` key),
46
+ * so the jail is never silently on. `requested` is the raw ref (null when
47
+ * unscoped); `resolved` names the container it pins to (null when the ref no
48
+ * longer resolves — a fail-closed empty jail). The MCP `--scope` flag is
49
+ * per-process and not visible here.
50
+ */
51
+ scope: {
52
+ requested: string | null;
53
+ source: "env" | "config" | null;
54
+ resolved: {
55
+ kind: "area" | "project";
56
+ uuid: string;
57
+ title: string;
58
+ } | null;
59
+ detail: string;
60
+ };
29
61
  experimental: {
30
62
  /** config allowExperimental (opt-in for private-surface capabilities). */
31
63
  enabled: boolean;
@@ -132,7 +164,7 @@ export interface DiagnoseOptions {
132
164
  export interface DiagnoseResult {
133
165
  report: DiagnoseReport | null;
134
166
  error: {
135
- code: string;
167
+ code: ErrorCode;
136
168
  message: string;
137
169
  remediation?: string;
138
170
  } | null;