things-api 0.17.0 → 0.19.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 (277) hide show
  1. package/README.md +16 -9
  2. package/deputy/AppIcon.icns +0 -0
  3. package/deputy/VERSION +1 -0
  4. package/deputy/helpers-Info.plist +27 -0
  5. package/deputy/prebuilt/Things API Helper.app/Contents/CodeResources +0 -0
  6. package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/Info.plist +22 -0
  7. package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/MacOS/things-reader +0 -0
  8. package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/Resources/AppIcon.icns +0 -0
  9. package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/_CodeSignature/CodeResources +128 -0
  10. package/deputy/prebuilt/Things API Helper.app/Contents/Info.plist +27 -0
  11. package/deputy/prebuilt/Things API Helper.app/Contents/MacOS/things-deputy +0 -0
  12. package/deputy/prebuilt/Things API Helper.app/Contents/Resources/AppIcon.icns +0 -0
  13. package/deputy/prebuilt/Things API Helper.app/Contents/_CodeSignature/CodeResources +137 -0
  14. package/deputy/reader/Info.plist +22 -0
  15. package/deputy/reader/entitlements.plist +45 -0
  16. package/deputy/reader/main.swift +580 -0
  17. package/deputy/src/main.swift +133 -0
  18. package/deputy/src/osascript.swift +102 -0
  19. package/deputy/src/server.swift +373 -0
  20. package/deputy/src/sqlite.swift +121 -0
  21. package/deputy/src/tcc.swift +58 -0
  22. package/dist/audit/schema.d.ts +13 -1
  23. package/dist/audit/schema.js.map +1 -1
  24. package/dist/capability.d.ts +160 -0
  25. package/dist/capability.js +416 -0
  26. package/dist/capability.js.map +1 -0
  27. package/dist/cli/commands/doctor.js +181 -2
  28. package/dist/cli/commands/doctor.js.map +1 -1
  29. package/dist/cli/commands/helpers.d.ts +17 -0
  30. package/dist/cli/commands/helpers.js +275 -0
  31. package/dist/cli/commands/helpers.js.map +1 -0
  32. package/dist/cli/commands/op-result.d.ts +15 -0
  33. package/dist/cli/commands/op-result.js +45 -0
  34. package/dist/cli/commands/op-result.js.map +1 -0
  35. package/dist/cli/commands/reads.js +47 -1
  36. package/dist/cli/commands/reads.js.map +1 -1
  37. package/dist/cli/commands/setup.d.ts +9 -0
  38. package/dist/cli/commands/setup.js +63 -83
  39. package/dist/cli/commands/setup.js.map +1 -1
  40. package/dist/cli/commands/writes.d.ts +1 -1
  41. package/dist/cli/commands/writes.js +262 -109
  42. package/dist/cli/commands/writes.js.map +1 -1
  43. package/dist/cli/dry-run.d.ts +1 -1
  44. package/dist/cli/dry-run.js +1 -1
  45. package/dist/cli/glyphs.d.ts +23 -4
  46. package/dist/cli/glyphs.js +46 -19
  47. package/dist/cli/glyphs.js.map +1 -1
  48. package/dist/cli/help.d.ts +1 -1
  49. package/dist/cli/help.js +53 -27
  50. package/dist/cli/help.js.map +1 -1
  51. package/dist/cli/helpers-check.d.ts +10 -0
  52. package/dist/cli/helpers-check.js +59 -0
  53. package/dist/cli/helpers-check.js.map +1 -0
  54. package/dist/cli/main.js +22 -1
  55. package/dist/cli/main.js.map +1 -1
  56. package/dist/cli/period.d.ts +3 -1
  57. package/dist/cli/period.js +1 -1
  58. package/dist/cli/period.js.map +1 -1
  59. package/dist/cli/read-driver.js +26 -1
  60. package/dist/cli/read-driver.js.map +1 -1
  61. package/dist/cli/render.d.ts +31 -4
  62. package/dist/cli/render.js +127 -15
  63. package/dist/cli/render.js.map +1 -1
  64. package/dist/client.d.ts +22 -2
  65. package/dist/client.js +52 -15
  66. package/dist/client.js.map +1 -1
  67. package/dist/config.d.ts +31 -0
  68. package/dist/config.js +9 -0
  69. package/dist/config.js.map +1 -1
  70. package/dist/contracts.d.ts +6 -2
  71. package/dist/contracts.js +1 -1
  72. package/dist/contracts.js.map +1 -1
  73. package/dist/db/baselines/db-v26.js +8 -4
  74. package/dist/db/baselines/db-v26.js.map +1 -1
  75. package/dist/db/baselines/db-v27.d.ts +42 -0
  76. package/dist/db/baselines/db-v27.js +47 -0
  77. package/dist/db/baselines/db-v27.js.map +1 -0
  78. package/dist/db/baselines/index.js +2 -1
  79. package/dist/db/baselines/index.js.map +1 -1
  80. package/dist/db/locate.d.ts +4 -1
  81. package/dist/db/locate.js +3 -1
  82. package/dist/db/locate.js.map +1 -1
  83. package/dist/db/schema.d.ts +1 -1
  84. package/dist/db/schema.js +9 -0
  85. package/dist/db/schema.js.map +1 -1
  86. package/dist/deputy/bridge-worker.d.ts +1 -0
  87. package/dist/deputy/bridge-worker.js +79 -0
  88. package/dist/deputy/bridge-worker.js.map +1 -0
  89. package/dist/deputy/bridge.d.ts +14 -0
  90. package/dist/deputy/bridge.js +70 -0
  91. package/dist/deputy/bridge.js.map +1 -0
  92. package/dist/deputy/client.d.ts +19 -0
  93. package/dist/deputy/client.js +104 -0
  94. package/dist/deputy/client.js.map +1 -0
  95. package/dist/deputy/db-facade.d.ts +18 -0
  96. package/dist/deputy/db-facade.js +71 -0
  97. package/dist/deputy/db-facade.js.map +1 -0
  98. package/dist/deputy/files.d.ts +1 -0
  99. package/dist/deputy/files.js +16 -0
  100. package/dist/deputy/files.js.map +1 -0
  101. package/dist/deputy/install.d.ts +319 -0
  102. package/dist/deputy/install.js +1239 -0
  103. package/dist/deputy/install.js.map +1 -0
  104. package/dist/deputy/notice.d.ts +6 -0
  105. package/dist/deputy/notice.js +28 -0
  106. package/dist/deputy/notice.js.map +1 -0
  107. package/dist/deputy/notices.d.ts +31 -0
  108. package/dist/deputy/notices.js +94 -0
  109. package/dist/deputy/notices.js.map +1 -0
  110. package/dist/deputy/osa.d.ts +21 -0
  111. package/dist/deputy/osa.js +72 -0
  112. package/dist/deputy/osa.js.map +1 -0
  113. package/dist/deputy/protocol.d.ts +140 -0
  114. package/dist/deputy/protocol.js +143 -0
  115. package/dist/deputy/protocol.js.map +1 -0
  116. package/dist/deputy/routing.d.ts +84 -0
  117. package/dist/deputy/routing.js +422 -0
  118. package/dist/deputy/routing.js.map +1 -0
  119. package/dist/deputy/shortcuts-exec.d.ts +10 -0
  120. package/dist/deputy/shortcuts-exec.js +50 -0
  121. package/dist/deputy/shortcuts-exec.js.map +1 -0
  122. package/dist/diagnose.d.ts +57 -2
  123. package/dist/diagnose.js +105 -3
  124. package/dist/diagnose.js.map +1 -1
  125. package/dist/direct-setup.d.ts +78 -0
  126. package/dist/direct-setup.js +484 -0
  127. package/dist/direct-setup.js.map +1 -0
  128. package/dist/host-access.d.ts +63 -0
  129. package/dist/host-access.js +165 -0
  130. package/dist/host-access.js.map +1 -0
  131. package/dist/index.d.ts +31 -5
  132. package/dist/index.js +23 -1
  133. package/dist/index.js.map +1 -1
  134. package/dist/mcp/server.d.ts +27 -1
  135. package/dist/mcp/server.js +300 -97
  136. package/dist/mcp/server.js.map +1 -1
  137. package/dist/model/mappers.d.ts +12 -3
  138. package/dist/model/mappers.js +6 -1
  139. package/dist/model/mappers.js.map +1 -1
  140. package/dist/model/recurrence.d.ts +5 -1
  141. package/dist/model/recurrence.js +19 -1
  142. package/dist/model/recurrence.js.map +1 -1
  143. package/dist/model/template-projection.d.ts +26 -0
  144. package/dist/model/template-projection.js +113 -0
  145. package/dist/model/template-projection.js.map +1 -0
  146. package/dist/op-result.d.ts +55 -0
  147. package/dist/op-result.js +161 -0
  148. package/dist/op-result.js.map +1 -0
  149. package/dist/read/detail.js +7 -1
  150. package/dist/read/detail.js.map +1 -1
  151. package/dist/read/filter-contract.d.ts +1 -1
  152. package/dist/read/filter-contract.js +4 -0
  153. package/dist/read/filter-contract.js.map +1 -1
  154. package/dist/read/queries.js +8 -1
  155. package/dist/read/queries.js.map +1 -1
  156. package/dist/read/shape.js +4 -0
  157. package/dist/read/shape.js.map +1 -1
  158. package/dist/read/views.d.ts +35 -4
  159. package/dist/read/views.js +120 -18
  160. package/dist/read/views.js.map +1 -1
  161. package/dist/session-grant.d.ts +48 -0
  162. package/dist/session-grant.js +170 -0
  163. package/dist/session-grant.js.map +1 -0
  164. package/dist/surface-copy.d.ts +8 -0
  165. package/dist/surface-copy.js +8 -0
  166. package/dist/surface-copy.js.map +1 -1
  167. package/dist/sync-health.js +6 -2
  168. package/dist/sync-health.js.map +1 -1
  169. package/dist/wizard.d.ts +58 -0
  170. package/dist/wizard.js +167 -0
  171. package/dist/wizard.js.map +1 -0
  172. package/dist/write/accessibility-probe.js +4 -2
  173. package/dist/write/accessibility-probe.js.map +1 -1
  174. package/dist/write/automation-probe.js +5 -1
  175. package/dist/write/automation-probe.js.map +1 -1
  176. package/dist/write/availability.d.ts +1 -1
  177. package/dist/write/availability.js +10 -6
  178. package/dist/write/availability.js.map +1 -1
  179. package/dist/write/batch.d.ts +20 -0
  180. package/dist/write/batch.js +94 -15
  181. package/dist/write/batch.js.map +1 -1
  182. package/dist/write/capabilities.d.ts +9 -0
  183. package/dist/write/capabilities.js +2 -0
  184. package/dist/write/capabilities.js.map +1 -1
  185. package/dist/write/clear-reminder.js +1 -1
  186. package/dist/write/clear-reminder.js.map +1 -1
  187. package/dist/write/commands.d.ts +12 -1
  188. package/dist/write/commands.js +170 -237
  189. package/dist/write/commands.js.map +1 -1
  190. package/dist/write/experimental.d.ts +19 -0
  191. package/dist/write/experimental.js +50 -0
  192. package/dist/write/experimental.js.map +1 -1
  193. package/dist/write/failure-hints.d.ts +3 -1
  194. package/dist/write/failure-hints.js.map +1 -1
  195. package/dist/write/guards.js +19 -2
  196. package/dist/write/guards.js.map +1 -1
  197. package/dist/write/lock.d.ts +16 -13
  198. package/dist/write/lock.js +55 -0
  199. package/dist/write/lock.js.map +1 -1
  200. package/dist/write/make-repeating-project.js +9 -13
  201. package/dist/write/make-repeating-project.js.map +1 -1
  202. package/dist/write/move.js +14 -6
  203. package/dist/write/move.js.map +1 -1
  204. package/dist/write/operations.d.ts +64 -25
  205. package/dist/write/operations.js +7 -0
  206. package/dist/write/operations.js.map +1 -1
  207. package/dist/write/opid.d.ts +14 -0
  208. package/dist/write/opid.js +22 -0
  209. package/dist/write/opid.js.map +1 -1
  210. package/dist/write/param-schema.d.ts +124 -0
  211. package/dist/write/param-schema.js +747 -0
  212. package/dist/write/param-schema.js.map +1 -0
  213. package/dist/write/pipeline.d.ts +78 -2
  214. package/dist/write/pipeline.js +249 -4
  215. package/dist/write/pipeline.js.map +1 -1
  216. package/dist/write/pre-state.d.ts +8 -0
  217. package/dist/write/pre-state.js +62 -17
  218. package/dist/write/pre-state.js.map +1 -1
  219. package/dist/write/promote-clone.js +635 -367
  220. package/dist/write/promote-clone.js.map +1 -1
  221. package/dist/write/reorder.js +95 -29
  222. package/dist/write/reorder.js.map +1 -1
  223. package/dist/write/repeat-anchor.d.ts +30 -0
  224. package/dist/write/repeat-anchor.js +166 -1
  225. package/dist/write/repeat-anchor.js.map +1 -1
  226. package/dist/write/repeat-rule.d.ts +28 -1
  227. package/dist/write/repeat-rule.js +64 -4
  228. package/dist/write/repeat-rule.js.map +1 -1
  229. package/dist/write/resolution-timestamps.d.ts +11 -0
  230. package/dist/write/resolution-timestamps.js +83 -38
  231. package/dist/write/resolution-timestamps.js.map +1 -1
  232. package/dist/write/reversibility.js +4 -0
  233. package/dist/write/reversibility.js.map +1 -1
  234. package/dist/write/template-mutation.d.ts +137 -0
  235. package/dist/write/template-mutation.js +451 -0
  236. package/dist/write/template-mutation.js.map +1 -0
  237. package/dist/write/undo.js +10 -20
  238. package/dist/write/undo.js.map +1 -1
  239. package/dist/write/update-fields.d.ts +151 -0
  240. package/dist/write/update-fields.js +427 -0
  241. package/dist/write/update-fields.js.map +1 -0
  242. package/dist/write/vectors/applescript.js +10 -16
  243. package/dist/write/vectors/applescript.js.map +1 -1
  244. package/dist/write/vectors/registry.d.ts +1 -1
  245. package/dist/write/vectors/registry.js +10 -2
  246. package/dist/write/vectors/registry.js.map +1 -1
  247. package/dist/write/vectors/session-reachability.d.ts +55 -0
  248. package/dist/write/vectors/session-reachability.js +56 -8
  249. package/dist/write/vectors/session-reachability.js.map +1 -1
  250. package/dist/write/vectors/shortcuts.js +7 -16
  251. package/dist/write/vectors/shortcuts.js.map +1 -1
  252. package/dist/write/vectors/simulator.d.ts +16 -1
  253. package/dist/write/vectors/simulator.js +68 -12
  254. package/dist/write/vectors/simulator.js.map +1 -1
  255. package/dist/write/vectors/types.d.ts +124 -1
  256. package/dist/write/vectors/ui-recipes.d.ts +19 -0
  257. package/dist/write/vectors/ui-recipes.js +158 -38
  258. package/dist/write/vectors/ui-recipes.js.map +1 -1
  259. package/dist/write/vectors/ui.d.ts +89 -0
  260. package/dist/write/vectors/ui.js +504 -49
  261. package/dist/write/vectors/ui.js.map +1 -1
  262. package/dist/write/verify/delta.d.ts +21 -0
  263. package/dist/write/verify/delta.js.map +1 -1
  264. package/dist/write/verify/poller.d.ts +13 -0
  265. package/dist/write/verify/poller.js +38 -0
  266. package/dist/write/verify/poller.js.map +1 -1
  267. package/package.json +9 -1
  268. package/schema/envelope.schema.json +5 -3
  269. package/scripts/build-helpers.sh +109 -0
  270. package/scripts/deputy-cert-setup.sh +60 -0
  271. package/skills/things-cli/SKILL.md +12 -5
  272. package/skills/things-cli/references/contracts.md +1 -0
  273. package/skills/things-cli/references/data-model.md +3 -0
  274. package/skills/things-cli/references/errors.md +5 -1
  275. package/skills/things-cli/references/gui.md +1 -0
  276. package/skills/things-cli/references/repeating.md +75 -0
  277. package/skills/things-cli/references/tag-cleanup.md +64 -0
