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.
- package/dist/adapters/claude-code.d.ts +1 -0
- package/dist/adapters/claude-code.js +57 -1
- package/dist/adapters/fake.js +9 -0
- package/dist/adapters/types.d.ts +3 -0
- package/dist/adapters/types.js +21 -0
- package/dist/cli/commands/status.js +160 -30
- package/dist/compile/collateral.d.ts +86 -2
- package/dist/compile/collateral.js +294 -3
- package/dist/config/config.d.ts +62 -0
- package/dist/config/config.js +157 -2
- package/dist/drivers/herdr.d.ts +20 -3
- package/dist/drivers/herdr.js +288 -105
- package/dist/gates/baseline.d.ts +1 -0
- package/dist/gates/baseline.js +91 -13
- package/dist/gates/review.d.ts +7 -0
- package/dist/gates/review.js +99 -6
- package/dist/gates/run-gates.d.ts +9 -0
- package/dist/gates/run-gates.js +285 -41
- package/dist/run/daemon.d.ts +48 -2
- package/dist/run/daemon.js +1417 -315
- package/dist/run/journal.d.ts +56 -3
- package/dist/run/journal.js +275 -1
- package/dist/run/stall.d.ts +35 -1
- package/dist/run/stall.js +118 -8
- package/dist/tui/cockpit/components.d.ts +30 -1
- package/dist/tui/cockpit/components.js +19 -3
- package/dist/tui/cockpit/derive.d.ts +29 -2
- package/dist/tui/cockpit/derive.js +219 -23
- package/dist/tui/cockpit/layout.d.ts +75 -6
- package/dist/tui/cockpit/layout.js +97 -19
- package/dist/tui/cockpit/live.d.ts +14 -1
- package/dist/tui/cockpit/live.js +223 -29
- package/dist/tui/cockpit/pointer.d.ts +261 -0
- package/dist/tui/cockpit/pointer.js +610 -0
- package/dist/tui/cockpit/run-cockpit.d.ts +36 -5
- package/dist/tui/cockpit/run-cockpit.js +270 -51
- 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;
|