things-api 0.16.0 → 0.18.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 +1 -1
  2. package/deputy/VERSION +1 -0
  3. package/deputy/helpers-Info.plist +23 -0
  4. package/deputy/prebuilt/Things API Helper.app/Contents/CodeResources +0 -0
  5. package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/Info.plist +20 -0
  6. package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/MacOS/things-reader +0 -0
  7. package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/_CodeSignature/CodeResources +115 -0
  8. package/deputy/prebuilt/Things API Helper.app/Contents/Info.plist +23 -0
  9. package/deputy/prebuilt/Things API Helper.app/Contents/MacOS/things-deputy +0 -0
  10. package/deputy/prebuilt/Things API Helper.app/Contents/_CodeSignature/CodeResources +125 -0
  11. package/deputy/reader/Info.plist +20 -0
  12. package/deputy/reader/entitlements.plist +15 -0
  13. package/deputy/reader/main.swift +491 -0
  14. package/deputy/src/main.swift +133 -0
  15. package/deputy/src/osascript.swift +102 -0
  16. package/deputy/src/server.swift +350 -0
  17. package/deputy/src/sqlite.swift +121 -0
  18. package/dist/cli/commands/doctor.js +55 -2
  19. package/dist/cli/commands/doctor.js.map +1 -1
  20. package/dist/cli/commands/helpers.d.ts +17 -0
  21. package/dist/cli/commands/helpers.js +148 -0
  22. package/dist/cli/commands/helpers.js.map +1 -0
  23. package/dist/cli/commands/op-result.d.ts +15 -0
  24. package/dist/cli/commands/op-result.js +39 -0
  25. package/dist/cli/commands/op-result.js.map +1 -0
  26. package/dist/cli/commands/repeat-flags.d.ts +3 -3
  27. package/dist/cli/commands/repeat-flags.js +90 -33
  28. package/dist/cli/commands/repeat-flags.js.map +1 -1
  29. package/dist/cli/commands/writes.js +79 -6
  30. package/dist/cli/commands/writes.js.map +1 -1
  31. package/dist/cli/help.js +13 -2
  32. package/dist/cli/help.js.map +1 -1
  33. package/dist/cli/helpers-check.d.ts +10 -0
  34. package/dist/cli/helpers-check.js +59 -0
  35. package/dist/cli/helpers-check.js.map +1 -0
  36. package/dist/cli/interrupt.d.ts +42 -0
  37. package/dist/cli/interrupt.js +105 -0
  38. package/dist/cli/interrupt.js.map +1 -0
  39. package/dist/cli/main.js +27 -1
  40. package/dist/cli/main.js.map +1 -1
  41. package/dist/client.js +19 -2
  42. package/dist/client.js.map +1 -1
  43. package/dist/config.d.ts +70 -0
  44. package/dist/config.js +25 -1
  45. package/dist/config.js.map +1 -1
  46. package/dist/contracts.d.ts +9 -2
  47. package/dist/contracts.js +1 -1
  48. package/dist/contracts.js.map +1 -1
  49. package/dist/db/baselines/db-v26.js +8 -4
  50. package/dist/db/baselines/db-v26.js.map +1 -1
  51. package/dist/db/baselines/db-v27.d.ts +42 -0
  52. package/dist/db/baselines/db-v27.js +47 -0
  53. package/dist/db/baselines/db-v27.js.map +1 -0
  54. package/dist/db/baselines/index.js +2 -1
  55. package/dist/db/baselines/index.js.map +1 -1
  56. package/dist/db/locate.d.ts +4 -1
  57. package/dist/db/locate.js +3 -1
  58. package/dist/db/locate.js.map +1 -1
  59. package/dist/db/schema.d.ts +1 -1
  60. package/dist/db/schema.js +9 -0
  61. package/dist/db/schema.js.map +1 -1
  62. package/dist/deputy/bridge-worker.d.ts +1 -0
  63. package/dist/deputy/bridge-worker.js +79 -0
  64. package/dist/deputy/bridge-worker.js.map +1 -0
  65. package/dist/deputy/bridge.d.ts +14 -0
  66. package/dist/deputy/bridge.js +70 -0
  67. package/dist/deputy/bridge.js.map +1 -0
  68. package/dist/deputy/client.d.ts +19 -0
  69. package/dist/deputy/client.js +104 -0
  70. package/dist/deputy/client.js.map +1 -0
  71. package/dist/deputy/db-facade.d.ts +18 -0
  72. package/dist/deputy/db-facade.js +71 -0
  73. package/dist/deputy/db-facade.js.map +1 -0
  74. package/dist/deputy/files.d.ts +1 -0
  75. package/dist/deputy/files.js +16 -0
  76. package/dist/deputy/files.js.map +1 -0
  77. package/dist/deputy/install.d.ts +105 -0
  78. package/dist/deputy/install.js +467 -0
  79. package/dist/deputy/install.js.map +1 -0
  80. package/dist/deputy/notice.d.ts +6 -0
  81. package/dist/deputy/notice.js +28 -0
  82. package/dist/deputy/notice.js.map +1 -0
  83. package/dist/deputy/notices.d.ts +31 -0
  84. package/dist/deputy/notices.js +94 -0
  85. package/dist/deputy/notices.js.map +1 -0
  86. package/dist/deputy/osa.d.ts +21 -0
  87. package/dist/deputy/osa.js +72 -0
  88. package/dist/deputy/osa.js.map +1 -0
  89. package/dist/deputy/protocol.d.ts +86 -0
  90. package/dist/deputy/protocol.js +106 -0
  91. package/dist/deputy/protocol.js.map +1 -0
  92. package/dist/deputy/routing.d.ts +63 -0
  93. package/dist/deputy/routing.js +338 -0
  94. package/dist/deputy/routing.js.map +1 -0
  95. package/dist/deputy/shortcuts-exec.d.ts +10 -0
  96. package/dist/deputy/shortcuts-exec.js +50 -0
  97. package/dist/deputy/shortcuts-exec.js.map +1 -0
  98. package/dist/diagnose.d.ts +43 -1
  99. package/dist/diagnose.js +64 -2
  100. package/dist/diagnose.js.map +1 -1
  101. package/dist/index.d.ts +16 -2
  102. package/dist/index.js +17 -1
  103. package/dist/index.js.map +1 -1
  104. package/dist/mcp/server.js +25 -7
  105. package/dist/mcp/server.js.map +1 -1
  106. package/dist/model/mappers.d.ts +12 -3
  107. package/dist/model/mappers.js +6 -1
  108. package/dist/model/mappers.js.map +1 -1
  109. package/dist/model/occurrences.d.ts +14 -1
  110. package/dist/model/occurrences.js +20 -4
  111. package/dist/model/occurrences.js.map +1 -1
  112. package/dist/model/recurrence.d.ts +64 -9
  113. package/dist/model/recurrence.js +94 -19
  114. package/dist/model/recurrence.js.map +1 -1
  115. package/dist/model/template-projection.d.ts +26 -0
  116. package/dist/model/template-projection.js +113 -0
  117. package/dist/model/template-projection.js.map +1 -0
  118. package/dist/op-result.d.ts +46 -0
  119. package/dist/op-result.js +156 -0
  120. package/dist/op-result.js.map +1 -0
  121. package/dist/paths.d.ts +8 -0
  122. package/dist/paths.js +10 -0
  123. package/dist/paths.js.map +1 -1
  124. package/dist/read/detail.js +7 -1
  125. package/dist/read/detail.js.map +1 -1
  126. package/dist/read/queries.js +8 -1
  127. package/dist/read/queries.js.map +1 -1
  128. package/dist/read/views.d.ts +6 -4
  129. package/dist/read/views.js +60 -18
  130. package/dist/read/views.js.map +1 -1
  131. package/dist/sync-health.js +8 -3
  132. package/dist/sync-health.js.map +1 -1
  133. package/dist/trace/tracer.d.ts +87 -0
  134. package/dist/trace/tracer.js +167 -0
  135. package/dist/trace/tracer.js.map +1 -0
  136. package/dist/write/accessibility-probe.js +4 -2
  137. package/dist/write/accessibility-probe.js.map +1 -1
  138. package/dist/write/automation-probe.js +5 -1
  139. package/dist/write/automation-probe.js.map +1 -1
  140. package/dist/write/availability.js +7 -3
  141. package/dist/write/availability.js.map +1 -1
  142. package/dist/write/clear-reminder.js +24 -21
  143. package/dist/write/clear-reminder.js.map +1 -1
  144. package/dist/write/commands.js +95 -45
  145. package/dist/write/commands.js.map +1 -1
  146. package/dist/write/completion-context.d.ts +57 -0
  147. package/dist/write/completion-context.js +49 -0
  148. package/dist/write/completion-context.js.map +1 -0
  149. package/dist/write/experimental.d.ts +19 -0
  150. package/dist/write/experimental.js +50 -0
  151. package/dist/write/experimental.js.map +1 -1
  152. package/dist/write/failure-hints.d.ts +10 -1
  153. package/dist/write/failure-hints.js +8 -0
  154. package/dist/write/failure-hints.js.map +1 -1
  155. package/dist/write/guards.d.ts +1 -1
  156. package/dist/write/guards.js +10 -0
  157. package/dist/write/guards.js.map +1 -1
  158. package/dist/write/move.js +14 -6
  159. package/dist/write/move.js.map +1 -1
  160. package/dist/write/operations.d.ts +40 -7
  161. package/dist/write/pipeline.d.ts +41 -0
  162. package/dist/write/pipeline.js +289 -19
  163. package/dist/write/pipeline.js.map +1 -1
  164. package/dist/write/pre-state.d.ts +1 -1
  165. package/dist/write/pre-state.js +35 -17
  166. package/dist/write/pre-state.js.map +1 -1
  167. package/dist/write/promote-clone.js +434 -19
  168. package/dist/write/promote-clone.js.map +1 -1
  169. package/dist/write/reorder.js +76 -27
  170. package/dist/write/reorder.js.map +1 -1
  171. package/dist/write/repeat-anchor.d.ts +140 -0
  172. package/dist/write/repeat-anchor.js +403 -0
  173. package/dist/write/repeat-anchor.js.map +1 -0
  174. package/dist/write/repeat-asserts.d.ts +28 -0
  175. package/dist/write/repeat-asserts.js +169 -0
  176. package/dist/write/repeat-asserts.js.map +1 -0
  177. package/dist/write/repeat-rule.js +37 -12
  178. package/dist/write/repeat-rule.js.map +1 -1
  179. package/dist/write/vectors/applescript.js +7 -16
  180. package/dist/write/vectors/applescript.js.map +1 -1
  181. package/dist/write/vectors/session-reachability.d.ts +133 -0
  182. package/dist/write/vectors/session-reachability.js +151 -0
  183. package/dist/write/vectors/session-reachability.js.map +1 -0
  184. package/dist/write/vectors/shortcuts.js +5 -14
  185. package/dist/write/vectors/shortcuts.js.map +1 -1
  186. package/dist/write/vectors/simulator.d.ts +16 -1
  187. package/dist/write/vectors/simulator.js +122 -32
  188. package/dist/write/vectors/simulator.js.map +1 -1
  189. package/dist/write/vectors/types.d.ts +183 -10
  190. package/dist/write/vectors/ui-recipes.d.ts +8 -0
  191. package/dist/write/vectors/ui-recipes.js +246 -58
  192. package/dist/write/vectors/ui-recipes.js.map +1 -1
  193. package/dist/write/vectors/ui.d.ts +156 -14
  194. package/dist/write/vectors/ui.js +846 -84
  195. package/dist/write/vectors/ui.js.map +1 -1
  196. package/dist/write/verify/delta.d.ts +12 -14
  197. package/dist/write/verify/delta.js +35 -34
  198. package/dist/write/verify/delta.js.map +1 -1
  199. package/dist/write/verify/poller.d.ts +13 -0
  200. package/dist/write/verify/poller.js +38 -0
  201. package/dist/write/verify/poller.js.map +1 -1
  202. package/package.json +8 -1
  203. package/schema/envelope.schema.json +22 -0
  204. package/scripts/build-helpers.sh +104 -0
  205. package/scripts/deputy-cert-setup.sh +60 -0
  206. package/skills/things-cli/SKILL.md +11 -3
  207. package/skills/things-cli/references/errors.md +4 -0
  208. package/skills/things-cli/references/repeating.md +69 -0