@@ -0,0 +1,319 @@
1
+ import { type HelpersMode } from "../config.ts";
2
+ import { type Wizard } from "../wizard.ts";
3
+ import { type DeputyHello } from "./protocol.ts";
4
+ /**
5
+ * Where the LaunchAgent plists live. THINGS_API_LAUNCH_AGENTS_DIR overrides
6
+ * for tests — WITHOUT it, every suite that exercises install/uninstall/reset
7
+ * mutates the DEVELOPER MACHINE's real ~/Library/LaunchAgents. That is not
8
+ * hypothetical: it deleted the live helpers' plists mid-`npm run check`
9
+ * twice on 2026-08-24 before this seam existed. Test setup must always set
10
+ * it alongside THINGS_API_STATE_DIR.
11
+ */
12
+ export declare function launchAgentsDir(env?: NodeJS.ProcessEnv): string;
13
+ export declare function deputyPlistPath(env?: NodeJS.ProcessEnv): string;
14
+ export declare function readerPlistPath(env?: NodeJS.ProcessEnv): string;
15
+ /**
16
+ * Where an install looks for the bundle when the caller names no path, in
17
+ * preference order: `deputy/prebuilt` — the signed + notarized bundle the
18
+ * release workflow stages into the published tarball, so an npm install needs
19
+ * neither Xcode nor a certificate — then `deputy/build`, the output of
20
+ * scripts/build-helpers.sh in a source checkout.
21
+ */
22
+ export declare function helpersBundleCandidates(): string[];
23
+ /**
24
+ * The first candidate bundle that carries a deputy executable; null when none
25
+ * does. Both candidates are READ only — nothing in the `things helpers` path
26
+ * ever writes inside the package directory, so the CLI works from a read-only
27
+ * package root (an npx cache); BUILDING a bundle there is the one operation
28
+ * that needs a writable checkout, and `--bundle <path>` covers a prebuilt one.
29
+ */
30
+ export declare function helpersDefaultBuildPath(): string | null;
31
+ /**
32
+ * The INSTALLED bundle's version, read prompt-free from its Info.plist
33
+ * (CFBundleShortVersionString, stamped from deputy/VERSION at build time).
34
+ * Null when nothing is installed or the plist is unreadable/unstamped. This is
35
+ * the version a passive upgrade notice compares against
36
+ * {@link EXPECTED_HELPERS_VERSION} without needing a running helper.
37
+ */
38
+ export declare function installedHelpersVersion(env?: NodeJS.ProcessEnv): string | null;
39
+ /**
40
+ * The reader's LaunchAgent. Two keys carry the whole host-universal rendezvous:
41
+ *
42
+ * - **`Sockets`** — launchd creates, binds, listens on and chmods the socket at
43
+ * `socketPath`, which is OUR state directory, and hands the sandboxed reader
44
+ * the already-listening fd at activation (`launch_activate_socket`). The
45
+ * reader cannot bind outside its container, so launchd binding on its behalf
46
+ * is the only way the rendezvous escapes it — and with the socket outside
47
+ * every container, a client reaching it crosses no consent class.
48
+ * - **`EnvironmentVariables`** — the access token, minted by the installer and
49
+ * written to a sibling file for clients. Delivering it through the plist is
50
+ * what lets the reader keep its expected token out of the container too.
51
+ *
52
+ * The plist therefore CARRIES A SECRET and is written 0600 — the same
53
+ * same-user trust class as the token file itself.
54
+ */
55
+ export declare function renderReaderPlist(appPath: string, socketPath: string, token: string): string;
56
+ /**
57
+ * Mint the reader's access token and lay down the client half of the
58
+ * rendezvous: `<state>/reader`, 0700, holding a 0600 token file. Returns the
59
+ * token so the same value can be injected into the LaunchAgent.
60
+ *
61
+ * The installer mints it — not the reader — because the reader can only write
62
+ * inside its container, which is the placement this whole arrangement exists
63
+ * to leave. A fresh token per install is deliberate: install owns the pair
64
+ * wholesale, and rotating the secret costs nothing when both ends are rewritten
65
+ * in the same breath.
66
+ */
67
+ export declare function mintReaderRendezvous(env: NodeJS.ProcessEnv): string;
68
+ export interface DeputySigning {
69
+ state: "signed" | "adhoc" | "unsigned" | "unknown";
70
+ authority: string | null;
71
+ }
72
+ /** codesign facts about a binary (diagnostic output — may name mechanisms). */
73
+ export declare function deputySigningInfo(binaryPath: string): DeputySigning;
74
+ export interface HelpersInstallResult {
75
+ bundlePath: string;
76
+ plistPath: string;
77
+ stateDir: string;
78
+ signing: DeputySigning;
79
+ readerInstalled: boolean;
80
+ /** Reader grant state after install: null when the reader is absent or never answered. */
81
+ readerGranted: boolean | null;
82
+ warnings: string[];
83
+ }
84
+ /**
85
+ * Install (or reinstall) the helpers: copy the built bundle to its stable
86
+ * path, write both LaunchAgent plists, and (re)bootstrap them under launchd.
87
+ */
88
+ export declare function installHelpers(options?: {
89
+ bundlePath?: string;
90
+ }, env?: NodeJS.ProcessEnv): HelpersInstallResult;
91
+ export interface HelpersRevocation {
92
+ /** One row per macOS permission-store reset attempted. */
93
+ tccResets: {
94
+ target: string;
95
+ ok: boolean;
96
+ detail: string;
97
+ }[];
98
+ /**
99
+ * What made the identifiers resolvable for `tccutil`: the bundle this
100
+ * machine had installed, the packaged bundle registered on the spot, or
101
+ * nothing at all (the grants cannot be addressed from here).
102
+ */
103
+ resolvedVia: "installed" | "packaged" | "none";
104
+ /** The packaged bundle handed to LaunchServices, when that path was taken. */
105
+ registeredBundle: string | null;
106
+ /** The one leg no tool can perform — surfaced, never silently skipped. */
107
+ shortcutsNote: string;
108
+ }
109
+ export interface HelpersUninstallResult {
110
+ /** Files/directories that existed and were removed. */
111
+ removed: string[];
112
+ /** Null unless revocation was asked for. */
113
+ revocation: HelpersRevocation | null;
114
+ warnings: string[];
115
+ }
116
+ export interface HelpersUninstallOptions {
117
+ /**
118
+ * Also revoke both identities' macOS permission grants and delete their
119
+ * local state (the reader's bookmark container, the deputy's tokens/logs).
120
+ */
121
+ revoke?: boolean;
122
+ }
123
+ export interface HelpersUninstallDeps {
124
+ /** External tool runner (test seam — a real `tccutil` revokes live grants). */
125
+ runTool?: (bin: string, args: string[]) => {
126
+ ok: boolean;
127
+ output: string;
128
+ };
129
+ /** Where a packaged bundle lives for the LaunchServices fallback. */
130
+ packagedBundlePath?: () => string | null;
131
+ }
132
+ /**
133
+ * Stop both halves and remove their LaunchAgents + the installed bundle.
134
+ *
135
+ * By default the macOS grants and the local state (tokens, logs, the reader's
136
+ * bookmark) are KEPT: the TCC rows are keyed to the two signing identities and
137
+ * simply go dormant, so a later reinstall picks them straight back up with no
138
+ * second ceremony. `revoke` turns this into the ceremony's full inverse —
139
+ * grants revoked first (see {@link revokeGrants}), then the uninstall, then the
140
+ * reader's container and the deputy's state dir deleted (the read grant is a
141
+ * bookmark FILE, not a TCC row, so revoking it means deleting it).
142
+ *
143
+ * Every leg is independent and IDEMPOTENT: an already-uninstalled helper, an
144
+ * empty permission store, and absent directories are all fine — each leg does
145
+ * whatever is still outstanding, so this works from any partial state and a
146
+ * second run is an all-no-op.
147
+ */
148
+ export declare function uninstallHelpers(options?: HelpersUninstallOptions, env?: NodeJS.ProcessEnv, deps?: HelpersUninstallDeps): HelpersUninstallResult;
149
+ /** Restart the launchd-managed helpers (picks up a rebuilt installed bundle). */
150
+ export declare function restartHelpers(): void;
151
+ /**
152
+ * The one-time grant ceremony: open the reader in `--grant` mode (the panel
153
+ * must be presented by the SANDBOXED process — that is what makes the grant
154
+ * durable) and wait for the bookmark to land, confirmed via the reader's
155
+ * handshake. The panel opens INSIDE the Things data folder when it exists, so
156
+ * accepting is the only click. Interactive by design; returns when granted or
157
+ * on timeout, and verifies the database actually resolves inside the granted
158
+ * scope so a wrong-folder grant reports loudly instead of half-working.
159
+ */
160
+ export declare function grantReader(env?: NodeJS.ProcessEnv): {
161
+ granted: boolean;
162
+ detail: string;
163
+ };
164
+ export type OnboardLeg = "reader-read-grant" | "automation-things" | "automation-system-events" | "accessibility" | "shortcuts";
165
+ /**
166
+ * Which TIER a leg belongs to (docs/design/permissions-doctrine.md, Article V).
167
+ * The BASE tier gathers read + write capability, which is what every consumer
168
+ * of this package needs. The GUI tier adds the two grants that let the helpers
169
+ * drive the Things WINDOW — Accessibility and Automation → System Events — and
170
+ * is only gathered when it was asked for, because those two are the widest
171
+ * grants the pair ever holds and most households never need them.
172
+ */
173
+ export type OnboardTier = "base" | "gui";
174
+ /**
175
+ * Where a leg stands after the ceremony. `pending` is a HUMAN-pace outcome (a
176
+ * dialog left unanswered, a toggle not yet flipped) and is not a failure —
177
+ * rerunning resumes exactly where it stopped. Only `denied` means macOS (or
178
+ * the user) refused, and only that makes the command exit nonzero.
179
+ */
180
+ export type OnboardState = "granted" | "denied" | "pending" | "skipped-not-installed";
181
+ export interface OnboardStep {
182
+ leg: OnboardLeg;
183
+ /** The row label in the closing report. */
184
+ label: string;
185
+ /** The tier this leg belongs to — `gui` legs run only when that tier is in. */
186
+ tier: OnboardTier;
187
+ state: OnboardState;
188
+ /** True when the leg was already satisfied, detected without raising anything. */
189
+ alreadyGranted: boolean;
190
+ detail: string;
191
+ }
192
+ export interface HelpersOnboardResult {
193
+ /** The tier this run gathered: `base`, or `gui` (base plus the GUI legs). */
194
+ tier: OnboardTier;
195
+ /**
196
+ * How the GUI tier came to be included: the `--gui` flag, the `ui-enabled`
197
+ * config key already being on, the wizard's interactive question, or not at
198
+ * all. Reported so the ceremony's own output can say why it did what it did.
199
+ */
200
+ guiRequestedBy: "flag" | "config" | "wizard" | null;
201
+ /** True when this run turned `ui-enabled` on as part of a successful GUI tier. */
202
+ uiEnabledSet: boolean;
203
+ steps: OnboardStep[];
204
+ /**
205
+ * The legs that were going to put something on screen, surveyed prompt-free
206
+ * BEFORE the first one ran. Empty means the ceremony raised nothing.
207
+ */
208
+ outstanding: OnboardLeg[];
209
+ /** Any leg refused. */
210
+ denied: boolean;
211
+ /** Any leg still waiting on a human. */
212
+ pending: boolean;
213
+ /** The single closing line printed under the report. */
214
+ closing: string;
215
+ }
216
+ /** The deputy transport the ceremony drives (a test seam — see {@link OnboardDeps}). */
217
+ export interface OnboardChannel {
218
+ hello(): DeputyHello;
219
+ request(fields: Record<string, unknown>, timeoutMs: number): Record<string, unknown>;
220
+ close(): void;
221
+ }
222
+ export interface OnboardDeps {
223
+ /** One line per step, as it happens. Default: stdout. */
224
+ progress?: (line: string) => void;
225
+ channel?: OnboardChannel;
226
+ /** Reader state, prompt-free: granted bookmark AND a database inside it. */
227
+ readerProbe?: () => {
228
+ granted: boolean;
229
+ locates: boolean;
230
+ } | null;
231
+ /** The reader's panel ceremony (default: {@link grantReader}). */
232
+ grant?: () => {
233
+ granted: boolean;
234
+ detail: string;
235
+ };
236
+ /** Best-effort deep link into System Settings. Default: `open <url>`. */
237
+ openUrl?: (url: string) => void;
238
+ sleep?: (ms: number) => void;
239
+ now?: () => number;
240
+ automationTimeoutMs?: number;
241
+ axTimeoutMs?: number;
242
+ axIntervalMs?: number;
243
+ /** How long to wait for the deputy's socket to appear (a just-installed helper is still coming up). */
244
+ deputyWaitMs?: number;
245
+ /**
246
+ * The Article V wizard. Default: built from TTY-ness (../wizard.ts). At a TTY
247
+ * it explains each dialog before the leg raises it and asks the tier question;
248
+ * off a TTY every method is inert and the ceremony behaves exactly as it did
249
+ * before the wizard existed.
250
+ */
251
+ wizard?: Wizard;
252
+ /** Is `ui-enabled` already on? Default: the stored config. */
253
+ uiEnabled?: () => boolean;
254
+ /** Turn `ui-enabled` on after a successful GUI tier. Default: the config file. */
255
+ setUiEnabled?: (value: boolean) => void;
256
+ }
257
+ /** What `onboardHelpers` is being asked to gather. */
258
+ export interface OnboardOptions {
259
+ /** The configured routing mode, for the closing line. */
260
+ mode: HelpersMode;
261
+ /**
262
+ * Gather the GUI tier as well (`things helpers setup --gui`). When omitted,
263
+ * the tier is still included if `ui-enabled` is already on (a machine that
264
+ * has opted into GUI-driving is asking for the grants by definition), or if
265
+ * the wizard's interactive question is answered yes.
266
+ */
267
+ gui?: boolean;
268
+ }
269
+ /**
270
+ * The full onboarding ceremony behind `things helpers setup`: fire every
271
+ * consent macOS will ever ask for while a human is sitting there, then report
272
+ * where each one landed. Every leg is IDEMPOTENT — an already-granted leg is
273
+ * detected prompt-free (the deputy's own `hello` carries its TCC standing) and
274
+ * skipped — so a rerun on a fully onboarded machine raises nothing and reports
275
+ * all-green. Interactive by design: run it at the machine.
276
+ *
277
+ * Throws when the helpers are not installed or the deputy does not answer;
278
+ * every other outcome is reported per leg. See docs/design/helpers-onboarding.md.
279
+ *
280
+ * Runs under `withDefaultInterrupts` for its whole synchronous span, so Ctrl-C
281
+ * stops it at a gate AND inside the Accessibility wait (../wizard.ts, "Why a
282
+ * ceremony runs with the DEFAULT signal disposition"). Throws `CeremonyStopped`
283
+ * when the human stops at a gate.
284
+ */
285
+ export declare function onboardHelpers(options: OnboardOptions, env?: NodeJS.ProcessEnv, deps?: OnboardDeps): HelpersOnboardResult;
286
+ export interface DeputyHalfStatus {
287
+ plistInstalled: boolean;
288
+ loaded: boolean;
289
+ running: boolean;
290
+ socketPath: string;
291
+ /**
292
+ * The socket file exists but no handshake came back (a dead process that
293
+ * left its socket behind, or one wedged mid-request). Distinct from plain
294
+ * "not running": the remedy is `things helpers restart`, not an install.
295
+ */
296
+ hungSocket: boolean;
297
+ hello: DeputyHello | null;
298
+ signing: DeputySigning | null;
299
+ detail: string;
300
+ }
301
+ export interface ReaderHalfStatus extends DeputyHalfStatus {
302
+ installed: boolean;
303
+ granted: boolean;
304
+ }
305
+ export interface HelpersStatus {
306
+ /** The configured routing mode (`helpers-enabled`), not what it resolved to. */
307
+ mode: HelpersMode;
308
+ bundleInstalled: boolean;
309
+ /** The installed bundle's version (Info.plist), null when nothing is installed. */
310
+ installedVersion: string | null;
311
+ deputy: DeputyHalfStatus;
312
+ reader: ReaderHalfStatus;
313
+ }
314
+ /**
315
+ * Prompt-free status for both halves: launchd load state, a live handshake
316
+ * when each socket answers, and the installed bundle's signing facts. Works
317
+ * with routing disabled — inspect first, enable after.
318
+ */
319
+ export declare function helpersStatus(mode: HelpersMode, env?: NodeJS.ProcessEnv): HelpersStatus;