things-api 0.17.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 (172) 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/writes.js +22 -3
  27. package/dist/cli/commands/writes.js.map +1 -1
  28. package/dist/cli/help.js +4 -0
  29. package/dist/cli/help.js.map +1 -1
  30. package/dist/cli/helpers-check.d.ts +10 -0
  31. package/dist/cli/helpers-check.js +59 -0
  32. package/dist/cli/helpers-check.js.map +1 -0
  33. package/dist/cli/main.js +22 -1
  34. package/dist/cli/main.js.map +1 -1
  35. package/dist/client.js +16 -2
  36. package/dist/client.js.map +1 -1
  37. package/dist/config.d.ts +31 -0
  38. package/dist/config.js +9 -0
  39. package/dist/config.js.map +1 -1
  40. package/dist/contracts.d.ts +1 -1
  41. package/dist/contracts.js +1 -1
  42. package/dist/db/baselines/db-v26.js +8 -4
  43. package/dist/db/baselines/db-v26.js.map +1 -1
  44. package/dist/db/baselines/db-v27.d.ts +42 -0
  45. package/dist/db/baselines/db-v27.js +47 -0
  46. package/dist/db/baselines/db-v27.js.map +1 -0
  47. package/dist/db/baselines/index.js +2 -1
  48. package/dist/db/baselines/index.js.map +1 -1
  49. package/dist/db/locate.d.ts +4 -1
  50. package/dist/db/locate.js +3 -1
  51. package/dist/db/locate.js.map +1 -1
  52. package/dist/db/schema.d.ts +1 -1
  53. package/dist/db/schema.js +9 -0
  54. package/dist/db/schema.js.map +1 -1
  55. package/dist/deputy/bridge-worker.d.ts +1 -0
  56. package/dist/deputy/bridge-worker.js +79 -0
  57. package/dist/deputy/bridge-worker.js.map +1 -0
  58. package/dist/deputy/bridge.d.ts +14 -0
  59. package/dist/deputy/bridge.js +70 -0
  60. package/dist/deputy/bridge.js.map +1 -0
  61. package/dist/deputy/client.d.ts +19 -0
  62. package/dist/deputy/client.js +104 -0
  63. package/dist/deputy/client.js.map +1 -0
  64. package/dist/deputy/db-facade.d.ts +18 -0
  65. package/dist/deputy/db-facade.js +71 -0
  66. package/dist/deputy/db-facade.js.map +1 -0
  67. package/dist/deputy/files.d.ts +1 -0
  68. package/dist/deputy/files.js +16 -0
  69. package/dist/deputy/files.js.map +1 -0
  70. package/dist/deputy/install.d.ts +105 -0
  71. package/dist/deputy/install.js +467 -0
  72. package/dist/deputy/install.js.map +1 -0
  73. package/dist/deputy/notice.d.ts +6 -0
  74. package/dist/deputy/notice.js +28 -0
  75. package/dist/deputy/notice.js.map +1 -0
  76. package/dist/deputy/notices.d.ts +31 -0
  77. package/dist/deputy/notices.js +94 -0
  78. package/dist/deputy/notices.js.map +1 -0
  79. package/dist/deputy/osa.d.ts +21 -0
  80. package/dist/deputy/osa.js +72 -0
  81. package/dist/deputy/osa.js.map +1 -0
  82. package/dist/deputy/protocol.d.ts +86 -0
  83. package/dist/deputy/protocol.js +106 -0
  84. package/dist/deputy/protocol.js.map +1 -0
  85. package/dist/deputy/routing.d.ts +63 -0
  86. package/dist/deputy/routing.js +338 -0
  87. package/dist/deputy/routing.js.map +1 -0
  88. package/dist/deputy/shortcuts-exec.d.ts +10 -0
  89. package/dist/deputy/shortcuts-exec.js +50 -0
  90. package/dist/deputy/shortcuts-exec.js.map +1 -0
  91. package/dist/diagnose.d.ts +43 -1
  92. package/dist/diagnose.js +64 -2
  93. package/dist/diagnose.js.map +1 -1
  94. package/dist/index.d.ts +13 -2
  95. package/dist/index.js +10 -1
  96. package/dist/index.js.map +1 -1
  97. package/dist/mcp/server.js +25 -7
  98. package/dist/mcp/server.js.map +1 -1
  99. package/dist/model/mappers.d.ts +12 -3
  100. package/dist/model/mappers.js +6 -1
  101. package/dist/model/mappers.js.map +1 -1
  102. package/dist/model/recurrence.d.ts +5 -1
  103. package/dist/model/recurrence.js +19 -1
  104. package/dist/model/recurrence.js.map +1 -1
  105. package/dist/model/template-projection.d.ts +26 -0
  106. package/dist/model/template-projection.js +113 -0
  107. package/dist/model/template-projection.js.map +1 -0
  108. package/dist/op-result.d.ts +46 -0
  109. package/dist/op-result.js +156 -0
  110. package/dist/op-result.js.map +1 -0
  111. package/dist/read/detail.js +7 -1
  112. package/dist/read/detail.js.map +1 -1
  113. package/dist/read/queries.js +8 -1
  114. package/dist/read/queries.js.map +1 -1
  115. package/dist/read/views.d.ts +6 -4
  116. package/dist/read/views.js +60 -18
  117. package/dist/read/views.js.map +1 -1
  118. package/dist/sync-health.js +6 -2
  119. package/dist/sync-health.js.map +1 -1
  120. package/dist/write/accessibility-probe.js +4 -2
  121. package/dist/write/accessibility-probe.js.map +1 -1
  122. package/dist/write/automation-probe.js +5 -1
  123. package/dist/write/automation-probe.js.map +1 -1
  124. package/dist/write/availability.js +7 -3
  125. package/dist/write/availability.js.map +1 -1
  126. package/dist/write/commands.js +58 -13
  127. package/dist/write/commands.js.map +1 -1
  128. package/dist/write/experimental.d.ts +19 -0
  129. package/dist/write/experimental.js +50 -0
  130. package/dist/write/experimental.js.map +1 -1
  131. package/dist/write/move.js +14 -6
  132. package/dist/write/move.js.map +1 -1
  133. package/dist/write/operations.d.ts +28 -4
  134. package/dist/write/pipeline.d.ts +2 -0
  135. package/dist/write/pipeline.js +59 -2
  136. package/dist/write/pipeline.js.map +1 -1
  137. package/dist/write/pre-state.js +33 -15
  138. package/dist/write/pre-state.js.map +1 -1
  139. package/dist/write/promote-clone.js +187 -19
  140. package/dist/write/promote-clone.js.map +1 -1
  141. package/dist/write/reorder.js +76 -27
  142. package/dist/write/reorder.js.map +1 -1
  143. package/dist/write/repeat-anchor.d.ts +30 -0
  144. package/dist/write/repeat-anchor.js +166 -1
  145. package/dist/write/repeat-anchor.js.map +1 -1
  146. package/dist/write/repeat-rule.js +10 -0
  147. package/dist/write/repeat-rule.js.map +1 -1
  148. package/dist/write/vectors/applescript.js +7 -16
  149. package/dist/write/vectors/applescript.js.map +1 -1
  150. package/dist/write/vectors/session-reachability.d.ts +55 -0
  151. package/dist/write/vectors/session-reachability.js +56 -8
  152. package/dist/write/vectors/session-reachability.js.map +1 -1
  153. package/dist/write/vectors/shortcuts.js +5 -14
  154. package/dist/write/vectors/shortcuts.js.map +1 -1
  155. package/dist/write/vectors/simulator.d.ts +16 -1
  156. package/dist/write/vectors/simulator.js +61 -10
  157. package/dist/write/vectors/simulator.js.map +1 -1
  158. package/dist/write/vectors/types.d.ts +67 -1
  159. package/dist/write/vectors/ui-recipes.js +128 -38
  160. package/dist/write/vectors/ui-recipes.js.map +1 -1
  161. package/dist/write/vectors/ui.d.ts +76 -0
  162. package/dist/write/vectors/ui.js +443 -37
  163. package/dist/write/vectors/ui.js.map +1 -1
  164. package/dist/write/verify/poller.d.ts +13 -0
  165. package/dist/write/verify/poller.js +38 -0
  166. package/dist/write/verify/poller.js.map +1 -1
  167. package/package.json +8 -1
  168. package/scripts/build-helpers.sh +104 -0
  169. package/scripts/deputy-cert-setup.sh +60 -0
  170. package/skills/things-cli/SKILL.md +8 -3
  171. package/skills/things-cli/references/errors.md +4 -0
  172. package/skills/things-cli/references/repeating.md +69 -0
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `things helpers` — lifecycle for the optional helper pair (one installed
3
+ * bundle housing both):
4
+ *
5
+ * things-deputy — app automation (mutations), unsandboxed.
6
+ * things-reader — database/file reads, sandboxed to a user-granted folder.
7
+ *
8
+ * Running them means macOS permission prompts and grants attach to two stable
9
+ * identities instead of every terminal or agent runtime that invokes
10
+ * `things`, so grants stop re-prompting when those runtimes update. Routing is
11
+ * tri-state (`helpers-enabled`: auto | true | false, default auto —
12
+ * installation is the intent signal), overridable per invocation with
13
+ * THINGS_API_HELPERS or the global `--helpers`/`--no-helpers` flags; the CLI
14
+ * always falls back to direct execution when a helper is unavailable.
15
+ */
16
+ import type { Command } from "commander";
17
+ export declare function registerHelpers(program: Command): void;
@@ -0,0 +1,148 @@
1
+ import { helpersStatus, ExitCode, grantReader, installHelpers, loadConfig, okEnvelope, restartHelpers, uninstallHelpers, } from "../../index.js";
2
+ function envelopeMeta(started) {
3
+ return { dbVersion: null, fingerprint: "unknown", elapsedMs: Date.now() - started };
4
+ }
5
+ /** One line describing what the configured mode means for this machine. */
6
+ function routingLine(status) {
7
+ switch (status.mode) {
8
+ case "true":
9
+ return "enabled — every process routes through the helpers, and reports when it cannot";
10
+ case "false":
11
+ return "disabled (things config set helpers-enabled auto)";
12
+ case "auto":
13
+ return status.bundleInstalled
14
+ ? "auto — the installed helpers are used while healthy; a failure is reported, never silent"
15
+ : "auto — nothing installed, so everything runs direct (things helpers install to change that)";
16
+ }
17
+ }
18
+ function renderStatus(status) {
19
+ const deputy = status.deputy;
20
+ const lines = [`deputy: ${deputy.running ? "running" : "does not appear to be running"}`];
21
+ // The plain no-socket case needs no elaboration; a socket that exists but
22
+ // misbehaves (not answering, handshake refused) is worth its own line.
23
+ if (!deputy.running && !deputy.detail.startsWith("not running")) {
24
+ lines.push(` detail: ${deputy.detail}`);
25
+ }
26
+ if (deputy.hungSocket) {
27
+ lines.push(" next: `things helpers restart` — the socket is present but no handshake answers");
28
+ }
29
+ lines.push(` routing: ${routingLine(status)}`, ` launchd: ${deputy.plistInstalled ? (deputy.loaded ? "installed + loaded" : "installed, NOT loaded") : "not installed (things helpers install)"}`, ` bundle: ${status.bundleInstalled
30
+ ? `installed${status.installedVersion !== null ? ` (v${status.installedVersion})` : ""}`
31
+ : "not installed"}`, ` socket: ${deputy.socketPath}`);
32
+ if (deputy.hello !== null) {
33
+ lines.push(` version: ${deputy.hello.deputyVersion} (protocol ${deputy.hello.protocol}, pid ${deputy.hello.pid})`);
34
+ }
35
+ if (deputy.signing !== null) {
36
+ lines.push(` signing: ${deputy.signing.state}${deputy.signing.authority !== null ? ` (${deputy.signing.authority})` : ""}`);
37
+ if (deputy.signing.state !== "signed") {
38
+ lines.push(" warning: an unsigned/ad-hoc helper loses its macOS grants on every rebuild — run scripts/deputy-cert-setup.sh once, rebuild, reinstall");
39
+ }
40
+ }
41
+ const reader = status.reader;
42
+ lines.push(`reader: ${reader.running ? (reader.granted ? "running, granted" : "running, NOT granted") : reader.installed ? reader.detail : "not installed"}`);
43
+ if (reader.running && !reader.granted) {
44
+ lines.push(" next: run `things helpers grant` and accept the panel (one time; the grant survives restarts, reboots, and rebuilds)");
45
+ }
46
+ if (reader.hungSocket) {
47
+ lines.push(" next: `things helpers restart` — the socket is present but no handshake answers");
48
+ }
49
+ return `${lines.join("\n")}\n`;
50
+ }
51
+ export function registerHelpers(program) {
52
+ const helpers = program
53
+ .command("helpers")
54
+ .description("Manage the optional helper pair that performs database reads and app automation " +
55
+ "on the CLI's behalf, so macOS permission grants attach to stable helpers instead " +
56
+ "of every terminal or agent runtime that runs `things`. Subcommands: status, " +
57
+ "install, grant, restart, uninstall.");
58
+ helpers
59
+ .command("status")
60
+ .description("Report both helpers' state: running or not, launchd installation, installed version, " +
61
+ "code-signing identity, the reader's grant, and the routing mode on this machine. " +
62
+ "Read-only.")
63
+ .option("--json", "emit versioned JSON envelope on stdout")
64
+ .action((opts) => {
65
+ const started = Date.now();
66
+ const status = helpersStatus(loadConfig().helpersMode);
67
+ if (opts.json === true) {
68
+ process.stdout.write(`${JSON.stringify(okEnvelope("helpers-status", status, envelopeMeta(started)))}\n`);
69
+ }
70
+ else {
71
+ process.stdout.write(renderStatus(status));
72
+ }
73
+ process.exitCode = ExitCode.Ok;
74
+ });
75
+ helpers
76
+ .command("install")
77
+ .description("Install the helper bundle: copy it to its stable location, register both helpers " +
78
+ "with launchd (starts now and on every login), and report signing + grant state. " +
79
+ "Under the default helpers-enabled auto, an installed and healthy helper is used from " +
80
+ "the next command on. Rerun after every rebuild.")
81
+ .option("--bundle <path>", "path to a built Things API Helper.app (default: deputy/build/Things API Helper.app in this package)")
82
+ .action((opts) => {
83
+ try {
84
+ const result = installHelpers(opts.bundle !== undefined ? { bundlePath: opts.bundle } : {});
85
+ process.stdout.write(`installed ${result.bundlePath}\nlaunchd agent: ${result.plistPath}\n`);
86
+ if (result.readerInstalled) {
87
+ process.stdout.write(result.readerGranted === true
88
+ ? "reader: granted — file reads ride the scoped reader\n"
89
+ : result.readerGranted === false
90
+ ? "reader: installed — run `things helpers grant` once to give it durable read access\n"
91
+ : "reader: installed, not answering yet — check `things helpers status`\n");
92
+ }
93
+ for (const warning of result.warnings) {
94
+ process.stderr.write(`warning: ${warning}\n`);
95
+ }
96
+ process.exitCode = ExitCode.Ok;
97
+ }
98
+ catch (err) {
99
+ process.stderr.write(`error: ${err instanceof Error ? err.message : String(err)}\n`);
100
+ process.exitCode = ExitCode.Environment;
101
+ }
102
+ });
103
+ helpers
104
+ .command("grant")
105
+ .description("One-time ceremony: opens a folder panel presented by the sandboxed reader helper, " +
106
+ "already showing the Things data folder. Accepting gives the reader durable read " +
107
+ "access to exactly that folder — it survives restarts, reboots, and updates, and " +
108
+ "macOS enforces that the reader can reach nothing else. Interactive: run this at " +
109
+ "the machine, not from an unattended session.")
110
+ .action(() => {
111
+ const result = grantReader();
112
+ if (result.granted) {
113
+ process.stdout.write("granted — file reads now ride the scoped reader\n");
114
+ process.exitCode = ExitCode.Ok;
115
+ }
116
+ else {
117
+ process.stderr.write(`not granted: ${result.detail}\n`);
118
+ process.exitCode = ExitCode.Environment;
119
+ }
120
+ });
121
+ helpers
122
+ .command("restart")
123
+ .description("Restart the launchd-managed helpers (picks up a rebuilt installed bundle).")
124
+ .action(() => {
125
+ try {
126
+ restartHelpers();
127
+ process.stdout.write("helpers restarted\n");
128
+ process.exitCode = ExitCode.Ok;
129
+ }
130
+ catch (err) {
131
+ process.stderr.write(`error: ${err instanceof Error ? err.message : String(err)}\n`);
132
+ process.exitCode = ExitCode.Environment;
133
+ }
134
+ });
135
+ helpers
136
+ .command("uninstall")
137
+ .description("Stop both helpers and remove their launchd registrations and the installed bundle. " +
138
+ "Local state (access token, logs, the reader's grant) is kept; routing config is " +
139
+ "untouched (commands fall back to direct execution).")
140
+ .action(() => {
141
+ const result = uninstallHelpers();
142
+ process.stdout.write(result.removed.length > 0
143
+ ? `removed:\n${result.removed.map((p) => ` ${p}`).join("\n")}\n`
144
+ : "nothing installed\n");
145
+ process.exitCode = ExitCode.Ok;
146
+ });
147
+ }
148
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/cli/commands/helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `things op-result <op-id>` — a read-only CALLER-RECOVERY lookup over the local
3
+ * change history (RSPA1 deliverable 3). Thin surface over the library's opResult().
4
+ *
5
+ * When your environment kills long commands (a wall-time cap) before a write's
6
+ * result is printed — a `--dangerously-drive-gui` drive can run its full verify
7
+ * budget — dispatch the op with `--op-id <key>`, let it die, then run this in a
8
+ * fresh process to learn what ACTUALLY happened from the record the killed process
9
+ * already durably wrote. NEVER blind-retry a GUI drive.
10
+ *
11
+ * Always exit 0: this is a successful HISTORY READ regardless of the underlying
12
+ * op's outcome (which lives in `data.status` / `data.result`).
13
+ */
14
+ import type { Command } from "commander";
15
+ export declare function registerOpResult(program: Command): void;
@@ -0,0 +1,39 @@
1
+ import { okEnvelope, opResult } from "../../index.js";
2
+ export function registerOpResult(program) {
3
+ program
4
+ .command("op-result")
5
+ .argument("<op-id>", "the --op-id / op_id the original write carried")
6
+ .description("Look up what happened to a write you dispatched with --op-id, from the local change " +
7
+ "history alone (opens no database, drives nothing). Use it to recover the outcome when " +
8
+ "your environment killed the command before it printed its result: let the command die, " +
9
+ "then run this. Reports FOUND (the final result + target + observation), INTENT-ONLY (the " +
10
+ "op started but no outcome was written — still running or the process died mid-flight, " +
11
+ "outcome UNCERTAIN), or UNKNOWN (no such op-id in history). Always exit 0 (a history read).")
12
+ .option("--json", "emit versioned JSON envelope on stdout")
13
+ .action((opId, opts) => {
14
+ const started = Date.now();
15
+ const data = opResult(opId);
16
+ const meta = {
17
+ dbVersion: null,
18
+ fingerprint: "unknown",
19
+ elapsedMs: Date.now() - started,
20
+ };
21
+ if (opts.json) {
22
+ process.stdout.write(`${JSON.stringify(okEnvelope("op-result", data, meta))}\n`);
23
+ }
24
+ else {
25
+ const head = data.status === "found"
26
+ ? `${data.result} — ${data.op}${data.uuid !== null ? ` (${data.uuid})` : ""}`
27
+ : data.status === "intent-only"
28
+ ? `intent-only — ${data.op} (no final outcome recorded)`
29
+ : "unknown op-id";
30
+ process.stdout.write(`op-result ${opId}: ${head}\n`);
31
+ process.stdout.write(` ${data.note}\n`);
32
+ if (data.status === "found" && data.observed !== null) {
33
+ process.stdout.write(` observed: ${JSON.stringify(data.observed)}\n`);
34
+ }
35
+ }
36
+ process.exitCode = 0;
37
+ });
38
+ }
39
+ //# sourceMappingURL=op-result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"op-result.js","sourceRoot":"","sources":["../../../src/cli/commands/op-result.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAqB,MAAM,gBAAgB,CAAC;AAEzE,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,OAAO;SACJ,OAAO,CAAC,WAAW,CAAC;SACpB,QAAQ,CAAC,SAAS,EAAE,gDAAgD,CAAC;SACrE,WAAW,CACV,sFAAsF;QACpF,wFAAwF;QACxF,yFAAyF;QACzF,2FAA2F;QAC3F,wFAAwF;QACxF,4FAA4F,CAC/F;SACA,MAAM,CAAC,QAAQ,EAAE,wCAAwC,CAAC;SAC1D,MAAM,CAAC,CAAC,IAAY,EAAE,IAAwB,EAAE,EAAE;QACjD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5B,MAAM,IAAI,GAAiB;YACzB,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,SAAS;YACtB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO;SAChC,CAAC;QACF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;QACnF,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GACR,IAAI,CAAC,MAAM,KAAK,OAAO;gBACrB,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,MAAM,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC7E,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,aAAa;oBAC7B,CAAC,CAAC,iBAAiB,IAAI,CAAC,EAAE,8BAA8B;oBACxD,CAAC,CAAC,eAAe,CAAC;YACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC;YACrD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;YACzC,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;gBACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;QACD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -3,7 +3,7 @@ import { armInterrupt, disarmInterrupt } from "../interrupt.js";
3
3
  import { isDevVersion } from "../skill.js";