@@ -14,7 +14,7 @@ export declare const API_VERSION = 1;
14
14
  * Package version, surfaced by `things --version` and the MCP serverInfo.
15
15
  * Kept in lockstep with package.json by a contract test.
16
16
  */
17
- export declare const PKG_VERSION = "0.16.0";
17
+ export declare const PKG_VERSION = "0.18.0";
18
18
  /**
19
19
  * Stable exit-code contract for the `things` CLI (mirrored by MCP error
20
20
  * codes). Part of the public API surface consumed by agents and scripts —
@@ -219,7 +219,7 @@ export interface OkEnvelope<T> {
219
219
  * `blocked:drift` maps to exit code 5 (DriftBlocked); every other `blocked:*`
220
220
  * maps to exit code 4 (Blocked).
221
221
  */
222
- export type ErrorCode = "usage" | "not-found" | "ambiguous" | "unsupported" | "environment" | "unexpected" | "bounce-aborted" | "verify-failed" | "blocked" | `verify-failed:${string}` | `blocked:${string}`;
222
+ export type ErrorCode = "usage" | "not-found" | "ambiguous" | "unsupported" | "environment" | "unexpected" | "bounce-aborted" | "verify-failed" | "blocked" | "interrupted" | `verify-failed:${string}` | `blocked:${string}`;
223
223
  export interface ErrorEnvelope {
224
224
  apiVersion: typeof API_VERSION;
225
225
  ok: false;
@@ -270,6 +270,13 @@ export interface ErrorEnvelope {
270
270
  cause?: unknown;
271
271
  failed?: unknown;
272
272
  completed?: unknown[];
273
+ signal?: string;
274
+ op?: string;
275
+ uuid?: string | null;
276
+ step?: string;
277
+ outcome?: "uncertain";
278
+ recheck?: string;
279
+ tracePath?: string;
273
280
  };
274
281
  };
