tickmarkr 1.83.0 → 1.85.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 (37) hide show
  1. package/dist/adapters/claude-code.d.ts +1 -0
  2. package/dist/adapters/claude-code.js +57 -1
  3. package/dist/adapters/fake.js +9 -0
  4. package/dist/adapters/types.d.ts +3 -0
  5. package/dist/adapters/types.js +21 -0
  6. package/dist/cli/commands/status.js +160 -30
  7. package/dist/compile/collateral.d.ts +86 -2
  8. package/dist/compile/collateral.js +294 -3
  9. package/dist/config/config.d.ts +62 -0
  10. package/dist/config/config.js +157 -2
  11. package/dist/drivers/herdr.d.ts +20 -3
  12. package/dist/drivers/herdr.js +288 -105
  13. package/dist/gates/baseline.d.ts +1 -0
  14. package/dist/gates/baseline.js +91 -13
  15. package/dist/gates/review.d.ts +7 -0
  16. package/dist/gates/review.js +99 -6
  17. package/dist/gates/run-gates.d.ts +9 -0
  18. package/dist/gates/run-gates.js +285 -41
  19. package/dist/run/daemon.d.ts +48 -2
  20. package/dist/run/daemon.js +1417 -315
  21. package/dist/run/journal.d.ts +56 -3
  22. package/dist/run/journal.js +275 -1
  23. package/dist/run/stall.d.ts +35 -1
  24. package/dist/run/stall.js +118 -8
  25. package/dist/tui/cockpit/components.d.ts +30 -1
  26. package/dist/tui/cockpit/components.js +19 -3
  27. package/dist/tui/cockpit/derive.d.ts +29 -2
  28. package/dist/tui/cockpit/derive.js +219 -23
  29. package/dist/tui/cockpit/layout.d.ts +75 -6
  30. package/dist/tui/cockpit/layout.js +97 -19
  31. package/dist/tui/cockpit/live.d.ts +14 -1
  32. package/dist/tui/cockpit/live.js +223 -29
  33. package/dist/tui/cockpit/pointer.d.ts +261 -0
  34. package/dist/tui/cockpit/pointer.js +610 -0
  35. package/dist/tui/cockpit/run-cockpit.d.ts +36 -5
  36. package/dist/tui/cockpit/run-cockpit.js +270 -51
  37. package/package.json +1 -1