4
4
  import { CLI_VERSION } from "../version.js";
5
5
  import { addRepeatCalendarFlags, addRepeatingRuleFieldsFromOpts, addRepeatRuleFlags, repeatRuleFlagsFromOpts, } from "./repeat-flags.js";
6
- import { aggregateExitCode, blockedCode, capabilitiesTable, ClockError, closeCliTrace, describeConfig, errorEnvelope, ExitCode, installCliTrace, getConfigKey, mutationWireData, okEnvelope, openThings, OP_ID_RE, outcomeFailed, ReferenceResolutionError, saveConfigKey, splitWhenSugar, trace, ThingsDbNotFoundError, ThingsDbOpenError, verifyFailedCode, } from "../../index.js";
6
+ import { aggregateExitCode, blockedCode, capabilitiesTable, ClockError, closeCliTrace, describeConfig, errorEnvelope, ExitCode, HELPERS_MODES, installCliTrace, getConfigKey, parseHelpersMode, mutationWireData, okEnvelope, openThings, OP_ID_RE, outcomeFailed, ReferenceResolutionError, saveConfigKey, splitWhenSugar, trace, ThingsDbNotFoundError, ThingsDbOpenError, verifyFailedCode, } from "../../index.js";
7
7
  import { usageError } from "../read-driver.js";
