things-api 0.18.0 → 0.19.1

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 (224) hide show
  1. package/README.md +18 -9
  2. package/deputy/AppIcon.icns +0 -0
  3. package/deputy/VERSION +1 -1
  4. package/deputy/helpers-Info.plist +4 -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 +3 -1
  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 +15 -2
  10. package/deputy/prebuilt/Things API Helper.app/Contents/Info.plist +5 -1
  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 +14 -2
  14. package/deputy/reader/Info.plist +2 -0
  15. package/deputy/reader/entitlements.plist +30 -0
  16. package/deputy/reader/main.swift +129 -40
  17. package/deputy/src/server.swift +25 -2
  18. package/deputy/src/tcc.swift +58 -0
  19. package/dist/audit/schema.d.ts +30 -1
  20. package/dist/audit/schema.js.map +1 -1
  21. package/dist/capability.d.ts +322 -0
  22. package/dist/capability.js +706 -0
  23. package/dist/capability.js.map +1 -0
  24. package/dist/cli/commands/doctor.d.ts +13 -1
  25. package/dist/cli/commands/doctor.js +141 -5
  26. package/dist/cli/commands/doctor.js.map +1 -1
  27. package/dist/cli/commands/helpers.js +189 -51
  28. package/dist/cli/commands/helpers.js.map +1 -1
  29. package/dist/cli/commands/mcp.js +8 -0
  30. package/dist/cli/commands/mcp.js.map +1 -1
  31. package/dist/cli/commands/op-result.js +6 -0
  32. package/dist/cli/commands/op-result.js.map +1 -1
  33. package/dist/cli/commands/reads.js +47 -1
  34. package/dist/cli/commands/reads.js.map +1 -1
  35. package/dist/cli/commands/repeat-flags.js +34 -2
  36. package/dist/cli/commands/repeat-flags.js.map +1 -1
  37. package/dist/cli/commands/setup.d.ts +9 -0
  38. package/dist/cli/commands/setup.js +76 -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 +311 -142
  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 +49 -27
  50. package/dist/cli/help.js.map +1 -1
  51. package/dist/cli/interrupt.d.ts +54 -6
  52. package/dist/cli/interrupt.js +78 -12
  53. package/dist/cli/interrupt.js.map +1 -1
  54. package/dist/cli/main.js +8 -5
  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 +23 -3
  65. package/dist/client.js +36 -13
  66. package/dist/client.js.map +1 -1
  67. package/dist/contracts.d.ts +8 -4
  68. package/dist/contracts.js +1 -1
  69. package/dist/contracts.js.map +1 -1
  70. package/dist/deputy/install.d.ts +234 -6
  71. package/dist/deputy/install.js +843 -31
  72. package/dist/deputy/install.js.map +1 -1
  73. package/dist/deputy/notices.js +2 -2
  74. package/dist/deputy/notices.js.map +1 -1
  75. package/dist/deputy/protocol.d.ts +59 -5
  76. package/dist/deputy/protocol.js +48 -11
  77. package/dist/deputy/protocol.js.map +1 -1
  78. package/dist/deputy/routing.d.ts +37 -0
  79. package/dist/deputy/routing.js +181 -27
  80. package/dist/deputy/routing.js.map +1 -1
  81. package/dist/deputy/wake.d.ts +61 -0
  82. package/dist/deputy/wake.js +149 -0
  83. package/dist/deputy/wake.js.map +1 -0
  84. package/dist/diagnose.d.ts +19 -4
  85. package/dist/diagnose.js +64 -8
  86. package/dist/diagnose.js.map +1 -1
  87. package/dist/direct-setup.d.ts +104 -0
  88. package/dist/direct-setup.js +658 -0
  89. package/dist/direct-setup.js.map +1 -0
  90. package/dist/host-access.d.ts +75 -0
  91. package/dist/host-access.js +177 -0
  92. package/dist/host-access.js.map +1 -0
  93. package/dist/index.d.ts +20 -5
  94. package/dist/index.js +14 -1
  95. package/dist/index.js.map +1 -1
  96. package/dist/mcp/server.d.ts +27 -1
  97. package/dist/mcp/server.js +308 -109
  98. package/dist/mcp/server.js.map +1 -1
  99. package/dist/op-result.d.ts +9 -0
  100. package/dist/op-result.js +13 -1
  101. package/dist/op-result.js.map +1 -1
  102. package/dist/read/filter-contract.d.ts +1 -1
  103. package/dist/read/filter-contract.js +4 -0
  104. package/dist/read/filter-contract.js.map +1 -1
  105. package/dist/read/shape.js +4 -0
  106. package/dist/read/shape.js.map +1 -1
  107. package/dist/read/views.d.ts +29 -0
  108. package/dist/read/views.js +60 -0
  109. package/dist/read/views.js.map +1 -1
  110. package/dist/session-grant.d.ts +48 -0
  111. package/dist/session-grant.js +185 -0
  112. package/dist/session-grant.js.map +1 -0
  113. package/dist/surface-copy.d.ts +19 -3
  114. package/dist/surface-copy.js +19 -3
  115. package/dist/surface-copy.js.map +1 -1
  116. package/dist/wizard.d.ts +58 -0
  117. package/dist/wizard.js +174 -0
  118. package/dist/wizard.js.map +1 -0
  119. package/dist/write/availability.d.ts +1 -16
  120. package/dist/write/availability.js +10 -65
  121. package/dist/write/availability.js.map +1 -1
  122. package/dist/write/batch.d.ts +20 -0
  123. package/dist/write/batch.js +111 -21
  124. package/dist/write/batch.js.map +1 -1
  125. package/dist/write/capabilities.d.ts +9 -0
  126. package/dist/write/capabilities.js +2 -0
  127. package/dist/write/capabilities.js.map +1 -1
  128. package/dist/write/clear-reminder.js +1 -1
  129. package/dist/write/clear-reminder.js.map +1 -1
  130. package/dist/write/commands.d.ts +22 -7
  131. package/dist/write/commands.js +231 -254
  132. package/dist/write/commands.js.map +1 -1
  133. package/dist/write/failure-hints.d.ts +32 -7
  134. package/dist/write/failure-hints.js +9 -14
  135. package/dist/write/failure-hints.js.map +1 -1
  136. package/dist/write/guards.js +22 -4
  137. package/dist/write/guards.js.map +1 -1
  138. package/dist/write/lock.d.ts +16 -13
  139. package/dist/write/lock.js +55 -0
  140. package/dist/write/lock.js.map +1 -1
  141. package/dist/write/make-repeating-project.js +9 -13
  142. package/dist/write/make-repeating-project.js.map +1 -1
  143. package/dist/write/move.js +9 -12
  144. package/dist/write/move.js.map +1 -1
  145. package/dist/write/operations.d.ts +51 -29
  146. package/dist/write/operations.js +16 -0
  147. package/dist/write/operations.js.map +1 -1
  148. package/dist/write/opid.d.ts +72 -14
  149. package/dist/write/opid.js +152 -8
  150. package/dist/write/opid.js.map +1 -1
  151. package/dist/write/param-schema.d.ts +80 -0
  152. package/dist/write/param-schema.js +754 -0
  153. package/dist/write/param-schema.js.map +1 -0
  154. package/dist/write/pipeline.d.ts +110 -5
  155. package/dist/write/pipeline.js +288 -14
  156. package/dist/write/pipeline.js.map +1 -1
  157. package/dist/write/pre-state.d.ts +38 -16
  158. package/dist/write/pre-state.js +117 -22
  159. package/dist/write/pre-state.js.map +1 -1
  160. package/dist/write/promote-clone.js +658 -444
  161. package/dist/write/promote-clone.js.map +1 -1
  162. package/dist/write/reorder.js +25 -8
  163. package/dist/write/reorder.js.map +1 -1
  164. package/dist/write/repeat-collateral.d.ts +31 -0
  165. package/dist/write/repeat-collateral.js +153 -0
  166. package/dist/write/repeat-collateral.js.map +1 -0
  167. package/dist/write/repeat-rule.d.ts +28 -1
  168. package/dist/write/repeat-rule.js +54 -4
  169. package/dist/write/repeat-rule.js.map +1 -1
  170. package/dist/write/resolution-timestamps.d.ts +11 -0
  171. package/dist/write/resolution-timestamps.js +108 -40
  172. package/dist/write/resolution-timestamps.js.map +1 -1
  173. package/dist/write/reversibility.js +4 -0
  174. package/dist/write/reversibility.js.map +1 -1
  175. package/dist/write/template-mutation.d.ts +137 -0
  176. package/dist/write/template-mutation.js +598 -0
  177. package/dist/write/template-mutation.js.map +1 -0
  178. package/dist/write/undo.js +10 -20
  179. package/dist/write/undo.js.map +1 -1
  180. package/dist/write/update-fields.d.ts +151 -0
  181. package/dist/write/update-fields.js +427 -0
  182. package/dist/write/update-fields.js.map +1 -0
  183. package/dist/write/vectors/applescript.js +6 -10
  184. package/dist/write/vectors/applescript.js.map +1 -1
  185. package/dist/write/vectors/registry.d.ts +1 -1
  186. package/dist/write/vectors/registry.js +10 -2
  187. package/dist/write/vectors/registry.js.map +1 -1
  188. package/dist/write/vectors/shortcuts.js +2 -2
  189. package/dist/write/vectors/shortcuts.js.map +1 -1
  190. package/dist/write/vectors/simulator.js +15 -4
  191. package/dist/write/vectors/simulator.js.map +1 -1
  192. package/dist/write/vectors/types.d.ts +268 -1
  193. package/dist/write/vectors/ui-certification.js +63 -13
  194. package/dist/write/vectors/ui-certification.js.map +1 -1
  195. package/dist/write/vectors/ui-chord.d.ts +144 -0
  196. package/dist/write/vectors/ui-chord.js +428 -0
  197. package/dist/write/vectors/ui-chord.js.map +1 -0
  198. package/dist/write/vectors/ui-drag.d.ts +8 -4
  199. package/dist/write/vectors/ui-drag.js +2 -0
  200. package/dist/write/vectors/ui-drag.js.map +1 -1
  201. package/dist/write/vectors/ui-recipes.d.ts +70 -3
  202. package/dist/write/vectors/ui-recipes.js +482 -44
  203. package/dist/write/vectors/ui-recipes.js.map +1 -1
  204. package/dist/write/vectors/ui.d.ts +280 -10
  205. package/dist/write/vectors/ui.js +1068 -77
  206. package/dist/write/vectors/ui.js.map +1 -1
  207. package/dist/write/vectors/url-scheme.js +3 -0
  208. package/dist/write/vectors/url-scheme.js.map +1 -1
  209. package/dist/write/verify/delta.d.ts +62 -0
  210. package/dist/write/verify/delta.js +36 -2
  211. package/dist/write/verify/delta.js.map +1 -1
  212. package/dist/write/verify/poller.d.ts +4 -1
  213. package/dist/write/verify/poller.js +14 -0
  214. package/dist/write/verify/poller.js.map +1 -1
  215. package/package.json +2 -1
  216. package/schema/envelope.schema.json +6 -4
  217. package/scripts/build-helpers.sh +5 -0
  218. package/skills/things-cli/SKILL.md +5 -3
  219. package/skills/things-cli/references/contracts.md +1 -0
  220. package/skills/things-cli/references/data-model.md +3 -0
  221. package/skills/things-cli/references/errors.md +1 -1
  222. package/skills/things-cli/references/gui.md +1 -0
  223. package/skills/things-cli/references/repeating.md +6 -0
  224. package/skills/things-cli/references/tag-cleanup.md +64 -0