@@ -0,0 +1,261 @@
1
+ import { type RunInteractionState } from "./keys.js";
2
+ import { type FrameRegion, type PlannedFrame } from "./layout.js";
3
+ /**
4
+ * The terminal reports no pointer at all until it is asked to, so the parser
5
+ * above reads nothing until these bytes are written. DECSET 1000 turns on normal
6
+ * tracking — presses, releases and the wheel. DECSET 1006 asks for them in SGR
7
+ * encoding: the one grammar `SGR_POINTER_REPORT` reads, and the only one that
8
+ * can state a cell past column 223 at all. DECSET 1003 widens that to motion
9
+ * with no button held — the only way a terminal ever says where the pointer is
10
+ * merely resting, and therefore the whole reason a hover highlight can exist
11
+ * at all. It is asked for last, so the widest tracking mode is the one asked
12
+ * for in the grammar already selected. The request lives beside the parser so a
13
+ * change to what is read cannot leave what is asked for behind.
14
+ */
15
+ export declare const POINTER_TRACKING_ON = "\u001B[?1000h\u001B[?1006h\u001B[?1003h";
16
+ /** The same three modes turned off, in exact reverse of the order they were
17
+ * asked for — a terminal left tracking writes reports into whatever runs after
18
+ * the cockpit exits. */
19
+ export declare const POINTER_TRACKING_OFF = "\u001B[?1003l\u001B[?1006l\u001B[?1000l";
20
+ /**
21
+ * The signals that end a process where nothing else repays the loan: they run
22
+ * no `finally`, unwind no stack and unmount no renderer, so a surface killed by
23
+ * one would leave the operator's terminal reporting a pointer into whatever
24
+ * shell comes next. Listening for them is the only way to hand the modes back.
25
+ *
26
+ * The roster is every catchable POSIX terminator an interactive cockpit is
27
+ * actually killed by — ⌃C, a `kill`, a closed terminal, and ⌃\ — not a
28
+ * shortlist of the three that came to mind. A signal missing from here is a
29
+ * terminal left reporting, so the test that guards it names its own required
30
+ * set rather than reading this one back.
31
+ */
32
+ export declare const POINTER_RELEASE_SIGNALS: readonly ["SIGINT", "SIGTERM", "SIGHUP", "SIGQUIT"];
33
+ /** A cell the pointer can be at, counted from zero like every planned region. */
34
+ export type PointerCell = {
35
+ readonly column: number;
36
+ readonly row: number;
37
+ };
38
+ /**
39
+ * The cell the pointer is resting on, or none. The same reference for as long
40
+ * as it has not moved, so a watcher redraws when the pointer moves and at no
41
+ * other time.
42
+ */
43
+ export declare function pointerRestingCell(): PointerCell | null;
44
+ /** Watch the resting cell. The returned call stops watching. */
45
+ export declare function watchPointerRest(watcher: () => void): () => void;
46
+ /**
47
+ * The rail columns the session dragged the boundary to, or none. The same
48
+ * reference for as long as it has not changed, so a watcher redraws when the
49
+ * drag moves the boundary and at no other time.
50
+ */
51
+ export declare function sessionRailOverride(): number | null;
52
+ /** Watch the session override. The returned call stops watching. */
53
+ export declare function watchSessionRailOverride(watcher: () => void): () => void;
54
+ /**
55
+ * The session boundary the relaunch contract is stated against: the override
56
+ * and any drag in progress are gone, exactly as a new process starts. The
57
+ * production marker is the tracking loan — a fresh borrow is a fresh session.
58
+ */
59
+ export declare function resetSessionRailOverride(): void;
60
+ /** The stream the modes are asked of — a real terminal, or something that is not one. */
61
+ export type PointerTrackingTerminal = {
62
+ readonly isTTY?: boolean;
63
+ readonly write: (bytes: string) => unknown;
64
+ };
65
+ /** The process the loan registers its last-resort repayment with. */
66
+ export type PointerTrackingHost = {
67
+ readonly pid: number;
68
+ readonly on: (signal: NodeJS.Signals, listener: () => void) => unknown;
69
+ readonly off: (signal: NodeJS.Signals, listener: () => void) => unknown;
70
+ readonly kill: (pid: number, signal: NodeJS.Signals) => unknown;
71
+ /** Which signals this host can be killed by at all — `process.platform`. */
72
+ readonly platform?: NodeJS.Platform;
73
+ };
74
+ /**
75
+ * Borrow pointer reporting, and return the one way to repay it.
76
+ *
77
+ * The loan is the whole lifecycle in one expression, so no caller can hold half
78
+ * of it. Only an interactive terminal is asked at all: writing mode requests
79
+ * into a pipe puts escape bytes in a capture rather than a mouse on a surface
80
+ * nobody is pointing at, so the non-tty and CI surfaces carry no enable
81
+ * sequence because none is ever written — not because a later guard strips one.
82
+ *
83
+ * Repayment is idempotent and reachable from every exit: the returned release
84
+ * for an ordinary return, the same release run from a `finally` or a renderer's
85
+ * cleanup for a thrown failure, and the signal listeners registered here for
86
+ * the exits that run neither. A listener repays and then re-raises its own
87
+ * signal with our listener removed, so the process still ends exactly the way
88
+ * the signal meant it to.
89
+ */
90
+ export declare function borrowPointerTracking(terminal: PointerTrackingTerminal, host?: PointerTrackingHost): () => void;
91
+ export type PointerAction = "press" | "release" | "move" | "wheel-up" | "wheel-down";
92
+ /** One reported pointer event, its cell zero-based like every planned region. */
93
+ export type PointerReport = {
94
+ readonly action: PointerAction;
95
+ readonly column: number;
96
+ readonly row: number;
97
+ /**
98
+ * The raw SGR button code the report arrived with. The action alone throws
99
+ * information away that a drag latch cannot survive without: under DECSET
100
+ * 1003 a motion with NO button held reports button 35 — `(button & 3) === 3`
101
+ * — and that no-button motion is the only signal that a release lost
102
+ * outside the window (the pointer let go past the terminal's edge, which
103
+ * sends no release at all) has already happened. Absent only on a report
104
+ * built by hand rather than parsed off the wire; a hand-built move is read
105
+ * as a drag-motion, the reading that cannot end a drag its producer had no
106
+ * way to describe.
107
+ */
108
+ readonly button?: number;
109
+ };
110
+ /** What one chunk of terminal input turned out to be: the reports it carried,
111
+ * and the bytes that were not part of any — the keyboard's own input. */
112
+ export type PointerReadout = {
113
+ /** Keyboard and pointer input in the byte order the terminal delivered it. */
114
+ readonly tokens: readonly PointerInputToken[];
115
+ readonly reports: readonly PointerReport[];
116
+ readonly keys: string;
117
+ };
118
+ export type PointerInputToken = {
119
+ readonly type: "keys";
120
+ readonly bytes: string;
121
+ } | {
122
+ readonly type: "pointer";
123
+ readonly report: PointerReport;
124
+ };
125
+ export type PointerReportReader = {
126
+ (chunk: string): PointerReadout;
127
+ /** Release a prefix that did not receive the bytes needed to become a report. */
128
+ flush(): PointerReadout;
129
+ /** The incomplete report prefix currently withheld from the keyboard. */
130
+ pending(): string;
131
+ };
132
+ /**
133
+ * The pointer reports carried by a chunk of terminal input. Bytes that are not
134
+ * a report are not pointer input and are left for whoever else reads the
135
+ * stream; a torn or malformed sequence simply reports nothing.
136
+ */
137
+ export declare function parsePointerReports(bytes: string): readonly PointerReport[];
138
+ /**
139
+ * A reader over the input stream rather than over one chunk. The terminal
140
+ * writes bytes, not messages: a single report is free to arrive split across
141
+ * chunks, and chunk-at-a-time parsing silently drops every report that lands on
142
+ * a boundary. The reader carries the torn tail into the next chunk and reports
143
+ * only sequences that have completed.
144
+ *
145
+ * It also states what was left — the bytes of that chunk that belonged to no
146
+ * report, including none at all while a torn one is still arriving. Reports and
147
+ * keys share one stream, so this is the only place that can tell them apart:
148
+ * downstream, a whole report is an unnameable escape sequence and half a report
149
+ * is the single character it happens to end on, either of which would be read as
150
+ * a keystroke by whatever scope is live.
151
+ */
152
+ export declare function createPointerReportReader(): PointerReportReader;
153
+ /**
154
+ * The width the key registry resolves at for the bands THIS plan drew. The
155
+ * focus order follows the plan rather than a second reading of the terminal:
156
+ * between 64 and 79 columns the plan draws the rail at a width the key floor
157
+ * alone would deny it, and the click targets and the focus order have to agree
158
+ * about that band or a click would act on a panel the frame does not show.
159
+ */
160
+ export declare function plannedKeyColumns(plan: PlannedFrame): number;
161
+ export type PointerTarget = {
162
+ /** The tightest planned region containing the cell. */
163
+ readonly region: FrameRegion;
164
+ /** The rail's menu row under the cell, when the cell is on one. */
165
+ readonly view?: number;
166
+ /** The body's drawn row under the cell, counted from the planned item region's own first row. */
167
+ readonly row?: number;
168
+ };
169
+ /**
170
+ * What the plan says is under a cell. The rail's view rows are
171
+ * `plan.sidebar.viewRows` — frame rows planFrame itself computed, where the
172
+ * label row was decided — so the menu's shape is looked up rather than
173
+ * reconstructed from `menuRows` out here. The body's item rows are a planned
174
+ * band of their own, so the tightest-region lookup lands on them directly and
175
+ * the first item's offset is the region's own row. The view strip the plan draws
176
+ * instead of a rail below 64 columns is one span with no per-view columns in it,
177
+ * so nothing here invents any: a strip cell resolves to the strip band and no
178
+ * further.
179
+ */
180
+ export declare function resolvePointerTarget(plan: PlannedFrame, cell: {
181
+ readonly column: number;
182
+ readonly row: number;
183
+ }): PointerTarget | undefined;
184
+ /**
185
+ * The focus index a target's band carries at the width the plan drew — the same
186
+ * order the frame paints its focus ring from, so a click can never focus a
187
+ * panel the frame does not show as focusable.
188
+ */
189
+ export declare function pointerFocusPanel(plan: PlannedFrame, target: PointerTarget): number | undefined;
190
+ /**
191
+ * The half of a surface a row hit resolves through: the plan the paint drew,
192
+ * and the identities the rows drawn into it carry.
193
+ */
194
+ export type PointerRowSurface = {
195
+ readonly plan: PlannedFrame;
196
+ /** The identities the body's drawn rows carry, top to bottom. */
197
+ readonly drawnRowIds: readonly string[];
198
+ };
199
+ /**
200
+ * The item a cell acts on — THE resolution, shared by every pointer path.
201
+ * A click reads it to decide what to select, and a hover highlight reads the
202
+ * same call to decide what to mark, so the highlight cannot name a row a click
203
+ * at that cell would miss: there is one answer, not two agreeing ones. A cell
204
+ * the plan does not place on an item row, and an item row the paint drew
205
+ * nothing into, are both nothing here rather than a nearest guess.
206
+ */
207
+ export declare function pointerRowAt(surface: PointerRowSurface, cell: {
208
+ readonly column: number;
209
+ readonly row: number;
210
+ }): string | undefined;
211
+ /** The surface a pointer report acts on: the plan the paint drew, and the rows drawn into it. */
212
+ export type PointerSurface = {
213
+ /** planFrame's own output — the only geometry a hit resolves through. */
214
+ readonly plan: PlannedFrame;
215
+ readonly interaction: RunInteractionState;
216
+ /** The identities the body's drawn rows carry, top to bottom. */
217
+ readonly drawnRowIds: readonly string[];
218
+ /** The rows a key may stand on, in the active view's own order. */
219
+ readonly rowIds: readonly string[];
220
+ };
221
+ /**
222
+ * The transition a pointer report makes, or undefined when nothing owns the
223
+ * cell. A click on a view name is that view's own number key; a click on the
224
+ * row already marked is ⏎; moving between panels is the advertised dive/back
225
+ * grammar; and a wheel is ↑↓ only when the panel under it already owns ↑↓.
226
+ * An off-focus wheel is not an action: borrowing focus or prompt scope and then
227
+ * restoring it would create a frame no advertised key sequence can reach.
228
+ *
229
+ * A drag of the panel boundary is the exception that proves the second law:
230
+ * it is no transition at all. The press landing on the boundary grabs it; each
231
+ * move hands the plan a new input through the session override; the release
232
+ * lets go — and when the release never arrives because the pointer was let go
233
+ * outside the window, the first no-button motion says so in its stead, so no
234
+ * latch outlives the drag it latched. The interaction comes back untouched —
235
+ * the drag re-plans the frame rather than moving anything inside it.
236
+ */
237
+ export declare function applyPointerReport(report: PointerReport, surface: PointerSurface): RunInteractionState | undefined;
238
+ /**
239
+ * The item a hover highlight marks: the one a click at that cell would ACT ON.
240
+ *
241
+ * `pointerRowAt` answers a smaller question — which drawn row the plan places
242
+ * under the cell — and a click is not only that lookup. It is a route: the /
243
+ * prompt applied, focus dived or backed to the panel under the pointer, and only
244
+ * then the row. Any of those may legitimately land somewhere else, the plainest
245
+ * case is the rail marker standing on a view the body is not drawing: the click
246
+ * that dives into content opens the MARKED view and selects no row at all, while
247
+ * the rows under the pointer belong to the view being left behind.
248
+ *
249
+ * So the highlight is not decided by the lookup. It is decided by running the
250
+ * click's own transition and asking what it settled on — the same
251
+ * `pointerTransition` the live report path dispatches through, on the same
252
+ * surface, so an answer these two could disagree about is not expressible. A
253
+ * click that acts on something else, or on nothing, lights nothing up.
254
+ *
255
+ * It reports no rest and returns no state: asking is not pointing and not
256
+ * clicking, so the surface is exactly as it was.
257
+ */
258
+ export declare function pointerHoverRow(surface: PointerSurface, cell: {
259
+ readonly column: number;
260
+ readonly row: number;
261
+ }): string | undefined;