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.
- package/README.md +1 -1
- package/deputy/VERSION +1 -0
- package/deputy/helpers-Info.plist +23 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/CodeResources +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/Info.plist +20 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/MacOS/things-reader +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/_CodeSignature/CodeResources +115 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Info.plist +23 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/MacOS/things-deputy +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/_CodeSignature/CodeResources +125 -0
- package/deputy/reader/Info.plist +20 -0
- package/deputy/reader/entitlements.plist +15 -0
- package/deputy/reader/main.swift +491 -0
- package/deputy/src/main.swift +133 -0
- package/deputy/src/osascript.swift +102 -0
- package/deputy/src/server.swift +350 -0
- package/deputy/src/sqlite.swift +121 -0
- package/dist/cli/commands/doctor.js +55 -2
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/helpers.d.ts +17 -0
- package/dist/cli/commands/helpers.js +148 -0
- package/dist/cli/commands/helpers.js.map +1 -0
- package/dist/cli/commands/op-result.d.ts +15 -0
- package/dist/cli/commands/op-result.js +39 -0
- package/dist/cli/commands/op-result.js.map +1 -0
- package/dist/cli/commands/repeat-flags.d.ts +3 -3
- package/dist/cli/commands/repeat-flags.js +90 -33
- package/dist/cli/commands/repeat-flags.js.map +1 -1
- package/dist/cli/commands/writes.js +79 -6
- package/dist/cli/commands/writes.js.map +1 -1
- package/dist/cli/help.js +13 -2
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/helpers-check.d.ts +10 -0
- package/dist/cli/helpers-check.js +59 -0
- package/dist/cli/helpers-check.js.map +1 -0
- package/dist/cli/interrupt.d.ts +42 -0
- package/dist/cli/interrupt.js +105 -0
- package/dist/cli/interrupt.js.map +1 -0
- package/dist/cli/main.js +27 -1
- package/dist/cli/main.js.map +1 -1
- package/dist/client.js +19 -2
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +70 -0
- package/dist/config.js +25 -1
- package/dist/config.js.map +1 -1
- package/dist/contracts.d.ts +9 -2
- package/dist/contracts.js +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/db/baselines/db-v26.js +8 -4
- package/dist/db/baselines/db-v26.js.map +1 -1
- package/dist/db/baselines/db-v27.d.ts +42 -0
- package/dist/db/baselines/db-v27.js +47 -0
- package/dist/db/baselines/db-v27.js.map +1 -0
- package/dist/db/baselines/index.js +2 -1
- package/dist/db/baselines/index.js.map +1 -1
- package/dist/db/locate.d.ts +4 -1
- package/dist/db/locate.js +3 -1
- package/dist/db/locate.js.map +1 -1
- package/dist/db/schema.d.ts +1 -1
- package/dist/db/schema.js +9 -0
- package/dist/db/schema.js.map +1 -1
- package/dist/deputy/bridge-worker.d.ts +1 -0
- package/dist/deputy/bridge-worker.js +79 -0
- package/dist/deputy/bridge-worker.js.map +1 -0
- package/dist/deputy/bridge.d.ts +14 -0
- package/dist/deputy/bridge.js +70 -0
- package/dist/deputy/bridge.js.map +1 -0
- package/dist/deputy/client.d.ts +19 -0
- package/dist/deputy/client.js +104 -0
- package/dist/deputy/client.js.map +1 -0
- package/dist/deputy/db-facade.d.ts +18 -0
- package/dist/deputy/db-facade.js +71 -0
- package/dist/deputy/db-facade.js.map +1 -0
- package/dist/deputy/files.d.ts +1 -0
- package/dist/deputy/files.js +16 -0
- package/dist/deputy/files.js.map +1 -0
- package/dist/deputy/install.d.ts +105 -0
- package/dist/deputy/install.js +467 -0
- package/dist/deputy/install.js.map +1 -0
- package/dist/deputy/notice.d.ts +6 -0
- package/dist/deputy/notice.js +28 -0
- package/dist/deputy/notice.js.map +1 -0
- package/dist/deputy/notices.d.ts +31 -0
- package/dist/deputy/notices.js +94 -0
- package/dist/deputy/notices.js.map +1 -0
- package/dist/deputy/osa.d.ts +21 -0
- package/dist/deputy/osa.js +72 -0
- package/dist/deputy/osa.js.map +1 -0
- package/dist/deputy/protocol.d.ts +86 -0
- package/dist/deputy/protocol.js +106 -0
- package/dist/deputy/protocol.js.map +1 -0
- package/dist/deputy/routing.d.ts +63 -0
- package/dist/deputy/routing.js +338 -0
- package/dist/deputy/routing.js.map +1 -0
- package/dist/deputy/shortcuts-exec.d.ts +10 -0
- package/dist/deputy/shortcuts-exec.js +50 -0
- package/dist/deputy/shortcuts-exec.js.map +1 -0
- package/dist/diagnose.d.ts +43 -1
- package/dist/diagnose.js +64 -2
- package/dist/diagnose.js.map +1 -1
- package/dist/index.d.ts +16 -2
- package/dist/index.js +17 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +25 -7
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/mappers.d.ts +12 -3
- package/dist/model/mappers.js +6 -1
- package/dist/model/mappers.js.map +1 -1
- package/dist/model/occurrences.d.ts +14 -1
- package/dist/model/occurrences.js +20 -4
- package/dist/model/occurrences.js.map +1 -1
- package/dist/model/recurrence.d.ts +64 -9
- package/dist/model/recurrence.js +94 -19
- package/dist/model/recurrence.js.map +1 -1
- package/dist/model/template-projection.d.ts +26 -0
- package/dist/model/template-projection.js +113 -0
- package/dist/model/template-projection.js.map +1 -0
- package/dist/op-result.d.ts +46 -0
- package/dist/op-result.js +156 -0
- package/dist/op-result.js.map +1 -0
- package/dist/paths.d.ts +8 -0
- package/dist/paths.js +10 -0
- package/dist/paths.js.map +1 -1
- package/dist/read/detail.js +7 -1
- package/dist/read/detail.js.map +1 -1
- package/dist/read/queries.js +8 -1
- package/dist/read/queries.js.map +1 -1
- package/dist/read/views.d.ts +6 -4
- package/dist/read/views.js +60 -18
- package/dist/read/views.js.map +1 -1
- package/dist/sync-health.js +8 -3
- package/dist/sync-health.js.map +1 -1
- package/dist/trace/tracer.d.ts +87 -0
- package/dist/trace/tracer.js +167 -0
- package/dist/trace/tracer.js.map +1 -0
- package/dist/write/accessibility-probe.js +4 -2
- package/dist/write/accessibility-probe.js.map +1 -1
- package/dist/write/automation-probe.js +5 -1
- package/dist/write/automation-probe.js.map +1 -1
- package/dist/write/availability.js +7 -3
- package/dist/write/availability.js.map +1 -1
- package/dist/write/clear-reminder.js +24 -21
- package/dist/write/clear-reminder.js.map +1 -1
- package/dist/write/commands.js +95 -45
- package/dist/write/commands.js.map +1 -1
- package/dist/write/completion-context.d.ts +57 -0
- package/dist/write/completion-context.js +49 -0
- package/dist/write/completion-context.js.map +1 -0
- package/dist/write/experimental.d.ts +19 -0
- package/dist/write/experimental.js +50 -0
- package/dist/write/experimental.js.map +1 -1
- package/dist/write/failure-hints.d.ts +10 -1
- package/dist/write/failure-hints.js +8 -0
- package/dist/write/failure-hints.js.map +1 -1
- package/dist/write/guards.d.ts +1 -1
- package/dist/write/guards.js +10 -0
- package/dist/write/guards.js.map +1 -1
- package/dist/write/move.js +14 -6
- package/dist/write/move.js.map +1 -1
- package/dist/write/operations.d.ts +40 -7
- package/dist/write/pipeline.d.ts +41 -0
- package/dist/write/pipeline.js +289 -19
- package/dist/write/pipeline.js.map +1 -1
- package/dist/write/pre-state.d.ts +1 -1
- package/dist/write/pre-state.js +35 -17
- package/dist/write/pre-state.js.map +1 -1
- package/dist/write/promote-clone.js +434 -19
- package/dist/write/promote-clone.js.map +1 -1
- package/dist/write/reorder.js +76 -27
- package/dist/write/reorder.js.map +1 -1
- package/dist/write/repeat-anchor.d.ts +140 -0
- package/dist/write/repeat-anchor.js +403 -0
- package/dist/write/repeat-anchor.js.map +1 -0
- package/dist/write/repeat-asserts.d.ts +28 -0
- package/dist/write/repeat-asserts.js +169 -0
- package/dist/write/repeat-asserts.js.map +1 -0
- package/dist/write/repeat-rule.js +37 -12
- package/dist/write/repeat-rule.js.map +1 -1
- package/dist/write/vectors/applescript.js +7 -16
- package/dist/write/vectors/applescript.js.map +1 -1
- package/dist/write/vectors/session-reachability.d.ts +133 -0
- package/dist/write/vectors/session-reachability.js +151 -0
- package/dist/write/vectors/session-reachability.js.map +1 -0
- package/dist/write/vectors/shortcuts.js +5 -14
- package/dist/write/vectors/shortcuts.js.map +1 -1
- package/dist/write/vectors/simulator.d.ts +16 -1
- package/dist/write/vectors/simulator.js +122 -32
- package/dist/write/vectors/simulator.js.map +1 -1
- package/dist/write/vectors/types.d.ts +183 -10
- package/dist/write/vectors/ui-recipes.d.ts +8 -0
- package/dist/write/vectors/ui-recipes.js +246 -58
- package/dist/write/vectors/ui-recipes.js.map +1 -1
- package/dist/write/vectors/ui.d.ts +156 -14
- package/dist/write/vectors/ui.js +846 -84
- package/dist/write/vectors/ui.js.map +1 -1
- package/dist/write/verify/delta.d.ts +12 -14
- package/dist/write/verify/delta.js +35 -34
- package/dist/write/verify/delta.js.map +1 -1
- package/dist/write/verify/poller.d.ts +13 -0
- package/dist/write/verify/poller.js +38 -0
- package/dist/write/verify/poller.js.map +1 -1
- package/package.json +8 -1
- package/schema/envelope.schema.json +22 -0
- package/scripts/build-helpers.sh +104 -0
- package/scripts/deputy-cert-setup.sh +60 -0
- package/skills/things-cli/SKILL.md +11 -3
- package/skills/things-cli/references/errors.md +4 -0
- package/skills/things-cli/references/repeating.md +69 -0
package/dist/contracts.d.ts
CHANGED
|
@@ -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.
|
|
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
|
+
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 —
|
package/dist/contracts.js.map
CHANGED
|
@@ -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;
|
|
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-
|
|
10
|
-
//
|
|
11
|
-
//
|
|
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:
|
|
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,
|
|
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 +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"}
|
package/dist/db/locate.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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}). ` +
|
package/dist/db/locate.js.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/db/schema.d.ts
CHANGED
|
@@ -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"],
|
package/dist/db/schema.js.map
CHANGED
|
@@ -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;
|