@ucsandman/legcli 0.11.0 → 0.13.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/CHANGELOG.md +213 -0
- package/README.md +95 -65
- package/bin/leg.mjs +123 -14
- package/docs/DECISIONS.md +18 -0
- package/docs/DEMO.md +20 -14
- package/docs/DEVIATIONS.md +1 -0
- package/docs/ERRORS.md +68 -0
- package/docs/ROADMAP-v2.md +50 -5
- package/docs/VOCABULARY.md +27 -0
- package/docs/board-guide.md +529 -96
- package/docs/cli-contracts.md +241 -5
- package/docs/concepts.md +167 -19
- package/docs/configuration.md +65 -1
- package/docs/faq.md +21 -5
- package/docs/getting-started.md +15 -11
- package/docs/redesign-2026-09-17.md +477 -0
- package/docs/screenshots/background-1280.png +0 -0
- package/docs/screenshots/board-400px.png +0 -0
- package/docs/screenshots/board-details-open.png +0 -0
- package/docs/screenshots/board-drawer.png +0 -0
- package/docs/screenshots/board-handoff.png +0 -0
- package/docs/screenshots/board-running.png +0 -0
- package/docs/screenshots/capacity-drawer-1280.png +0 -0
- package/docs/screenshots/floor.png +0 -0
- package/docs/screenshots/new-card-dialog.png +0 -0
- package/docs/screenshots/settings-ladder-1280.png +0 -0
- package/docs/screenshots/terminals-1280.png +0 -0
- package/fixtures/limits/claude/claude-fable-limit.json +11 -0
- package/fixtures/limits/claude/claude-model-limit.json +1 -1
- package/fixtures/limits/claude/claude-session-limit.json +1 -1
- package/fixtures/limits/claude/claude-weekly-limit.json +1 -1
- package/fixtures/live/claude/resume-model-probe.json +20 -0
- package/fixtures/live/claude/usage-oauth.json +87 -0
- package/fixtures/verified.json +1 -1
- package/package.json +3 -2
- package/scripts/board-jump-probe.mjs +335 -0
- package/scripts/seed-fake-cards.mjs +59 -6
- package/scripts/seed-wes-board.mjs +81 -12
- package/src/accounts.mjs +6 -1
- package/src/attach.mjs +378 -93
- package/src/audit.mjs +1 -1
- package/src/board/board.css +203 -11
- package/src/board/board.js +664 -200
- package/src/board/entry.js +343 -0
- package/src/board/floor.html +51 -39
- package/src/board/floor.js +585 -73
- package/src/board/index.html +122 -45
- package/src/board/sessions.js +1569 -141
- package/src/board/strip.js +163 -0
- package/src/buckets.mjs +101 -0
- package/src/cards.mjs +9 -1
- package/src/chain.mjs +13 -0
- package/src/hook.mjs +7 -1
- package/src/ledger.mjs +10 -2
- package/src/models.mjs +265 -0
- package/src/orchestrator.mjs +13 -4
- package/src/preferences.mjs +278 -5
- package/src/scheduler.mjs +24 -1
- package/src/server.mjs +625 -78
- package/src/sessions.mjs +17 -1
- package/src/taps/claude-usage.mjs +107 -3
- package/src/taps/claude.mjs +144 -5
- package/src/taps/codex.mjs +23 -3
- package/src/usage-poll.mjs +260 -0
- package/src/usage.mjs +439 -12
package/src/board/index.html
CHANGED
|
@@ -39,8 +39,20 @@
|
|
|
39
39
|
<p id="verdict-sub"></p>
|
|
40
40
|
</section>
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
<!-- Usage is a property of the work, not a region of its own. The strip is
|
|
43
|
+
one band: a token per login carrying the bucket that will actually stop
|
|
44
|
+
it. The panels are not rewritten, they move intact behind the disclosure
|
|
45
|
+
at the end of the strip, with every gauge, notch and spoken sentence. -->
|
|
46
|
+
<section class="capacity" aria-label="Capacity by login">
|
|
47
|
+
<div class="capacity-strip">
|
|
48
|
+
<div class="cap-tokens" id="capacity-tokens"></div>
|
|
49
|
+
<button type="button" class="btn btn-secondary disclosure cap-open" id="capacity-toggle" aria-expanded="false" aria-controls="capacity-drawer">Capacity and models ></button>
|
|
50
|
+
</div>
|
|
51
|
+
<div class="drawer capacity-drawer" id="capacity-drawer" hidden>
|
|
52
|
+
<section class="logins" id="accounts" aria-label="Logins"></section>
|
|
53
|
+
<p class="head-caption" id="head-caption">Times are local.</p>
|
|
54
|
+
</div>
|
|
55
|
+
</section>
|
|
44
56
|
|
|
45
57
|
<section class="region-terminals" aria-labelledby="terminals-head">
|
|
46
58
|
<div class="section-head">
|
|
@@ -58,6 +70,22 @@
|
|
|
58
70
|
<p class="empty-line" hidden>No terminal is running. Start one in any repo: <code>leg claude</code>, <code>leg codex</code> or <code>leg agy</code>. It appears here within a second of the agent's first turn.</p>
|
|
59
71
|
</section>
|
|
60
72
|
|
|
73
|
+
<!-- C.1: a card is a terminal you are not sitting at. Live cards are rows
|
|
74
|
+
here, directly under Terminals; finished ones fall into the ledger
|
|
75
|
+
cell below instead of piling up as rows. -->
|
|
76
|
+
<section class="region-background" id="background" aria-labelledby="background-head" hidden>
|
|
77
|
+
<div class="section-head">
|
|
78
|
+
<h2 id="background-head">Background</h2>
|
|
79
|
+
<p class="region-meta" role="status" aria-atomic="true"></p>
|
|
80
|
+
</div>
|
|
81
|
+
<!-- the live card rows are `.row`: the four-cell grid whose `.r4
|
|
82
|
+
.row-actions` block is written against the terminal rows, so the two
|
|
83
|
+
row kinds line up. `.card-list` is the gap between them, the same
|
|
84
|
+
container the cards drawer uses. -->
|
|
85
|
+
<div class="card-list" id="background-grid"></div>
|
|
86
|
+
<div id="card-entry" hidden></div>
|
|
87
|
+
</section>
|
|
88
|
+
|
|
61
89
|
<!-- Finished terminals, what landed, and what is queued are all history or
|
|
62
90
|
background. They sit on the ground rather than on a panel, because a
|
|
63
91
|
raised surface here would compete with the terminals that are live. -->
|
|
@@ -151,13 +179,33 @@
|
|
|
151
179
|
first request there is no address above to point at. -->
|
|
152
180
|
<p class="field-help">Stored in this browser's localStorage and sent as a bearer token with every request. Clear the field to sign out.</p>
|
|
153
181
|
</div>
|
|
182
|
+
<!-- The fallback ladder (docs/redesign-2026-09-17.md B.3). A rung is a
|
|
183
|
+
destination, not an agent: claude/opus and claude/sonnet are two
|
|
184
|
+
separate steps down before Leg leaves the login at all. The ids are
|
|
185
|
+
the ones the order editor used, because the same save button, status
|
|
186
|
+
span and list container do the same job for the longer shape. -->
|
|
154
187
|
<fieldset class="default-order" id="default-order" hidden>
|
|
155
|
-
<legend>New terminal handoff
|
|
156
|
-
<p class="field-help">Used by terminals started after you save.</p>
|
|
188
|
+
<legend>New terminal handoff ladder</legend>
|
|
189
|
+
<p class="field-help">Each rung is an agent, a login and a model. Leg walks down from the top and takes the first rung that is open. Used by terminals started after you save; a running terminal keeps the copy it started with, and Details on its row edits that one.</p>
|
|
157
190
|
<div id="default-order-list"></div>
|
|
158
|
-
<
|
|
191
|
+
<div class="ladder-policy" id="ladder-spend"></div>
|
|
192
|
+
<fieldset class="ladder-policy" id="ladder-climb"></fieldset>
|
|
193
|
+
<div class="ladder-policy" id="ladder-reserve"></div>
|
|
194
|
+
<button type="button" class="btn btn-secondary" id="default-order-save">Save ladder</button>
|
|
159
195
|
<span class="field-status" id="default-order-status" aria-live="polite"></span>
|
|
160
196
|
</fieldset>
|
|
197
|
+
<!-- Where a terminal that is waiting on a human says so when the board is
|
|
198
|
+
not the window you are looking at. The tab badge needs no toggle: it
|
|
199
|
+
needs no permission and costs nothing, so it is always on. -->
|
|
200
|
+
<fieldset class="notify" id="notify-settings" hidden>
|
|
201
|
+
<legend>Notifications</legend>
|
|
202
|
+
<p class="field-help">The tab title says <code>(1) Leg</code> and the favicon gains a dot whenever a terminal is waiting on you. That one is always on.</p>
|
|
203
|
+
<label class="notify-toggle" for="notify-terminal"><input type="checkbox" id="notify-terminal"> Terminal toast when a terminal waits on you</label>
|
|
204
|
+
<p class="field-help">Claude Code only, through its Notification hook: the toast reaches the window the agent is already running in.</p>
|
|
205
|
+
<label class="notify-toggle" for="notify-board"><input type="checkbox" id="notify-board"> Browser notification when a terminal waits on you</label>
|
|
206
|
+
<p class="field-help" id="notify-board-help"></p>
|
|
207
|
+
<span class="field-status" id="notify-status" aria-live="polite"></span>
|
|
208
|
+
</fieldset>
|
|
161
209
|
<!-- Who did what, across every terminal and every card. The owner's, like
|
|
162
210
|
the rest of this panel: the trail names repositories and people. It
|
|
163
211
|
loads when asked rather than on every board render. -->
|
|
@@ -196,35 +244,67 @@
|
|
|
196
244
|
<div class="detail-inner" id="session-drawer-content"></div>
|
|
197
245
|
</div>
|
|
198
246
|
|
|
199
|
-
|
|
200
|
-
|
|
247
|
+
<!-- the announced name is the heading on screen: an aria-label here would be a
|
|
248
|
+
second name for one thing, and the one a voice-control user says out loud
|
|
249
|
+
is the one they can read -->
|
|
250
|
+
<dialog id="new-card-dialog" aria-labelledby="new-card-dialog-title">
|
|
251
|
+
<h2 class="dialog-title" id="new-card-dialog-title">More settings</h2>
|
|
201
252
|
<p class="dialog-intro">An agent works without an interactive terminal in a separate git worktree. The default Build workflow stops with changes in that worktree and does not merge them.</p>
|
|
202
253
|
<form id="new-card-form">
|
|
203
254
|
<div class="form-error" id="new-card-error" hidden></div>
|
|
204
255
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
256
|
+
<!-- Two questions, side by side on a wide screen and stacked on a phone:
|
|
257
|
+
WHAT is being asked for (left) and WHO runs it (right). The right
|
|
258
|
+
column opens showing the saved handoff ladder, so the dialog and the
|
|
259
|
+
one-line entry row above it say the same thing until the reader
|
|
260
|
+
changes one of them. -->
|
|
261
|
+
<div class="dialog-cols">
|
|
262
|
+
<div class="dialog-col">
|
|
263
|
+
|
|
264
|
+
<div class="form-row">
|
|
265
|
+
<label for="nc-task">Task</label>
|
|
266
|
+
<span class="field-help">Describe one concrete outcome the agent can finish.</span>
|
|
267
|
+
<textarea id="nc-task" rows="5" required autofocus></textarea>
|
|
268
|
+
</div>
|
|
209
269
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
270
|
+
<div class="form-row">
|
|
271
|
+
<label for="nc-repo-known">Repository</label>
|
|
272
|
+
<select id="nc-repo-known"></select>
|
|
273
|
+
<label for="nc-repo" class="sub-label">Path</label>
|
|
274
|
+
<input type="text" id="nc-repo" required autocomplete="off" spellcheck="false">
|
|
275
|
+
</div>
|
|
215
276
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
277
|
+
<div class="form-row">
|
|
278
|
+
<label for="nc-trunk">Branch to cut from</label>
|
|
279
|
+
<input type="text" id="nc-trunk" value="main" autocomplete="off" spellcheck="false">
|
|
280
|
+
<span class="field-help" id="nc-trunk-help">The card works in its own checkout cut from this branch.</span>
|
|
281
|
+
</div>
|
|
282
|
+
|
|
283
|
+
<div class="form-row">
|
|
284
|
+
<label for="nc-queue">
|
|
285
|
+
<input type="checkbox" id="nc-queue" checked>
|
|
286
|
+
Run now
|
|
287
|
+
</label>
|
|
288
|
+
<span class="field-help">Turn this off to save a draft in Backlog.</span>
|
|
289
|
+
</div>
|
|
290
|
+
|
|
291
|
+
</div>
|
|
292
|
+
<div class="dialog-col">
|
|
293
|
+
|
|
294
|
+
<div class="form-row">
|
|
295
|
+
<span class="form-label" id="nc-chain-label">Who runs it</span>
|
|
296
|
+
<span class="field-help">Leg starts at the top and takes the next row only when the row above it cannot continue. Each row is a provider and one of its models.</span>
|
|
297
|
+
<div id="nc-chain-rows" role="group" aria-labelledby="nc-chain-label"></div>
|
|
298
|
+
<button type="button" class="btn btn-secondary" id="nc-add-row">Add a fallback</button>
|
|
299
|
+
<span class="field-help" id="nc-fallback-summary"></span>
|
|
300
|
+
<label for="nc-save-ladder" class="notify-toggle">
|
|
301
|
+
<input type="checkbox" id="nc-save-ladder">
|
|
302
|
+
Save as my default ladder
|
|
303
|
+
</label>
|
|
304
|
+
<span class="field-help">Writes these rows to Settings, so the one-line entry row and every new terminal use them too.</span>
|
|
305
|
+
</div>
|
|
221
306
|
|
|
222
|
-
|
|
223
|
-
<label for="nc-queue">
|
|
224
|
-
<input type="checkbox" id="nc-queue" checked>
|
|
225
|
-
Run now
|
|
226
|
-
</label>
|
|
227
|
-
<span class="field-help">Turn this off to save a draft in Backlog.</span>
|
|
307
|
+
</div>
|
|
228
308
|
</div>
|
|
229
309
|
|
|
230
310
|
<details class="advanced-options">
|
|
@@ -241,21 +321,9 @@
|
|
|
241
321
|
<textarea id="nc-custom-pipeline" rows="4" hidden aria-label="Custom workflow JSON" placeholder='[{"name":"build","kind":"agent"}]'></textarea>
|
|
242
322
|
</div>
|
|
243
323
|
|
|
244
|
-
<div class="form-row">
|
|
245
|
-
<label>First-agent permissions and limits</label>
|
|
246
|
-
<div id="nc-first-controls"></div>
|
|
247
|
-
</div>
|
|
248
|
-
|
|
249
|
-
<div class="form-row">
|
|
250
|
-
<label>Fallback agents</label>
|
|
251
|
-
<span class="field-help">Leg tries each row in order only when the agent before it cannot continue.</span>
|
|
252
|
-
<div id="nc-chain-rows"></div>
|
|
253
|
-
<button type="button" class="btn btn-secondary" id="nc-add-row">Add fallback agent</button>
|
|
254
|
-
</div>
|
|
255
|
-
|
|
256
324
|
<div class="form-row">
|
|
257
325
|
<label for="nc-test-adapter">Scripted first agent (test/demo only)</label>
|
|
258
|
-
<select id="nc-test-adapter"><option value="">Use the real first
|
|
326
|
+
<select id="nc-test-adapter"><option value="">Use the real first row above</option></select>
|
|
259
327
|
</div>
|
|
260
328
|
|
|
261
329
|
<div class="form-row">
|
|
@@ -264,11 +332,6 @@
|
|
|
264
332
|
<input type="text" id="nc-leases">
|
|
265
333
|
</div>
|
|
266
334
|
|
|
267
|
-
<div class="form-row">
|
|
268
|
-
<label for="nc-trunk">Trunk branch</label>
|
|
269
|
-
<input type="text" id="nc-trunk" value="main">
|
|
270
|
-
</div>
|
|
271
|
-
|
|
272
335
|
<div class="form-row">
|
|
273
336
|
<label for="nc-land-mode">Merge method</label>
|
|
274
337
|
<select id="nc-land-mode">
|
|
@@ -296,8 +359,22 @@
|
|
|
296
359
|
</form>
|
|
297
360
|
</dialog>
|
|
298
361
|
|
|
362
|
+
<!-- D14: every binding clicks a button that is already on a row, so this map is
|
|
363
|
+
the list of those buttons and nothing else can drift from it. sessions.js
|
|
364
|
+
fills it from the same table the key handler reads. -->
|
|
365
|
+
<div class="keymap" id="keymap" role="dialog" aria-label="Keyboard shortcuts" hidden>
|
|
366
|
+
<h3 class="drawer-head">Keyboard</h3>
|
|
367
|
+
<dl class="keymap-list" id="keymap-list"></dl>
|
|
368
|
+
<button type="button" class="btn btn-secondary" id="keymap-close">Close</button>
|
|
369
|
+
</div>
|
|
370
|
+
|
|
299
371
|
<div class="sysmsg" id="toast" aria-live="polite"></div>
|
|
300
372
|
|
|
373
|
+
<!-- strip.js and entry.js are shared with /floor and are read at load by the
|
|
374
|
+
two files under them (the capacity tokens, the one-line entry), so they
|
|
375
|
+
are first: deferred scripts run in document order. -->
|
|
376
|
+
<script src="strip.js" defer></script>
|
|
377
|
+
<script src="entry.js" defer></script>
|
|
301
378
|
<script src="board.js" defer></script>
|
|
302
379
|
<script src="sessions.js" defer></script>
|
|
303
380
|
<script src="history.js" defer></script>
|