@@ -1,7 +1,9 @@
1
1
  import { UI_DRIVE_OPS } from "../operations.js";
2
2
  /** The manifest profile — records the tier + Things build the suite certified. */
3
- export const UI_CERTIFICATION_PROFILE = "UIC1 + UIC3 + AXDRAG2 + UIC5 + UIC6 + UIC7 + UIC7b + HEADCERT1 + HXPC1 + DISS1 in-VM (Things 3.22.11) + " +
4
- "UIC8 promote-via-clone compounds in-VM (golden-v2 / Things 3.22.12) on-device pending";
3
+ export const UI_CERTIFICATION_PROFILE = "UIC1 + UIC3 + AXDRAG2 + UIC5 + UIC6 + UIC7 + UIC7b + HEADCERT1 + HEADXPROJ + DISS1 in-VM (Things 3.22.11) + " +
4
+ "UIC8 promote-via-clone compounds in-VM (golden-v2 / Things 3.22.12) + RDLG2 recipe re-point + " +
5
+ "HXPC1 heading-ellipsis/Move-picker paths in-VM (golden-v4 / Things 3.23) + " +
6
+ "CHORDMH1 heading-order arrow chords in-VM (golden-v4 / Things 3.23) — on-device pending";
5
7
  const CERTIFICATION = {
6
8
  "todo.make-repeating": {
7
9
  status: "lab-certified",
@@ -48,16 +50,59 @@ const CERTIFICATION = {
48
50
  evidence: ["UI2-d", "UIC1-a", "HEADCERT1"],
49
51
  },
50
52
  "project.move-heading-to-project": {
51
- // HXPC1 (2026-07-28, bjhx-lab, Things 3.22.11): the ellipsis Move… recipe ran
52
- // end-to-end in the clone HID-click the "More. <title>" button → Move… →
53
- // type the destination → Return and the exact HEADXPROJ delta was observed:
54
- // heading `HXH` project-FK rewritten HX-PA → HX-PB, both children followed via
55
- // their intact heading FK (project NULL, heading=HXH), single-row change, no
56
- // index churn. The shipped recipe's popover-item AX PATHS (description-based
57
- // click-element) are provisional pending an on-device sitting HXPC1 drove the
58
- // equivalent frame-center synthesis; the DB oracle + recipe flow are certified.
53
+ // HEADXPROJ (2026-07-27, bjhx-lab, Things 3.22.11) established the flow and the
54
+ // DB oracle with a hand-written driver: HID-click the "More. <title>" button →
55
+ // Move… → type the destination → Return, and heading `HXH`'s project FK
56
+ // rewritten HX-PA → HX-PB with both children following via their intact heading
57
+ // FK (project NULL, heading=HXH) — a single-row change, no index churn.
58
+ //
59
+ // HXPC1 (2026-08-25, hxpc1-lab, Things 3.23 / golden-v4) certified the SHIPPED
60
+ // recipe for the first time and corrected three of the four provisional paths:
61
+ // the "More. <title>" button is three levels below the content table (so the
62
+ // shipped one-level `whose` clause matched nothing and the drive never got past
63
+ // its first click), the picker is a detached `MovePopUpDialog-` window rather
64
+ // than a sheet of the main window, and the commit is a CLICK on the row whose
65
+ // title matches exactly — the blind Return could take the picker's
66
+ // `New Project "<typed>"` row whenever the destination was absent from it,
67
+ // which a completed or canceled destination is. 7/7 through the production CLI
68
+ // (clean match, prefix collision, completed-destination refusal with zero
69
+ // mutation). docs/lab/hxpc1-picker-assert.md.
59
70
  status: "lab-certified",
60
- evidence: ["HXPC1"],
71
+ evidence: ["HEADXPROJ", "HXPC1"],
72
+ },
73
+ "project.move-heading": {
74
+ // HEADORD1 (2026-08-25, headord1-lab, Things 3.23 / golden-v4) discovered and
75
+ // characterised the affordance: ⌘↑/⌘↓ = ±1 slot, ⌘⌥↑/⌘⌥↓ = to top/bottom on a
76
+ // selected heading row; a single-row `index` rewrite with no sibling renumber
77
+ // and children untouched behind their FK; a chord with nowhere to go declined
78
+ // with zero delta and one alert beep; System Events modifiers frontmost-only,
79
+ // `CGEventPostToPid` background-capable.
80
+ //
81
+ // CHORDMH1 (2026-08-25, chordmh1-lab, Things 3.23 / golden-v4) certified the
82
+ // SHIPPED op. Its delivery gate re-measured the whole gesture with Things
83
+ // never activated at all — `open -g` reveal, pure-AX row select, pid-posted
84
+ // chord — and Finder frontmost at every stage, so the op ships BACKGROUND
85
+ // delivery with no `activate` step (the least-disruptive tier any ordering op
86
+ // has reached). The certification arms drove the production CLI over
87
+ // 3-heading fixtures: ±1 up, ±1 down, to-top, to-bottom, a multi-hop, the
88
+ // already-in-position no-op, the dry run, and the ungated call — children
89
+ // byte-identical on every arm, sibling indexes byte-identical, zero beeps on
90
+ // the normal paths. docs/lab/chordmh1-move-heading-build.md.
91
+ //
92
+ // CHORDMH2 (2026-08-25, chordmh2-lab, Things 3.23 / golden-v4) lifted CHORDMH1's
93
+ // one deliberate capability cut — the whole-project refusal on any archived
94
+ // heading — after CHORD2 cell 7a′ measured that an archived heading renders no
95
+ // content row, takes no ordinal in the walk, and is skipped by a live heading's
96
+ // ±1. The fence stood in for an ordinal mismatch, so the three reads that feed
97
+ // the plan, the driver and the bare-placement anchor now return the RENDERED
98
+ // (`status = 0`) order. Certified through the production CLI: one chord carried
99
+ // a heading past an archived row's slot, that heading was the only row
100
+ // rewritten, the archived row was byte-untouched on status/index/stopDate/umd,
101
+ // children intact, zero beeps; an archived heading named as a movee or an
102
+ // anchor still refuses with zero mutation.
103
+ // docs/lab/chordmh2-archived-fence-lift.md.
104
+ status: "lab-certified",
105
+ evidence: ["HEADORD1", "CHORDMH1", "CHORDMH2"],
61
106
  },
62
107
  "project.dissolve-heading": {
63
108
  // DISS1 (2026-07-28, bjhx-lab, Things 3.22.11): the ellipsis Delete recipe ran
@@ -66,8 +111,13 @@ const CERTIFICATION = {
66
111
  // TMTask), its 3 children re-homed as DIRECT project children (heading→NULL,
67
112
  // project→parent, index preserved: c1<c2<c3, trashed=0). NO confirm sheet.
68
113
  // Popover items are AX-description-enumerable (the recipe resolves Delete by
69
- // description, scoped to the popover). The shipped recipe's popover AX paths are
70
- // provisional pending an on-device sitting; the DB oracle + flow are certified.
114
+ // description, scoped to the popover) the one provisional path HXPC1 measured
115
+ // CORRECT. Its sibling was not: the "More. <title>" button this drive opens the
116
+ // popover with was addressed one level too shallow, so it resolved nothing and
117
+ // the drive died at its first click on every host. HXPC1 (2026-08-25, Things
118
+ // 3.23) fixed the walk and certified it through the move-heading sibling, but
119
+ // this op was NOT driven end to end there — its next sitting should carry a cell
120
+ // (docs/lab/hxpc1-picker-assert.md §B0/§D). The DB oracle + flow are certified.
71
121
  status: "lab-certified",
72
122
  evidence: ["DISS1"],
73
123
  },
@@ -1 +1 @@
1
- {"version":3,"file":"ui-certification.js","sourceRoot":"","sources":["../../../src/write/vectors/ui-certification.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ui-certification.js","sourceRoot":"","sources":["../../../src/write/vectors/ui-certification.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,144 @@
1
+ import type { DatabaseSync } from "node:sqlite";
2
+ import type { UiCommand, UiRunner } from "./ui.ts";
3
+ /** The move a `chord-reorder` step performs, compiled from the pre-state. */
4
+ export interface HeadingChordSpec {
5
+ /** The project whose headings are being reordered. */
6
+ projectUuid: string;
7
+ /**
8
+ * Every LIVE (`status = 0`) heading of the project, in the order they must end
9
+ * up in — the full end state, not just the moved block. The driver places them
10
+ * left to right, so this doubles as the verification target. Archived headings
11
+ * are absent by construction: they render no row, so they are neither
12
+ * addressable nor displaced (CHORD2 cell 7a′).
13
+ */
14
+ targetOrder: string[];
15
+ /**
16
+ * The headings the caller named. Only these may ever be chorded: if the
17
+ * driver's placement walk would have to move a heading the caller did not
18
+ * name, it refuses rather than touch a bystander.
19
+ */
20
+ movees: string[];
21
+ /** The project view's content table (the recipe supplies the one path). */
22
+ tablePath: string;
23
+ }
24
+ /** The database read the driver asserts against between chords. */
25
+ export interface HeadingOrderState {
26
+ /**
27
+ * The project's LIVE (`status = 0`) headings in `index` order, with their raw
28
+ * index — the rows the project view actually renders, and therefore the rows
29
+ * the positional `select-heading-row` walk enumerates. An ARCHIVED heading is
30
+ * absent: it renders no row, takes no ordinal, and a live heading's ±1 chord
31
+ * skips its slot in one dispatch (CHORD2 cell 7a′). Filtering here is what
32
+ * keeps the driver's ordinals in step with the walk's.
33
+ */
34
+ headings: {
35
+ uuid: string;
36
+ index: number;
37
+ }[];
38
+ /**
39
+ * Digest over every non-trashed child of those headings: `uuid:headingFK:index`.
40
+ * The chord law says children are untouched behind their FK — this is what
41
+ * proves it, and what catches the one measured hazard in the family (a row
42
+ * driven across a heading boundary has its heading FK rewritten, HEADORD1 §2
43
+ * cells 1h4/1i2; it cannot happen to a heading, and this asserts that).
44
+ */
45
+ childDigest: string;
46
+ /** How many child rows the digest covers (reported in the failure text). */
47
+ childCount: number;
48
+ }
49
+ /** The database seam the chord driver reads its ground truth through. */
50
+ export type HeadingOrderReader = (projectUuid: string) => HeadingOrderState;
51
+ /**
52
+ * The client-side default: heading order + child containment, from the open DB.
53
+ *
54
+ * The heading read is filtered to `status = 0` so it returns the RENDERED order
55
+ * (CHORD2 cell 7a′). The child digest is deliberately NOT filtered — it covers
56
+ * every non-trashed child of every heading of the project, archived headings
57
+ * included, because no heading chord may disturb any of them.
58
+ */
59
+ export declare function createHeadingOrderReader(db: DatabaseSync): HeadingOrderReader;
60
+ /**
61
+ * The four chords, as `(key code, CGEventFlags)` pairs. `126`/`125` are the
62
+ * arrow keys; `0x100000` is `kCGEventFlagMaskCommand` and `0x80000`
63
+ * `kCGEventFlagMaskAlternate`. Named rather than inlined so the recipe trace and
64
+ * the failure text can say which chord was posted.
65
+ */
66
+ export type ChordId = "up-one" | "down-one" | "to-top" | "to-bottom";
67
+ export declare function chordGlyph(id: ChordId): string;
68
+ /**
69
+ * Post ONE modifier-bearing key event pair straight at the Things process
70
+ * (`CGEventPostToPid`), through the same JXA ObjC bridge every other synthetic
71
+ * input in this codebase rides.
72
+ *
73
+ * Why not System Events. The shipped `key` primitive emits `key code N` with no
74
+ * modifier support at all, and the System-Events spelling that DOES carry
75
+ * modifiers only lands while Things is FRONTMOST (HEADORD1 cell 1h2b: with
76
+ * Finder frontmost it produced no delta). `CGEventPostToPid` addresses the
77
+ * process rather than the focused surface, so the whole gesture — reveal,
78
+ * select, chord — runs with Things in the background and the user's focus
79
+ * untouched. Measured on Things 3.23 / golden-v4 (HEADORD1 1h2a; re-measured end
80
+ * to end, with Things never activated at all, by CHORDMH1's delivery gate).
81
+ *
82
+ * Note this is the KEYBOARD tap only. NATIVE1-e measured `CGEventPostToPid` as
83
+ * inert for Things' MOUSE hit-testing, which is why click synthesis still uses
84
+ * the HID tap and stays foreground-bound; keyboard events to the pid are a
85
+ * different path and do land.
86
+ */
87
+ export declare function jxaChordScript(id: ChordId): string;
88
+ export declare function chordCommand(id: ChordId): UiCommand;
89
+ /** Select the Nth heading row of the revealed project view (the shipped primitive). */
90
+ export declare function chordSelectCommand(tablePath: string, ordinal: number, script: string): UiCommand;
91
+ export interface ChordDriveResult {
92
+ ok: boolean;
93
+ /** Human-readable outcome (chords posted) or the refusal reason. */
94
+ detail: string;
95
+ /** How many chords were posted before the outcome (partial-state honesty). */
96
+ chords: number;
97
+ }
98
+ /** One scheduled step: which heading to chord, with what, and where it must land. */
99
+ export interface ChordStep {
100
+ /** The heading to select and move — ALWAYS one the caller named. */
101
+ uuid: string;
102
+ chord: ChordId;
103
+ /** The position the heading must occupy afterwards (the progress assertion). */
104
+ landsAt: number;
105
+ }
106
+ /**
107
+ * The next chord that advances `order` towards `target`, or null when they
108
+ * already agree. `movees` is the only set of rows a chord may ever move.
109
+ *
110
+ * THE SCHEDULE, and why it is this one. The obvious walk — "put target[i] into
111
+ * slot i, left to right" — is WRONG here, because target[i] is very often a row
112
+ * the caller never named: asking to move heading A down one slot produces a
113
+ * target whose first element is the BYSTANDER B. Moving B is not an option (it
114
+ * would break the untouched-siblings law the whole vector rests on), and the
115
+ * equally obvious repair — "push whichever movee sits at slot i down" — thrashes
116
+ * forever when two movees sit side by side, each pushing the other back.
117
+ *
118
+ * So the rule fixes the first mismatched slot `i` from the row's own side:
119
+ *
120
+ * - target[i] IS a movee → it is necessarily BELOW slot i (everything above
121
+ * already matches), so step it UP; from slot 0 the one-dispatch ⌘⌥↑ takes it
122
+ * there directly.
123
+ * - target[i] is a bystander `R` → every row between slot i and R's current
124
+ * position is provably a movee (the non-movees keep their relative order, so
125
+ * R is the first non-movee at or below i), and pushing the ONE movee directly
126
+ * above R down past it moves R up by exactly one slot.
127
+ *
128
+ * Both branches strictly reduce a distance that cannot go below zero, so the
129
+ * schedule terminates, and every chord it emits moves a named heading by one
130
+ * slot. Two endpoint shortcuts run first, because they are the common single
131
+ * heading requests and each costs one dispatch instead of a walk: a movee whose
132
+ * target is the very top or the very bottom is sent there with ⌘⌥↑ / ⌘⌥↓.
133
+ */
134
+ export declare function planChordStep(order: readonly string[], target: readonly string[], movees: ReadonlySet<string>): ChordStep | {
135
+ error: string;
136
+ } | null;
137
+ /**
138
+ * Drive a project's headings into `spec.targetOrder`, one verified chord at a
139
+ * time (see {@link planChordStep} for the schedule). Nothing here trusts the
140
+ * plan it made a moment ago: every step is re-derived from a fresh database
141
+ * read, and the step is only counted once the database says it landed where it
142
+ * was aimed with nothing else touched.
143
+ */
144
+ export declare function driveHeadingChordReorder(spec: HeadingChordSpec, run: UiRunner, reader: HeadingOrderReader | undefined, selectScript: (ordinal: number) => string, sleep?: (ms: number) => Promise<void>): Promise<ChordDriveResult>;