8
8
  import { dim } from "../style.js";
9
9
  function addWriteFlags(cmd) {
@@ -354,6 +354,7 @@ function emitResult(result, opts, meta) {
354
354
  ` invocation: ${result.plan.invocation}`,
355
355
  ` hazards checked: ${result.plan.hazardsChecked.join(", ") || "none"}`,
356
356
  ` expected delta: ${JSON.stringify(result.plan.expectedDelta)}`,
357
+ ...(result.plan.notes ?? []).map((n) => ` note: ${n}`),
357
358
  "",
358
359
  ].join("\n"));
359
360
  }
@@ -1423,7 +1424,12 @@ export function registerWriteCommands(program) {
1423
1424
  .option("--notes <text>", "notes body")
1424
1425
  .option("--when <value>", "today | evening | anytime | someday | YYYY-MM-DD")
1425
1426
  .option("--reminder <time>", "HH:mm reminder (needs a schedulable --when)")
1426
- .option("--deadline <date>", "YYYY-MM-DD")
1427
+ .option("--deadline <date>", "YYYY-MM-DD — deadlines EVERY occurrence: each starts (deadline − --when) days " +
1428
+ "before its own deadline (needs a concrete --when, on or before the deadline; " +
1429
+ "alternative spelling of --start-days-earlier — give one or the other, both must agree)")
1430
+ .option("--start-days-earlier <n>", "deadlines EVERY occurrence, naming the lead directly: each starts N days before " +
1431
+ "its own deadline (needs a concrete --when; alternative spelling of --deadline <date> — " +
1432
+ "give one or the other, both must agree)")
1427
1433
  .option("--tag <name>", "tag to attach (repeatable)", collect, [])
1428
1434
  .option("--checklist-item <title>", "checklist item (repeatable)", collect, [])
1429
1435
  .option("--project <ref>", "destination project (uuid or unique name)")
@@ -1445,6 +1451,9 @@ export function registerWriteCommands(program) {
1445
1451
  ...(opts["when"] !== undefined && { when: opts["when"] }),
1446
1452
  ...(opts["reminder"] !== undefined && { reminder: opts["reminder"] }),
1447
1453
  ...(opts["deadline"] !== undefined && { deadline: opts["deadline"] }),
1454
+ ...(opts["startDaysEarlier"] !== undefined && {
1455
+ startDaysEarlier: Number(opts["startDaysEarlier"]),
1456
+ }),
1448
1457
  ...(tags.length > 0 && { tags }),
1449
1458
  ...(checklistItems.length > 0 && { checklistItems }),
1450
1459
  ...(projectRef !== undefined && { project: projectRef }),
@@ -2155,7 +2164,8 @@ export function registerWriteCommands(program) {
2155
2164
  .command("set <key> <value>")
2156
2165
  .description("Persist a config key: profile | maxDisruption | actor | auditEnabled | " +
2157
2166
  "accepted-fingerprint | certified-app-version | allow-experimental | bounce-enabled | " +
2158
- "bounce-max-items | auto-launch | ui-enabled | ui-drive-budget-ms | trace | scope")
2167
+ "bounce-max-items | auto-launch | helpers-enabled (auto | true | false) | ui-enabled | " +
2168
+ "ui-drive-budget-ms | trace | scope")
2159
2169
  .action((key, value, opts) => {
2160
2170
  const map = {
2161
2171
  profile: "profile",
@@ -2168,6 +2178,7 @@ export function registerWriteCommands(program) {
2168
2178
  "bounce-enabled": "bounceEnabled",
2169
2179
  "bounce-max-items": "bounceMaxItems",
2170
2180
  "auto-launch": "autoLaunch",
2181
+ "helpers-enabled": "helpersMode",
2171
2182
  "ui-enabled": "uiEnabled",
2172
2183
  "ui-drive-budget-ms": "uiDriveBudgetMs",
2173
2184
  trace: "traceEnabled",
@@ -2179,6 +2190,14 @@ export function registerWriteCommands(program) {
2179
2190
  process.exitCode = ExitCode.Usage;
2180
2191
  return;
2181
2192
  }
2193
+ // `helpers-enabled` is TRI-state (auto | true | false): anything else is
2194
+ // refused rather than silently coerced to a boolean, so a typo can never
2195
+ // read as "off" on a machine that meant "auto".
2196
+ if (target === "helpersMode" && parseHelpersMode(value) === undefined) {
2197
+ process.stderr.write(`error: helpers-enabled accepts ${HELPERS_MODES.join(" | ")} (got "${value}")\n`);
2198
+ process.exitCode = ExitCode.Usage;
2199
+ return;
2200
+ }
2182
2201
  const parsed = target === "maxDisruption" || target === "bounceMaxItems" || target === "uiDriveBudgetMs"
2183
2202
  ? Number(value)
2184
2203
  : target === "auditEnabled" ||