275
282
  meta: EnvelopeMeta;
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.16.0";
16
+ export const PKG_VERSION = "0.18.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 —
@@ -1 +1 @@
1
- {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,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"}
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,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;AAyVX,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"}
@@ -6,13 +6,17 @@
6
6
  */
7
7
  export const DB_V26 = {
8
8
  databaseVersion: 26,
9
- // Recomputed 2026-07-10: manifest gained TMSettings.logInterval and
10
- // TMSettings.manualLogDate (the log-move boundary completion ≠ logged);
11
- // verified identical from the live library (doctor) and the fixture DDL.
9
+ // Recomputed 2026-08-23: manifest gained TMTask.rt1_instanceCreationStartDate
10
+ // and TMTask.rt1_instanceCreationCount (the spawn cursor + tally the
11
+ // projection-day helper reads src/db/schema.ts says why); both columns are
12
+ // pre-existing in v26 and v27 alike, so this is a manifest widening, not a
13
+ // schema change, and DB_V27 shares the constant.
14
+ // Prior (2026-07-10 — TMSettings.logInterval + TMSettings.manualLogDate):
15
+ // sha256:784bd2f6533e6f85e053b0ec68958083d4ebca11c152ad1d2935178240d4c52b
12
16
  // Prior (2026-07-04, Phase 10b/10c — rt1_instanceCreationPaused +
13
17
  // deadlineSuppressionDate):
14
18
  // sha256:5526059b10ffffe1b67f796d031857d030403bd5b747374646a2803a55c0e5c3
15
- fingerprint: "sha256:784bd2f6533e6f85e053b0ec68958083d4ebca11c152ad1d2935178240d4c52b",
19
+ fingerprint: "sha256:d2b7e98c6d384ef1ecd256b1410a11652e80c5860cc48370ec9b4d6956c7d4df",
16
20
  // Things 3.22.12 (build 32212016) ships the IDENTICAL DB v26 schema (fingerprint
17
21
  // byte-identical) and an identical Things.sdef — a behavioral-only update, re-certified
18
22
  // 2026-08-03 against golden-v2 (drift-runbook step 3; assumption-register *Confirmed under*).
@@ -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,iFAAiF;IACjF,wFAAwF;IACxF,8FAA8F;IAC9F,sBAAsB,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;CAC/C,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,8EAA8E;IAC9E,qEAAqE;IACrE,6EAA6E;IAC7E,2EAA2E;IAC3E,iDAAiD;IACjD,0EAA0E;IAC1E,4EAA4E;IAC5E,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"}
@@ -0,0 +1,42 @@
1
+ import type { Baseline } from "../fingerprint.ts";
2
+ /**
3
+ * Schema baseline for Meta.databaseVersion = 27 (Things 3.23).
4
+ *
5
+ * Captured 2026-08-22 from a live Things 3.23 library: tables, columns, and
6
+ * triggers are byte-identical to v26 (fingerprint equal; every extra column
7
+ * pre-existing), and the migration's DDL delta is INDEX-ONLY — invisible to
8
+ * the fingerprint by design (indexes steer the query planner, not data
9
+ * semantics). The migration DID move data, re-measured in a clock-pinned lab
10
+ * clone and confirmed against a live 3.23 library — docs/lab/gv4-323-campaign.md
11
+ * §2.1–§2.3, which CORRECTS the first host-side reading in
12
+ * docs/lab/dbv27-migration-diff.md:
13
+ * - `rt1_nextInstanceStartDate` is SCOPED TO TEMPLATES, not retired: nulled on
14
+ * every non-template row, retained byte-identical on every repeating template
15
+ * that carried one (live host: 0 of 21,962 non-templates, 73 of 114 templates)
16
+ * — which is exactly what the new partial index is for. The 3.23 app still
17
+ * maintains the cache, so `src/model/template-projection.ts` is right to
18
+ * prefer it and derive only when it is absent.
19
+ * - the counter move is a `-1` sentinel → computed `0` back-fill on the row
20
+ * classes that never held a real count (leaf counts on `type=0`, checklist
21
+ * counts on `type=1`/`type=2`); rows carrying real counts were untouched. It
22
+ * is NOT a leaf self-count. Consumers that read `-1` as "unknown" now see a
23
+ * genuine 0.
24
+ * - the strictly-forward spawn-cursor rewrite did NOT reproduce in the lab
25
+ * (`rt1_instanceCreationStartDate` byte-unchanged); the host's move is best
26
+ * explained as cursor catch-up to "now" on first launch, not a schema rewrite.
27
+ * So writes re-enable on this baseline while doctor's passive behavioral notice
28
+ * keeps pointing at the re-certification (drift-runbook steps 2–3: new golden +
29
+ * lab:regress + assumption-register walk) until `certified-app-version` moves
30
+ * to 3.23.
31
+ *
32
+ * The shared fixture DDL (test/fixtures/schema-v26.sql — one file for both
33
+ * generations, the tables being identical) reproduces this fingerprint exactly
34
+ * (asserted by test/unit/fingerprint.test.ts). That fixture stamps
35
+ * `Meta.databaseVersion = 27` and carries the v27 index set; the simulator's
36
+ * `SIMULATED_DATABASE_VERSION` fence is pinned to 27 in lockstep.
37
+ *
38
+ * The hash is DB_V26's by construction — the two versions' depended shape is
39
+ * identical — so a manifest widening (2026-08-23: the template spawn cursor +
40
+ * tally) moves both baselines through the one constant.
41
+ */
42
+ export declare const DB_V27: Baseline;
@@ -0,0 +1,47 @@
1
+ import { DB_V26 } from "./db-v26.js";
2
+ /**
3
+ * Schema baseline for Meta.databaseVersion = 27 (Things 3.23).
4
+ *
5
+ * Captured 2026-08-22 from a live Things 3.23 library: tables, columns, and
6
+ * triggers are byte-identical to v26 (fingerprint equal; every extra column
7
+ * pre-existing), and the migration's DDL delta is INDEX-ONLY — invisible to
8
+ * the fingerprint by design (indexes steer the query planner, not data
9
+ * semantics). The migration DID move data, re-measured in a clock-pinned lab
10
+ * clone and confirmed against a live 3.23 library — docs/lab/gv4-323-campaign.md
11
+ * §2.1–§2.3, which CORRECTS the first host-side reading in
12
+ * docs/lab/dbv27-migration-diff.md:
13
+ * - `rt1_nextInstanceStartDate` is SCOPED TO TEMPLATES, not retired: nulled on
14
+ * every non-template row, retained byte-identical on every repeating template
15
+ * that carried one (live host: 0 of 21,962 non-templates, 73 of 114 templates)
16
+ * — which is exactly what the new partial index is for. The 3.23 app still
17
+ * maintains the cache, so `src/model/template-projection.ts` is right to
18
+ * prefer it and derive only when it is absent.
19
+ * - the counter move is a `-1` sentinel → computed `0` back-fill on the row
20
+ * classes that never held a real count (leaf counts on `type=0`, checklist
21
+ * counts on `type=1`/`type=2`); rows carrying real counts were untouched. It
22
+ * is NOT a leaf self-count. Consumers that read `-1` as "unknown" now see a
23
+ * genuine 0.
24
+ * - the strictly-forward spawn-cursor rewrite did NOT reproduce in the lab
25
+ * (`rt1_instanceCreationStartDate` byte-unchanged); the host's move is best
26
+ * explained as cursor catch-up to "now" on first launch, not a schema rewrite.
27
+ * So writes re-enable on this baseline while doctor's passive behavioral notice
28
+ * keeps pointing at the re-certification (drift-runbook steps 2–3: new golden +
29
+ * lab:regress + assumption-register walk) until `certified-app-version` moves
30
+ * to 3.23.
31
+ *
32
+ * The shared fixture DDL (test/fixtures/schema-v26.sql — one file for both
33
+ * generations, the tables being identical) reproduces this fingerprint exactly
34
+ * (asserted by test/unit/fingerprint.test.ts). That fixture stamps
35
+ * `Meta.databaseVersion = 27` and carries the v27 index set; the simulator's
36
+ * `SIMULATED_DATABASE_VERSION` fence is pinned to 27 in lockstep.
37
+ *
38
+ * The hash is DB_V26's by construction — the two versions' depended shape is
39
+ * identical — so a manifest widening (2026-08-23: the template spawn cursor +
40
+ * tally) moves both baselines through the one constant.
41
+ */
42
+ export const DB_V27 = {
43
+ databaseVersion: 27,
44
+ fingerprint: DB_V26.fingerprint,
45
+ knownThingsAppVersions: ["3.23"],
46
+ };
47
+ //# sourceMappingURL=db-v27.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-v27.js","sourceRoot":"","sources":["../../../src/db/baselines/db-v27.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,CAAC,MAAM,MAAM,GAAa;IAC9B,eAAe,EAAE,EAAE;IACnB,WAAW,EAAE,MAAM,CAAC,WAAW;IAC/B,sBAAsB,EAAE,CAAC,MAAM,CAAC;CACjC,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { DB_V26 } from "./db-v26.js";
2
+ import { DB_V27 } from "./db-v27.js";
2
3
  /** All known-good schema baselines, keyed by Meta.databaseVersion. */
3
- export const BASELINES = [DB_V26];
4
+ export const BASELINES = [DB_V26, DB_V27];
4
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/db/baselines/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,sEAAsE;AACtE,MAAM,CAAC,MAAM,SAAS,GAAwB,CAAC,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/db/baselines/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,sEAAsE;AACtE,MAAM,CAAC,MAAM,SAAS,GAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC"}
@@ -1,6 +1,9 @@
1
+ /** The Things group container, relative to $HOME (also the grant-ceremony target). */
2
+ export declare const THINGS_GROUP_CONTAINER = "Library/Group Containers/JLMPQHK86H.com.culturedcode.ThingsMac";
1
3
  export interface LocateResult {
2
4
  path: string;
3
- source: "option" | "env" | "container";
5
+ /** "deputy" = resolved by the things-deputy broker (its handshake names the container db). */
6
+ source: "option" | "env" | "container" | "deputy";
4
7
  /** Additional candidate paths that also matched (warn when >1). */
5
8
  otherCandidates: string[];
6
9
  }
package/dist/db/locate.js CHANGED
@@ -7,7 +7,9 @@
7
7
  import { globSync, statSync } from "node:fs";
8
8
  import { homedir } from "node:os";
9
9
  import { join } from "node:path";
10
- const CONTAINER_GLOB = join("Library/Group Containers/JLMPQHK86H.com.culturedcode.ThingsMac", "ThingsData-*/Things Database.thingsdatabase/main.sqlite");
10
+ /** The Things group container, relative to $HOME (also the grant-ceremony target). */
11
+ export const THINGS_GROUP_CONTAINER = "Library/Group Containers/JLMPQHK86H.com.culturedcode.ThingsMac";
12
+ const CONTAINER_GLOB = join(THINGS_GROUP_CONTAINER, "ThingsData-*/Things Database.thingsdatabase/main.sqlite");
11
13
  export class ThingsDbNotFoundError extends Error {
12
14
  constructor(searched) {
13
15
  super(`Things database not found (searched ${searched}). ` +
@@ -1 +1 @@
1
- {"version":3,"file":"locate.js","sourceRoot":"","sources":["../../src/db/locate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,cAAc,GAAG,IAAI,CACzB,gEAAgE,EAChE,yDAAyD,CAC1D,CAAC;AASF,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,QAAgB;QAC1B,KAAK,CACH,uCAAuC,QAAQ,KAAK;YAClD,8DAA8D;YAC9D,oDAAoD,CACvD,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,MAAM,UAAU,cAAc,CAAC,OAA4C;IACzE,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;QACpB,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;IACzE,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACzC,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;IAC/D,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,EAAE,IAAI,IAAI,OAAO,EAAE,CAAC;IACxC,MAAM,OAAO,GAAG,QAAQ,CAAC,cAAc,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IACtF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;IAC9D,CAAC;IACD,MAAM,OAAO,GAAG,OAAO;SACpB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;SACxD,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;IACxE,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,WAAW;QACnB,eAAe,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;KAC7D,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"locate.js","sourceRoot":"","sources":["../../src/db/locate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,sFAAsF;AACtF,MAAM,CAAC,MAAM,sBAAsB,GACjC,gEAAgE,CAAC;AAEnE,MAAM,cAAc,GAAG,IAAI,CACzB,sBAAsB,EACtB,yDAAyD,CAC1D,CAAC;AAUF,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,QAAgB;QAC1B,KAAK,CACH,uCAAuC,QAAQ,KAAK;YAClD,8DAA8D;YAC9D,oDAAoD,CACvD,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,MAAM,UAAU,cAAc,CAAC,OAA4C;IACzE,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;QACpB,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;IACzE,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACzC,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;IAC/D,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,EAAE,IAAI,IAAI,OAAO,EAAE,CAAC;IACxC,MAAM,OAAO,GAAG,QAAQ,CAAC,cAAc,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IACtF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;IAC9D,CAAC;IACD,MAAM,OAAO,GAAG,OAAO;SACpB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;SACxD,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;IACxE,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,WAAW;QACnB,eAAe,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;KAC7D,CAAC;AACJ,CAAC"}
@@ -8,7 +8,7 @@
8
8
  * - docs/atlas/schema-v26.md documents the semantics of every entry.
9
9
  */
10
10
  export declare const DEPENDED_TABLES: {
11
- readonly TMTask: readonly ["uuid", "type", "status", "stopDate", "trashed", "title", "notes", "creationDate", "userModificationDate", "start", "startDate", "startBucket", "reminderTime", "deadline", "deadlineSuppressionDate", "index", "todayIndex", "todayIndexReferenceDate", "area", "project", "heading", "untrashedLeafActionsCount", "openUntrashedLeafActionsCount", "checklistItemsCount", "openChecklistItemsCount", "rt1_repeatingTemplate", "rt1_recurrenceRule", "rt1_nextInstanceStartDate", "rt1_instanceCreationPaused", "repeater"];
11
+ readonly TMTask: readonly ["uuid", "type", "status", "stopDate", "trashed", "title", "notes", "creationDate", "userModificationDate", "start", "startDate", "startBucket", "reminderTime", "deadline", "deadlineSuppressionDate", "index", "todayIndex", "todayIndexReferenceDate", "area", "project", "heading", "untrashedLeafActionsCount", "openUntrashedLeafActionsCount", "checklistItemsCount", "openChecklistItemsCount", "rt1_repeatingTemplate", "rt1_recurrenceRule", "rt1_nextInstanceStartDate", "rt1_instanceCreationPaused", "rt1_instanceCreationStartDate", "rt1_instanceCreationCount", "repeater"];
12
12
  readonly TMArea: readonly ["uuid", "title", "visible", "index"];
13
13
  readonly TMTag: readonly ["uuid", "title", "shortcut", "usedDate", "parent", "index"];
14
14
  readonly TMTaskTag: readonly ["tasks", "tags"];
package/dist/db/schema.js CHANGED
@@ -38,6 +38,15 @@ export const DEPENDED_TABLES = {
38
38
  "rt1_recurrenceRule",
39
39
  "rt1_nextInstanceStartDate",
40
40
  "rt1_instanceCreationPaused",
41
+ // The spawn cursor and the spawn tally became load-bearing reads when the
42
+ // projection-day helper (src/model/template-projection.ts, #520/#522)
43
+ // started DERIVING a template's next occurrence from the decoded rule when
44
+ // the cached `rt1_nextInstanceStartDate` is absent: the cursor is where the
45
+ // derivation starts, the count is what an ends-AFTER rule is measured
46
+ // against. In the manifest, their loss in a future migration is a drift
47
+ // block with remediation instead of a raw SQLite error mid-read.
48
+ "rt1_instanceCreationStartDate",
49
+ "rt1_instanceCreationCount",
41
50
  "repeater",
42
51
  ],
43
52
  TMArea: ["uuid", "title", "visible", "index"],
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,MAAM,EAAE;QACN,MAAM;QACN,MAAM;QACN,QAAQ;QACR,UAAU;QACV,SAAS;QACT,OAAO;QACP,OAAO;QACP,cAAc;QACd,sBAAsB;QACtB,OAAO;QACP,WAAW;QACX,aAAa;QACb,cAAc;QACd,UAAU;QACV,yBAAyB;QACzB,OAAO;QACP,YAAY;QACZ,yBAAyB;QACzB,MAAM;QACN,SAAS;QACT,SAAS;QACT,2BAA2B;QAC3B,+BAA+B;QAC/B,qBAAqB;QACrB,yBAAyB;QACzB,uBAAuB;QACvB,oBAAoB;QACpB,2BAA2B;QAC3B,4BAA4B;QAC5B,UAAU;KACX;IACD,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC;IAC7C,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC;IACnE,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE;QACf,MAAM;QACN,OAAO;QACP,QAAQ;QACR,UAAU;QACV,OAAO;QACP,MAAM;QACN,cAAc;QACd,sBAAsB;KACvB;IACD,UAAU,EAAE;QACV,MAAM;QACN,8BAA8B;QAC9B,oBAAoB;QACpB,aAAa;QACb,eAAe;KAChB;IACD,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC;CACd,CAAC;AAIX,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAoB,CAAC;AAE3E;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,4BAA4B;IACtD,eAAe,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,8BAA8B;IAC1D,cAAc,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,2BAA2B;IACtD,oBAAoB,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,kBAAkB;IAChD,gBAAgB,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACxB,wBAAwB,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;CAC3B,CAAC;AAEX,iFAAiF;AACjF,MAAM,UAAU,CAAC,CAAC,UAAkB;IAClC,OAAO,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;AACjD,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,UAAU,CAAC,KAAoB;IAC7C,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClD,CAAC"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,MAAM,EAAE;QACN,MAAM;QACN,MAAM;QACN,QAAQ;QACR,UAAU;QACV,SAAS;QACT,OAAO;QACP,OAAO;QACP,cAAc;QACd,sBAAsB;QACtB,OAAO;QACP,WAAW;QACX,aAAa;QACb,cAAc;QACd,UAAU;QACV,yBAAyB;QACzB,OAAO;QACP,YAAY;QACZ,yBAAyB;QACzB,MAAM;QACN,SAAS;QACT,SAAS;QACT,2BAA2B;QAC3B,+BAA+B;QAC/B,qBAAqB;QACrB,yBAAyB;QACzB,uBAAuB;QACvB,oBAAoB;QACpB,2BAA2B;QAC3B,4BAA4B;QAC5B,0EAA0E;QAC1E,sEAAsE;QACtE,2EAA2E;QAC3E,4EAA4E;QAC5E,sEAAsE;QACtE,wEAAwE;QACxE,iEAAiE;QACjE,+BAA+B;QAC/B,2BAA2B;QAC3B,UAAU;KACX;IACD,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC;IAC7C,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC;IACnE,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE;QACf,MAAM;QACN,OAAO;QACP,QAAQ;QACR,UAAU;QACV,OAAO;QACP,MAAM;QACN,cAAc;QACd,sBAAsB;KACvB;IACD,UAAU,EAAE;QACV,MAAM;QACN,8BAA8B;QAC9B,oBAAoB;QACpB,aAAa;QACb,eAAe;KAChB;IACD,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC;CACd,CAAC;AAIX,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAoB,CAAC;AAE3E;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,4BAA4B;IACtD,eAAe,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,8BAA8B;IAC1D,cAAc,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,2BAA2B;IACtD,oBAAoB,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,kBAAkB;IAChD,gBAAgB,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACxB,wBAAwB,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;CAC3B,CAAC;AAEX,iFAAiF;AACjF,MAAM,UAAU,CAAC,CAAC,UAAkB;IAClC,OAAO,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;AACjD,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,UAAU,CAAC,KAAoB;IAC7C,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Worker half of the synchronous deputy bridge (see bridge.ts). Owns the
3
+ * long-lived socket to the deputy and services one request at a time: the main
4
+ * thread posts a request on the message port and blocks in Atomics.wait; this
5
+ * worker performs the socket round-trip, posts the response back, and bumps the
6
+ * shared counter to wake the main thread.
7
+ */
8
+ import { connect } from "node:net";
9
+ import { workerData } from "node:worker_threads";
10
+ const { socketPath, sab, port } = workerData;
11
+ const flag = new Int32Array(sab);
12
+ let socket = null;
13
+ let buffer = "";
14
+ let pendingLine = null;
15
+ let pendingError = null;
16
+ function resetSocket(err) {
17
+ socket = null;
18
+ buffer = "";
19
+ const reject = pendingError;
20
+ pendingLine = null;
21
+ pendingError = null;
22
+ reject?.(err);
23
+ }
24
+ function ensureSocket() {
25
+ if (socket !== null)
26
+ return Promise.resolve(socket);
27
+ return new Promise((resolve, reject) => {
28
+ const sock = connect(socketPath);
29
+ sock.setEncoding("utf8");
30
+ sock.once("connect", () => {
31
+ socket = sock;
32
+ resolve(sock);
33
+ });
34
+ sock.on("data", (chunk) => {
35
+ buffer += chunk;
36
+ const nl = buffer.indexOf("\n");
37
+ if (nl < 0)
38
+ return;
39
+ const line = buffer.slice(0, nl);
40
+ buffer = buffer.slice(nl + 1);
41
+ const deliver = pendingLine;
42
+ pendingLine = null;
43
+ pendingError = null;
44
+ deliver?.(line);
45
+ });
46
+ sock.on("error", (err) => {
47
+ if (socket === null)
48
+ reject(err);
49
+ resetSocket(err);
50
+ });
51
+ sock.on("close", () => {
52
+ resetSocket(new Error("deputy closed the connection"));
53
+ });
54
+ });
55
+ }
56
+ async function roundTrip(request) {
57
+ const sock = await ensureSocket();
58
+ const line = await new Promise((resolve, reject) => {
59
+ pendingLine = resolve;
60
+ pendingError = reject;
61
+ sock.write(`${JSON.stringify(request)}\n`);
62
+ });
63
+ return JSON.parse(line);
64
+ }
65
+ port.on("message", ({ bridgeId, request }) => {
66
+ void roundTrip(request)
67
+ .then((response) => ({ bridgeId, response: response }))
68
+ .catch((err) => ({
69
+ bridgeId,
70
+ error: err instanceof Error ? err.message : String(err),
71
+ }))
72
+ .then((envelope) => {
73
+ port.postMessage(envelope);
74
+ Atomics.add(flag, 0, 1);
75
+ Atomics.notify(flag, 0);
76
+ });
77
+ });
78
+ port.start();
79
+ //# sourceMappingURL=bridge-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-worker.js","sourceRoot":"","sources":["../../src/deputy/bridge-worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export declare class DeputySyncBridge {
2
+ private readonly worker;
3
+ private readonly flag;
4
+ private readonly port;
5
+ private seq;
6
+ constructor(socketPath: string);
7
+ /**
8
+ * Send one request and block until its response (or the deadline). Late
9
+ * responses from a previously timed-out request are drained and discarded by
10
+ * the id match, so one timeout never poisons the next call.
11
+ */
12
+ request(payload: Record<string, unknown>, timeoutMs: number): Record<string, unknown>;
13
+ close(): void;
14
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Synchronous bridge to the deputy for callers that cannot await — the
3
+ * DatabaseSync-shaped read facade and the sync consent probes. A dedicated
4
+ * worker thread owns the socket; the main thread posts a request, blocks in
5
+ * Atomics.wait on a shared counter, then drains the port with
6
+ * receiveMessageOnPort. One request is in flight at a time by construction
7
+ * (the main thread is blocked while it waits).
8
+ *
9
+ * The bridge must NOT be used for long-running osascript drives — blocking the
10
+ * event loop would suspend the drive watchdog and signal handlers. Async
11
+ * dispatch rides client.ts instead.
12
+ */
13
+ import { MessageChannel, receiveMessageOnPort, Worker, } from "node:worker_threads";
14
+ import { DeputyRequestError } from "./protocol.js";
15
+ export class DeputySyncBridge {
16
+ worker;
17
+ flag;
18
+ port;
19
+ seq = 0;
20
+ constructor(socketPath) {
21
+ const sab = new SharedArrayBuffer(4);
22
+ this.flag = new Int32Array(sab);
23
+ const channel = new MessageChannel();
24
+ this.port = channel.port1;
25
+ // Live TS source runs the .ts twin; the published build runs the emitted
26
+ // .js next to this module (same trick as src/cli/version.ts).
27
+ const ext = import.meta.url.endsWith(".ts") ? "ts" : "js";
28
+ this.worker = new Worker(new URL(`./bridge-worker.${ext}`, import.meta.url), {
29
+ workerData: { socketPath, sab, port: channel.port2 },
30
+ transferList: [channel.port2],
31
+ });
32
+ // The bridge must never keep the CLI process alive on its own.
33
+ this.worker.unref();
34
+ }
35
+ /**
36
+ * Send one request and block until its response (or the deadline). Late
37
+ * responses from a previously timed-out request are drained and discarded by
38
+ * the id match, so one timeout never poisons the next call.
39
+ */
40
+ request(payload, timeoutMs) {
41
+ const id = `s${++this.seq}`;
42
+ let seen = Atomics.load(this.flag, 0);
43
+ // oxlint-disable-next-line require-post-message-target-origin -- worker_threads port, no targetOrigin
44
+ this.port.postMessage({ bridgeId: id, request: payload });
45
+ const deadline = Date.now() + timeoutMs;
46
+ for (;;) {
47
+ let received = receiveMessageOnPort(this.port);
48
+ while (received !== undefined) {
49
+ const message = received.message;
50
+ if (message.bridgeId === id) {
51
+ if (message.error !== undefined) {
52
+ throw new DeputyRequestError("bridge-io", message.error);
53
+ }
54
+ return message.response ?? {};
55
+ }
56
+ received = receiveMessageOnPort(this.port);
57
+ }
58
+ const remaining = deadline - Date.now();
59
+ if (remaining <= 0) {
60
+ throw new DeputyRequestError("bridge-timeout", `the deputy did not answer within ${timeoutMs}ms`);
61
+ }
62
+ Atomics.wait(this.flag, 0, seen, remaining);
63
+ seen = Atomics.load(this.flag, 0);
64
+ }
65
+ }
66
+ close() {
67
+ void this.worker.terminate();
68
+ }
69
+ }
70
+ //# sourceMappingURL=bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/deputy/bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export declare class DeputyAsyncClient {
2
+ private socket;
3
+ private buffer;
4
+ private seq;
5
+ private readonly pending;
6
+ private readonly socketPath;
7
+ constructor(socketPath: string);
8
+ private ensureSocket;
9
+ private onData;
10
+ private failAll;
11
+ /**
12
+ * Send one request; resolves with the raw response object (protocol errors
13
+ * included — the caller inspects `ok`). Rejects only on transport failure or
14
+ * client-side deadline (`timeoutMs` should exceed any deputy-side timeout so
15
+ * the deputy's own honest answer wins).
16
+ */
17
+ request(payload: Record<string, unknown>, timeoutMs: number): Promise<Record<string, unknown>>;
18
+ close(): void;
19
+ }
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Async deputy client for event-loop-friendly callers: the applescript vector
3
+ * and the ui vector's step runner. Long osascript drives ride this client so
4
+ * timers (drive watchdog) and signal handlers keep running; synchronous
5
+ * callers ride bridge.ts instead. One shared socket, requests matched by id.
6
+ */
7
+ import { connect } from "node:net";
8
+ import { DeputyRequestError } from "./protocol.js";
9
+ export class DeputyAsyncClient {
10
+ socket = null;
11
+ buffer = "";
12
+ seq = 0;
13
+ pending = new Map();
14
+ socketPath;
15
+ constructor(socketPath) {
16
+ this.socketPath = socketPath;
17
+ }
18
+ ensureSocket() {
19
+ if (this.socket !== null)
20
+ return Promise.resolve(this.socket);
21
+ return new Promise((resolve, reject) => {
22
+ const sock = connect(this.socketPath);
23
+ sock.setEncoding("utf8");
24
+ sock.once("connect", () => {
25
+ this.socket = sock;
26
+ // An idle deputy connection must never keep the CLI process alive.
27
+ sock.unref();
28
+ resolve(sock);
29
+ });
30
+ sock.on("data", (chunk) => this.onData(chunk));
31
+ sock.on("error", (err) => {
32
+ if (this.socket === null)
33
+ reject(err);
34
+ this.failAll(err);
35
+ });
36
+ sock.on("close", () => this.failAll(new Error("deputy closed the connection")));
37
+ });
38
+ }
39
+ onData(chunk) {
40
+ this.buffer += chunk;
41
+ for (;;) {
42
+ const nl = this.buffer.indexOf("\n");
43
+ if (nl < 0)
44
+ return;
45
+ const line = this.buffer.slice(0, nl);
46
+ this.buffer = this.buffer.slice(nl + 1);
47
+ let parsed;
48
+ try {
49
+ parsed = JSON.parse(line);
50
+ }
51
+ catch {
52
+ continue;
53
+ }
54
+ const id = typeof parsed["id"] === "string" ? parsed["id"] : null;
55
+ const entry = id !== null ? this.pending.get(id) : undefined;
56
+ if (id === null || entry === undefined)
57
+ continue;
58
+ this.pending.delete(id);
59
+ clearTimeout(entry.timer);
60
+ entry.resolve(parsed);
61
+ }
62
+ }
63
+ failAll(err) {
64
+ this.socket = null;
65
+ this.buffer = "";
66
+ const waiting = [...this.pending.values()];
67
+ this.pending.clear();
68
+ for (const entry of waiting) {
69
+ clearTimeout(entry.timer);
70
+ entry.reject(err);
71
+ }
72
+ }
73
+ /**
74
+ * Send one request; resolves with the raw response object (protocol errors
75
+ * included — the caller inspects `ok`). Rejects only on transport failure or
76
+ * client-side deadline (`timeoutMs` should exceed any deputy-side timeout so
77
+ * the deputy's own honest answer wins).
78
+ */
79
+ async request(payload, timeoutMs) {
80
+ const sock = await this.ensureSocket();
81
+ const id = `a${++this.seq}`;
82
+ // Wake the socket handle while a request is in flight (see unref above).
83
+ sock.ref();
84
+ try {
85
+ return await new Promise((resolve, reject) => {
86
+ const timer = setTimeout(() => {
87
+ this.pending.delete(id);
88
+ reject(new DeputyRequestError("client-timeout", `the deputy did not answer within ${timeoutMs}ms`));
89
+ }, timeoutMs);
90
+ this.pending.set(id, { resolve, reject, timer });
91
+ sock.write(`${JSON.stringify({ ...payload, id })}\n`);
92
+ });
93
+ }
94
+ finally {
95
+ if (this.pending.size === 0)
96
+ sock.unref();
97
+ }
98
+ }
99
+ close() {
100
+ this.socket?.destroy();
101
+ this.socket = null;
102
+ }
103
+ }
104
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/deputy/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * A DatabaseSync-shaped READ facade over the deputy's `sql` verb. The read
3
+ * layer types against node:sqlite's DatabaseSync and only ever prepares
4
+ * SELECT/PRAGMA statements consumed via `.all()` / `.get()`; this facade
5
+ * implements exactly that surface synchronously (through the bridge) and
6
+ * throws a teaching error on anything else — never a silent no-op. WAL
7
+ * freshness is preserved: the deputy holds one read-only connection outside
8
+ * any transaction, so every statement sees a fresh snapshot exactly like a
9
+ * local connection (docs/design/architecture.md §0).
10
+ */
11
+ import type { DatabaseSync } from "node:sqlite";
12
+ /**
13
+ * Build the facade. The cast is confined to this one construction site: the
14
+ * object structurally implements the read subset, a Proxy turns any other
15
+ * member access into a teaching error, and symbol probes (inspect, iterators)
16
+ * stay undefined so logging never explodes.
17
+ */
18
+ export declare function createDeputyDbFacade(env?: NodeJS.ProcessEnv): DatabaseSync;