@ashlr/hub 3.8.0 → 3.9.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 +201 -0
- package/dist/build-identity.json +2 -2
- package/dist/cli/resource-profile.js +95 -21
- package/dist/cli/resource-profile.js.map +1 -1
- package/dist/core/resources/native-profile.d.ts +56 -0
- package/dist/core/resources/native-profile.js +368 -6
- package/dist/core/resources/native-profile.js.map +1 -1
- package/dist/core/run/model-catalog.js +8 -1
- package/dist/core/run/model-catalog.js.map +1 -1
- package/dist/core/universe/builtins/preparation/manifest.json +1 -1
- package/dist/core/universe/builtins/preparation/preparation-bridge.mjs +9 -2
- package/dist/core/universe/builtins/preparation/preparation-verification-fixtures.mjs +8 -1
- package/dist/core/verse/adapters/claude.d.ts +49 -2
- package/dist/core/verse/adapters/claude.js +317 -56
- package/dist/core/verse/adapters/claude.js.map +1 -1
- package/dist/core/verse/adapters/codex.d.ts +81 -5
- package/dist/core/verse/adapters/codex.js +409 -47
- package/dist/core/verse/adapters/codex.js.map +1 -1
- package/dist/core/verse/adapters/grok.d.ts +13 -1
- package/dist/core/verse/adapters/grok.js +28 -2
- package/dist/core/verse/adapters/grok.js.map +1 -1
- package/dist/core/verse/adapters/index.d.ts +32 -0
- package/dist/core/verse/adapters/index.js +2 -0
- package/dist/core/verse/adapters/index.js.map +1 -1
- package/dist/core/verse/codex-rollout.d.ts +284 -0
- package/dist/core/verse/codex-rollout.js +786 -0
- package/dist/core/verse/codex-rollout.js.map +1 -0
- package/dist/core/verse/context-fit.d.ts +63 -0
- package/dist/core/verse/context-fit.js +355 -0
- package/dist/core/verse/context-fit.js.map +1 -0
- package/dist/core/verse/context-math.d.ts +215 -0
- package/dist/core/verse/context-math.js +365 -0
- package/dist/core/verse/context-math.js.map +1 -0
- package/dist/core/verse/local-models.d.ts +137 -1
- package/dist/core/verse/local-models.js +209 -5
- package/dist/core/verse/local-models.js.map +1 -1
- package/dist/core/verse/model-windows.d.ts +217 -0
- package/dist/core/verse/model-windows.js +616 -0
- package/dist/core/verse/model-windows.js.map +1 -0
- package/dist/core/verse/preferences.d.ts +123 -0
- package/dist/core/verse/preferences.js +403 -0
- package/dist/core/verse/preferences.js.map +1 -0
- package/dist/core/verse/project-memory.d.ts +112 -0
- package/dist/core/verse/project-memory.js +295 -0
- package/dist/core/verse/project-memory.js.map +1 -0
- package/dist/core/verse/seats.d.ts +106 -4
- package/dist/core/verse/seats.js +291 -89
- package/dist/core/verse/seats.js.map +1 -1
- package/dist/core/verse/session-engine.d.ts +76 -2
- package/dist/core/verse/session-engine.js +684 -63
- package/dist/core/verse/session-engine.js.map +1 -1
- package/dist/core/verse/session-handoff.d.ts +94 -0
- package/dist/core/verse/session-handoff.js +551 -0
- package/dist/core/verse/session-handoff.js.map +1 -0
- package/dist/core/verse/session-search.d.ts +63 -0
- package/dist/core/verse/session-search.js +213 -0
- package/dist/core/verse/session-search.js.map +1 -0
- package/dist/core/verse/session-store.d.ts +16 -2
- package/dist/core/verse/session-store.js +80 -6
- package/dist/core/verse/session-store.js.map +1 -1
- package/dist/core/verse/types.d.ts +333 -1
- package/dist/core/verse/types.js +54 -2
- package/dist/core/verse/types.js.map +1 -1
- package/dist/core/verse/verse-api.d.ts +40 -5
- package/dist/core/verse/verse-api.js +724 -25
- package/dist/core/verse/verse-api.js.map +1 -1
- package/dist/core/web/api.d.ts +14 -4
- package/dist/core/web/api.js +26 -11
- package/dist/core/web/api.js.map +1 -1
- package/dist/core/web/public/next/assets/{App-BsbJFA2j.js → App-XURmiAAp.js} +5 -5
- package/dist/core/web/public/next/assets/{App-BsbJFA2j.js.map → App-XURmiAAp.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ApprovalsSection-2CCSoBTJ.js → ApprovalsSection-BriUzoZc.js} +2 -2
- package/dist/core/web/public/next/assets/{ApprovalsSection-2CCSoBTJ.js.map → ApprovalsSection-BriUzoZc.js.map} +1 -1
- package/dist/core/web/public/next/assets/AutonomySection-C4GBsQVc.js +2 -0
- package/dist/core/web/public/next/assets/{AutonomySection-yeNNUPur.js.map → AutonomySection-C4GBsQVc.js.map} +1 -1
- package/dist/core/web/public/next/assets/ChatSection-BpOBOUvg.css +1 -0
- package/dist/core/web/public/next/assets/ChatSection-hlgPBRco.js +84 -0
- package/dist/core/web/public/next/assets/ChatSection-hlgPBRco.js.map +1 -0
- package/dist/core/web/public/next/assets/ConfirmDialog-BdQYI-Ng.js +2 -0
- package/dist/core/web/public/next/assets/ConfirmDialog-BdQYI-Ng.js.map +1 -0
- package/dist/core/web/public/next/assets/{Dialog-nK15L1M0.js → Dialog-BxdIfmFH.js} +2 -2
- package/dist/core/web/public/next/assets/{Dialog-nK15L1M0.js.map → Dialog-BxdIfmFH.js.map} +1 -1
- package/dist/core/web/public/next/assets/{DiffViewer-D369eZe8.js → DiffViewer-DmeRWuc4.js} +2 -2
- package/dist/core/web/public/next/assets/{DiffViewer-D369eZe8.js.map → DiffViewer-DmeRWuc4.js.map} +1 -1
- package/dist/core/web/public/next/assets/{McpSection-DVgiSYG1.js → McpSection-q34T7Tho.js} +2 -2
- package/dist/core/web/public/next/assets/{McpSection-DVgiSYG1.js.map → McpSection-q34T7Tho.js.map} +1 -1
- package/dist/core/web/public/next/assets/{MutationTokenDialog-B9I4PAcp.js → MutationTokenDialog-CFAkwOEt.js} +2 -2
- package/dist/core/web/public/next/assets/{MutationTokenDialog-B9I4PAcp.js.map → MutationTokenDialog-CFAkwOEt.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-z6tJj3s9.js → ResourcePoolConsoleApp-DHc8GFOY.js} +4 -4
- package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-z6tJj3s9.js.map → ResourcePoolConsoleApp-DHc8GFOY.js.map} +1 -1
- package/dist/core/web/public/next/assets/{RouteErrorBoundary-OSajL45F.js → RouteErrorBoundary-ZL9F4qUn.js} +2 -2
- package/dist/core/web/public/next/assets/{RouteErrorBoundary-OSajL45F.js.map → RouteErrorBoundary-ZL9F4qUn.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Meter-CLcr-4wS.css → Segmented-8cf0Fypn.css} +1 -1
- package/dist/core/web/public/next/assets/{Meter-Cmo1pLbk.js → Segmented-DbRjVye3.js} +2 -2
- package/dist/core/web/public/next/assets/Segmented-DbRjVye3.js.map +1 -0
- package/dist/core/web/public/next/assets/SettingsSection-nJGGGYqv.js +2 -0
- package/dist/core/web/public/next/assets/{SettingsSection-B3YH2Npi.js.map → SettingsSection-nJGGGYqv.js.map} +1 -1
- package/dist/core/web/public/next/assets/UniverseConsoleApp-6GJydgo4.js +2 -0
- package/dist/core/web/public/next/assets/{UniverseConsoleApp-wEKIzl1M.js.map → UniverseConsoleApp-6GJydgo4.js.map} +1 -1
- package/dist/core/web/public/next/assets/{UniverseView-CQVpJqqI.js → UniverseView-DLDtNYL8.js} +2 -2
- package/dist/core/web/public/next/assets/{UniverseView-CQVpJqqI.js.map → UniverseView-DLDtNYL8.js.map} +1 -1
- package/dist/core/web/public/next/assets/UsageSection-Cf9d9iFH.js +2 -0
- package/dist/core/web/public/next/assets/UsageSection-Cf9d9iFH.js.map +1 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-DsdKQoTH.css +1 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-y0uOHixd.js +3 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-y0uOHixd.js.map +1 -0
- package/dist/core/web/public/next/assets/{charts-BopViIha.js → charts-CVooqJWN.js} +2 -2
- package/dist/core/web/public/next/assets/{charts-BopViIha.js.map → charts-CVooqJWN.js.map} +1 -1
- package/dist/core/web/public/next/assets/context-model-Bqv8DVuH.js +2 -0
- package/dist/core/web/public/next/assets/context-model-Bqv8DVuH.js.map +1 -0
- package/dist/core/web/public/next/assets/global-eaY9GyX3.js +2 -0
- package/dist/core/web/public/next/assets/global-eaY9GyX3.js.map +1 -0
- package/dist/core/web/public/next/assets/{icons-L06pQH6j.js → icons-vex8rclC.js} +2 -2
- package/dist/core/web/public/next/assets/{icons-L06pQH6j.js.map → icons-vex8rclC.js.map} +1 -1
- package/dist/core/web/public/next/assets/{index-CXgVQHek.js → index-D2Eik-zt.js} +3 -3
- package/dist/core/web/public/next/assets/{index-CXgVQHek.js.map → index-D2Eik-zt.js.map} +1 -1
- package/dist/core/web/public/next/assets/{queries-D3sSlan1.js → queries-bAYU0VNy.js} +2 -2
- package/dist/core/web/public/next/assets/{queries-D3sSlan1.js.map → queries-bAYU0VNy.js.map} +1 -1
- package/dist/core/web/public/next/assets/use-guarded-action-C7QrP7Yp.js +2 -0
- package/dist/core/web/public/next/assets/{use-guarded-action-BxfJ9E-n.js.map → use-guarded-action-C7QrP7Yp.js.map} +1 -1
- package/dist/core/web/public/next/assets/verse-model-TfDk9cky.js +2 -0
- package/dist/core/web/public/next/assets/verse-model-TfDk9cky.js.map +1 -0
- package/dist/core/web/public/next/assets/{workspace-model-v0a1gl-C.js → workspace-model-CHol5RVp.js} +2 -2
- package/dist/core/web/public/next/assets/{workspace-model-v0a1gl-C.js.map → workspace-model-CHol5RVp.js.map} +1 -1
- package/dist/core/web/public/next/index.html +1 -1
- package/dist/release-dependency-inventory.json +1 -1
- package/docs/README.md +1 -0
- package/package.json +1 -1
- package/dist/core/web/public/next/assets/AutonomySection-yeNNUPur.js +0 -2
- package/dist/core/web/public/next/assets/ChatSection-BfnLe5dT.css +0 -1
- package/dist/core/web/public/next/assets/ChatSection-DwDDnCZQ.js +0 -80
- package/dist/core/web/public/next/assets/ChatSection-DwDDnCZQ.js.map +0 -1
- package/dist/core/web/public/next/assets/ConfirmDialog-C363ty_c.js +0 -2
- package/dist/core/web/public/next/assets/ConfirmDialog-C363ty_c.js.map +0 -1
- package/dist/core/web/public/next/assets/Meter-Cmo1pLbk.js.map +0 -1
- package/dist/core/web/public/next/assets/SettingsSection-B3YH2Npi.js +0 -2
- package/dist/core/web/public/next/assets/UniverseConsoleApp-wEKIzl1M.js +0 -2
- package/dist/core/web/public/next/assets/UsageSection-dToBThXe.js +0 -2
- package/dist/core/web/public/next/assets/UsageSection-dToBThXe.js.map +0 -1
- package/dist/core/web/public/next/assets/VerseConsoleApp-CMkCizvL.css +0 -1
- package/dist/core/web/public/next/assets/VerseConsoleApp-DHU32JCQ.js +0 -3
- package/dist/core/web/public/next/assets/VerseConsoleApp-DHU32JCQ.js.map +0 -1
- package/dist/core/web/public/next/assets/global-DMWakEhP.js +0 -2
- package/dist/core/web/public/next/assets/global-DMWakEhP.js.map +0 -1
- package/dist/core/web/public/next/assets/use-guarded-action-BxfJ9E-n.js +0 -2
- package/dist/core/web/public/next/assets/verse-model-CvtK6vP6.js +0 -2
- package/dist/core/web/public/next/assets/verse-model-CvtK6vP6.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -339,6 +339,207 @@ superseded, not a setup procedure. Use [runtime activation authority](docs/RUNTI
|
|
|
339
339
|
and the [current architecture boundary](docs/ARCHITECTURE.md#legacy-fleet-activation-boundary).
|
|
340
340
|
Neither the historical record nor a successful test activates a resident fleet.
|
|
341
341
|
|
|
342
|
+
## [3.9.0] — 2026-09-24 UTC — the context meter tells the truth, and long sessions have somewhere to go
|
|
343
|
+
|
|
344
|
+
The Verse context meter was wrong on every engine, in a different way each time,
|
|
345
|
+
and a session that was filling up had nowhere to go but a cold new chat. The
|
|
346
|
+
numbers below were read from the pinned CLI binaries, each seat's own model
|
|
347
|
+
catalog and every September Codex rollout on this machine; no paid model was
|
|
348
|
+
prompted to produce them. `docs/VERSE-CONTEXT.md` is the new authority for all of it.
|
|
349
|
+
|
|
350
|
+
### Behaviour change: new Claude chats compact at ≈367k, existing ones keep ≈967k
|
|
351
|
+
|
|
352
|
+
- **New Claude chats on a 1M model start in Standard** and compact at ≈367k
|
|
353
|
+
(`--autocompact 400000`), not near 967k as every Claude chat did before.
|
|
354
|
+
Expansive — the old full window — is one click away, and can be a seat's default.
|
|
355
|
+
- **Chats created before 3.9 keep the window they ran with.** A Claude chat with
|
|
356
|
+
no recorded mode is marked **Expansive** the first time 3.9 loads it and runs
|
|
357
|
+
with `--autocompact auto`, exactly as before, so upgrading compacts nothing and
|
|
358
|
+
spends nothing. Codex, Grok, local and 200k-Claude chats from before 3.9 stay
|
|
359
|
+
Standard, which is what they already ran at.
|
|
360
|
+
- **Switching a chat to Standard above ≈367k compacts it on the next turn.** The
|
|
361
|
+
CLI then summarizes the whole context — on a paid seat that spends usage — and
|
|
362
|
+
early turns survive only as that summary. The same holds for a Codex chat
|
|
363
|
+
switched back from Expansive above 244.8k. Switching to Expansive is always
|
|
364
|
+
free. The mode menu warns before you switch.
|
|
365
|
+
|
|
366
|
+
### Windows read from the CLIs, not assumed
|
|
367
|
+
|
|
368
|
+
- **Claude.** Six of the eight models run a **1M** window and compact near
|
|
369
|
+
967k; Verse showed 200k for all of them, so a Fable session went red at 180k
|
|
370
|
+
and then sat at 100 % while it grew to 967k — hiding exactly the range where
|
|
371
|
+
every turn is most expensive. Each model now carries its real window, and the
|
|
372
|
+
window the CLI reports at runtime (`result.modelUsage`) wins, which also
|
|
373
|
+
catches the CLI dropping a session to 200k when long-context credit runs out.
|
|
374
|
+
- **"Opus 5.5" was running Opus 5.** Verse offered `claude-opus-5.5`; Claude
|
|
375
|
+
Code's id parser rejects the dotted suffix and falls back to a substring match
|
|
376
|
+
on `claude-opus-5`. The real id is `claude-opus-5-5`, which needs Claude Code
|
|
377
|
+
2.1.280 — and the claude-a seat is pinned to 2.1.257. Opus 5.5 is now listed on
|
|
378
|
+
that seat **disabled, with the reason** and the fix
|
|
379
|
+
(`ashlr resources profile repin`, new in this release — below), rather than
|
|
380
|
+
silently running a different model. Old sessions keep their recorded id, but
|
|
381
|
+
their turns now ask for the real model, so on a seat that cannot run it the
|
|
382
|
+
turn is refused up front (409 `VERSE_MODEL_UNAVAILABLE`, with the reason)
|
|
383
|
+
instead of starting a CLI that would reject the id. A client that still sends
|
|
384
|
+
`claude-opus-5.5` when creating a chat gets `claude-opus-5-5`.
|
|
385
|
+
- **Codex.** The CLI measures against 95 % of the window — 258,400, reported by
|
|
386
|
+
every one of 151,715 rollout readings — and compacts near 244,800. Occupancy was
|
|
387
|
+
the turn's *summed* input — a median 28.8× the real last-call prompt across 260
|
|
388
|
+
recent turns — so the meter sat red on almost every turn. It now comes from the
|
|
389
|
+
seat's own rollout — the last call's `last_token_usage.total_tokens`, the
|
|
390
|
+
figure Codex itself compacts against, and the window the rollout reports —
|
|
391
|
+
read every 2 s during a turn; until that is readable the figure is marked `≤`. The rollout also fixes per-turn usage: on `exec resume`,
|
|
392
|
+
Codex's reported usage is the whole thread's running total, which Verse would
|
|
393
|
+
have added again every turn (no Verse codex chat had run yet, so no stored
|
|
394
|
+
total is wrong). Models come from each seat's own catalog, so hidden slugs are
|
|
395
|
+
no longer offered.
|
|
396
|
+
- **Grok** is 500k compacting at 400k, not 256k — the meter read twice the real
|
|
397
|
+
fill. Labels come from the catalog ("Grok 4.7 Fast"), and only its `.info`
|
|
398
|
+
entries are read: the same file carries a per-model `api_key` field. Like
|
|
399
|
+
Claude, the window Grok reports at runtime wins.
|
|
400
|
+
- **Local.** Claude Code assumes 200k for a model it does not know, so a local
|
|
401
|
+
seat never compacted before a 64k runner overflowed. Verse now tells it the
|
|
402
|
+
real window (`CLAUDE_CODE_MAX_CONTEXT_TOKENS`), resolves that window from what
|
|
403
|
+
the runner actually serves (llama-server's per-slot window on that lane,
|
|
404
|
+
Ollama's own server default for unpinned tags — preferred over whatever
|
|
405
|
+
context a resident runner was loaded with, since another app may have loaded
|
|
406
|
+
it at 8k), and parses `-ctx64k` tags, which the old suffix pattern missed.
|
|
407
|
+
Before every local turn the chat's stored window is refreshed from live
|
|
408
|
+
discovery, so the window the CLI is told and the one the meter shows are the
|
|
409
|
+
same, current number. Tags under a 56k window are listed disabled with the
|
|
410
|
+
reason: after Claude Code's 33k reserve and its ~15k base prompt they would
|
|
411
|
+
compact on every turn. The fleet's model catalog no longer
|
|
412
|
+
tags the 64k local coder `long-context` (a capability defined as ≥ 100k), which
|
|
413
|
+
had routed long-context work to a model that would overflow.
|
|
414
|
+
- Readings are stored **unclamped**: an overflow is information, and the old
|
|
415
|
+
clamp erased it on disk.
|
|
416
|
+
|
|
417
|
+
### Compaction you can see
|
|
418
|
+
|
|
419
|
+
Native compactions become persisted `compaction` events — Claude and Grok from
|
|
420
|
+
`compact_boundary`, Codex from its rollout, sized from the readings just before
|
|
421
|
+
and after it — with a transcript divider ("Auto-compacted 967k → 19k in 1m 58s")
|
|
422
|
+
and a per-session count. The meter draws the whole window with a tick at the
|
|
423
|
+
compaction point and warns at 80 % / 95 % of **that point**. The old fixed
|
|
424
|
+
70 / 90 % of the window turned red only after Grok and Codex had already
|
|
425
|
+
compacted.
|
|
426
|
+
|
|
427
|
+
**Compact now** — in the chip beside the meter on every Claude and local session
|
|
428
|
+
(a "Context" chip where the model has no second mode), and in the handoff banner — sends `/compact` as an ordinary turn,
|
|
429
|
+
through the same gate as every turn, and the divider reads "Compacted on
|
|
430
|
+
request". It was verified headless on a local seat, where it is free but slow
|
|
431
|
+
(about 2½ minutes for a 15k context on a 27B model). **On a paid seat it spends
|
|
432
|
+
usage**: the CLI reads the whole context to write its summary.
|
|
433
|
+
|
|
434
|
+
### Standard and expansive context
|
|
435
|
+
|
|
436
|
+
A new chat on any Claude 1M model now compacts at ≈367k by default
|
|
437
|
+
(`--autocompact 400000`) instead of ≈967k (chats from before 3.9 keep ≈967k —
|
|
438
|
+
above). Each turn re-sends the whole conversation, and long-context
|
|
439
|
+
recall degrades with length on every published benchmark, so a session held
|
|
440
|
+
near 900k re-reads about 2.3× what one held under 400k does. **Expansive** mode
|
|
441
|
+
restores the full window — and on GPT-6 / GPT-5.6 raises Codex to its 872k
|
|
442
|
+
catalog maximum, passing `model_context_window` and
|
|
443
|
+
`model_auto_compact_token_limit` together (one without the other breaks Codex's
|
|
444
|
+
compaction). The mode is per session, applies from the next turn, can be a
|
|
445
|
+
seat's default, and exists only where it is real. Verse may suggest it; it never
|
|
446
|
+
switches it on. The menu's cost note is the ratio of the two compaction points
|
|
447
|
+
(≈2.6× on Claude, ≈3.2× on Codex). On Codex every Expansive surface also says
|
|
448
|
+
that GPT-5.6 requests above 272k reportedly count about 2× against plan limits
|
|
449
|
+
(one secondary source; GPT-6 Astra reportedly exempt) — if that holds, a turn
|
|
450
|
+
near the expansive limit counts nearer 6× a standard one.
|
|
451
|
+
|
|
452
|
+
### Continue in a fresh chat
|
|
453
|
+
|
|
454
|
+
A banner appears when a session nears its compaction point, has compacted twice,
|
|
455
|
+
or has sat idle past the prompt cache's lifetime with a large context. It builds
|
|
456
|
+
a handoff note from the session's own log — goal, latest asks, state, files,
|
|
457
|
+
commands, errors, `git diff --stat` per root — with no model call, lets you edit
|
|
458
|
+
it and pick any seat (a Claude chat can continue on Codex), creates the new
|
|
459
|
+
session for free and leaves the note in its composer. Nothing is sent until you
|
|
460
|
+
press send.
|
|
461
|
+
|
|
462
|
+
### Shared memory, fit, search, efficiency
|
|
463
|
+
|
|
464
|
+
- **Project memory:** one private directory per project under
|
|
465
|
+
`~/.ashlr/verse/memory/`, shared by every seat, with a fixed instruction block
|
|
466
|
+
that stays byte-identical across turns so the prompt cache survives. On by
|
|
467
|
+
default, per-project opt-out, editable from the Resources panel. Claude and
|
|
468
|
+
local seats get the directory with `--add-dir` and the block with
|
|
469
|
+
`--append-system-prompt`; Codex through `-c` overrides (a writable root and
|
|
470
|
+
`developer_instructions`), since `exec resume` takes no `--add-dir`. Grok, whose
|
|
471
|
+
CLI can be granted nothing beyond its working directory, gets a read-only
|
|
472
|
+
snapshot through `--rules`. **It is not free on a paid seat:** the block (up
|
|
473
|
+
to 6 KB) rides in the system prompt of every turn of every new session —
|
|
474
|
+
cached after the first turn, but cached tokens still count — and it asks the
|
|
475
|
+
agent to read and update `MEMORY.md`, which is extra tool calls and output.
|
|
476
|
+
Turn it off per project, or for every project, in the Resources panel.
|
|
477
|
+
The editor shows the sanitized copy the API serves and says so; a save that
|
|
478
|
+
would write `[REDACTED]` placeholders over real values is refused.
|
|
479
|
+
- **Context fit:** per-model verdicts — fits, tight, needs expansive, or split —
|
|
480
|
+
for a folder or workspace, from `git ls-files` sizes, plus each engine's base
|
|
481
|
+
prompt (local 15k, measured; Claude 25k, Codex 15k, Grok 20k, estimated), so
|
|
482
|
+
a handoff note fits the 64k local seat while a whole repository shows split.
|
|
483
|
+
- **Session search** across past chats from the sidebar: a bounded keyword scan
|
|
484
|
+
of Verse's own session store (newest 200 sessions, 20 MB of message text), with
|
|
485
|
+
no index and no embeddings.
|
|
486
|
+
- **Efficiency:** cache-hit ratio, context per turn, compactions and an
|
|
487
|
+
idle-cache warning, computed in the browser.
|
|
488
|
+
|
|
489
|
+
Memory aside, all of it is deterministic and spends nothing: the handoff
|
|
490
|
+
preview, context fit, search and the efficiency stats make no model call. The
|
|
491
|
+
only model calls remain the turns you send, through the same local-only-gated
|
|
492
|
+
chokepoint as before.
|
|
493
|
+
|
|
494
|
+
### Re-pin a seat to a newer CLI
|
|
495
|
+
|
|
496
|
+
`ashlr resources profile repin --directory <profile> --executable <binary>`
|
|
497
|
+
points an existing prepared native profile at another CLI binary — the fix the
|
|
498
|
+
claude-a seat's note names for Opus 5.5. It changes only the pinned executable
|
|
499
|
+
(the launcher's one `const profile=` line and `profile.json`) and refuses a
|
|
500
|
+
profile that is not unmodified `prepare` output. `--dry-run` checks everything
|
|
501
|
+
and writes nothing. A real repin first saves `launcher.mjs`, `profile.json` and
|
|
502
|
+
`command.json` as `.prev` files — one rollback set; restoring all three restores
|
|
503
|
+
the old pin. Re-running an interrupted repin finishes it, repinning to the
|
|
504
|
+
current binary reports `unchanged`, and failures say whether the profile
|
|
505
|
+
changed. It does not check sign-in: run `ashlr resources launcher check`
|
|
506
|
+
afterwards. The command ships in the built CLI, so it needs `npm run build` in a
|
|
507
|
+
source checkout.
|
|
508
|
+
|
|
509
|
+
### For API clients
|
|
510
|
+
|
|
511
|
+
- New routes under `/api/verse`: `POST /sessions/:id/context-mode`,
|
|
512
|
+
`POST /sessions/:id/handoff-preview`, `GET`/`POST /preferences`,
|
|
513
|
+
`GET /context-fit`, `GET /search`, `GET`/`POST /memory`. None starts a model
|
|
514
|
+
call. `handoff-preview` is a POST because it runs `git`, so like every POST it
|
|
515
|
+
answers 404 on a read-only server.
|
|
516
|
+
- `POST /sessions` is now strict: an unknown key is a 400, and `workspaceName` is
|
|
517
|
+
refused (the server fills it from `workspaceId`). New sessions always carry
|
|
518
|
+
`memoryEnabled`, `false` when memory is off for the project.
|
|
519
|
+
- The new GETs reject unknown or duplicated query parameters; `context-fit`
|
|
520
|
+
takes `extraRoots` repeated once per root, because a comma is legal in a path.
|
|
521
|
+
- `POST /memory` content is capped at 64 KiB; that route alone accepts a body
|
|
522
|
+
of up to 2 × 64 KiB + 8 KiB so a full-size file survives JSON escaping. It
|
|
523
|
+
answers 409 `VERSE_MEMORY_REDACTED` when the content holds more `[REDACTED]`
|
|
524
|
+
placeholders than the file on disk, and `GET`/`POST /memory` responses carry
|
|
525
|
+
`contentSanitized: true` whenever the content sent is not the file's bytes.
|
|
526
|
+
- New sessions always record `contextMode` (`'standard'` included); an absent
|
|
527
|
+
key marks a pre-3.9 record (resolved as above).
|
|
528
|
+
- New persisted events `compaction` and `context`; `context` may carry
|
|
529
|
+
`contextWindowSource` (absent = `runtime`), so a catalog budget written after
|
|
530
|
+
a mode switch is not shown as a measurement. `VERSE_HANDOFF_SUMMARY_REQUEST`
|
|
531
|
+
(`types.ts`) is the fixed "summarize first" turn. The full additive contract
|
|
532
|
+
is in `docs/VERSE-CONTRACT-V1.md`.
|
|
533
|
+
|
|
534
|
+
### Hygiene
|
|
535
|
+
|
|
536
|
+
- `eslint.config.js` ignores `.claude/**`. Agent worktrees there produced about
|
|
537
|
+
98k lint errors, which made `npm run lint` — and so `prepublishOnly` — fail on
|
|
538
|
+
this machine.
|
|
539
|
+
- Two release-truth test pins that asserted superseded facts (npm provenance,
|
|
540
|
+
removed on purpose in `e24a7dae`, and the pre-rewrite desktop README) now
|
|
541
|
+
assert the current policy.
|
|
542
|
+
|
|
342
543
|
## [3.8.0] — 2026-09-23 UTC — local-only actually prevents spend
|
|
343
544
|
|
|
344
545
|
Two gates that make a promise the UI was already making. Both landed after the
|
package/dist/build-identity.json
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
import { isAbsolute, parse as parsePath, resolve } from 'node:path';
|
|
2
2
|
const USAGE = `usage: ashlr resources profile prepare --provider codex|claude|grok
|
|
3
3
|
--directory NEW_ABS --executable ABS [--json]
|
|
4
|
+
ashlr resources profile repin --directory EXISTING_ABS --executable ABS
|
|
5
|
+
[--dry-run] [--json]
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
prepare creates one new private profile under an existing owned mode-0700 parent.
|
|
6
8
|
Writes a standalone launcher, command.json, preparation manifest and empty native
|
|
7
9
|
state directories. Existing targets are never overwritten, repaired or reused.
|
|
8
10
|
On failure, a partially prepared directory may remain; inspect it rather than
|
|
9
11
|
deleting account state automatically. No parent directories are created.
|
|
10
12
|
|
|
13
|
+
repin points one existing prepared profile at a different native executable,
|
|
14
|
+
for example a newer CLI version that a model requires. It rewrites only the
|
|
15
|
+
executable locator in launcher.mjs and profile.json (command.json names node and
|
|
16
|
+
the launcher, never the native executable, so its bytes do not change), keeps
|
|
17
|
+
the provider, native state and sign-in untouched, and first copies the three
|
|
18
|
+
files to launcher.mjs.prev, profile.json.prev and command.json.prev. Every file
|
|
19
|
+
must still be prepare's unmodified output; a hand-edited profile is refused.
|
|
20
|
+
Rerunning the same repin after an interruption finishes it; repinning to the
|
|
21
|
+
current executable writes nothing. Sessions already running keep the binary
|
|
22
|
+
they started with; the next launch through the profile uses the new one.
|
|
23
|
+
--dry-run validates everything and reports the change without writing.
|
|
24
|
+
|
|
11
25
|
No executable is launched, credentials read/copied, account signed in, provider
|
|
12
26
|
contacted, pool enrolled or resident service installed. The returned login argv
|
|
13
27
|
is a separate interactive native action, not something this command executes.
|
|
@@ -16,12 +30,17 @@ environment; they are operator-owned code, not a sandbox or billing attestation.
|
|
|
16
30
|
Node with process.execve support and a supported POSIX platform are required.
|
|
17
31
|
--executable must name a canonical regular executable file, not an install symlink.
|
|
18
32
|
Output includes private local paths, never authentication material.
|
|
19
|
-
Exit codes: 0 prepared (authentication not checked),
|
|
20
|
-
2 invalid arguments. Grok preparation
|
|
21
|
-
it does not enable a Grok
|
|
33
|
+
Exit codes: 0 prepared, repinned or already pinned (authentication not checked),
|
|
34
|
+
1 preparation or repin unavailable, 2 invalid arguments. Grok preparation
|
|
35
|
+
supports separate native login/metadata; it does not enable a Grok
|
|
36
|
+
task-generation adapter.
|
|
22
37
|
`;
|
|
23
38
|
class UsageError extends Error {
|
|
24
39
|
}
|
|
40
|
+
/** A repin failure whose message is fixed, path-free text saying whether the profile changed. */
|
|
41
|
+
class RepinFailure extends Error {
|
|
42
|
+
}
|
|
43
|
+
const REPIN_UNAVAILABLE = 'Native profile repin unavailable; inspect the profile before retrying';
|
|
25
44
|
function parse(args) {
|
|
26
45
|
if (args.length > 12 || args.some((arg) => typeof arg !== 'string' || Buffer.byteLength(arg) > 4096 ||
|
|
27
46
|
[...arg].some((char) => char.charCodeAt(0) < 32 || char.charCodeAt(0) >= 127 && char.charCodeAt(0) <= 159)) ||
|
|
@@ -29,10 +48,14 @@ function parse(args) {
|
|
|
29
48
|
throw new UsageError('Invalid profile arguments');
|
|
30
49
|
if (args.length === 1 && ['--help', '-h'].includes(args[0]))
|
|
31
50
|
return { help: true };
|
|
32
|
-
|
|
33
|
-
|
|
51
|
+
const subcommand = args[0];
|
|
52
|
+
if (subcommand !== 'prepare' && subcommand !== 'repin')
|
|
53
|
+
throw new UsageError('Expected prepare or repin subcommand');
|
|
54
|
+
// repin reads the provider from the existing profile and never changes it.
|
|
55
|
+
const valued = subcommand === 'prepare' ? ['--provider', '--directory', '--executable'] : ['--directory', '--executable'];
|
|
34
56
|
const values = new Map();
|
|
35
57
|
let json = false;
|
|
58
|
+
let dryRun = false;
|
|
36
59
|
for (let i = 1; i < args.length; i++) {
|
|
37
60
|
const flag = args[i];
|
|
38
61
|
if (flag === '--json') {
|
|
@@ -41,16 +64,21 @@ function parse(args) {
|
|
|
41
64
|
json = true;
|
|
42
65
|
continue;
|
|
43
66
|
}
|
|
44
|
-
if (
|
|
67
|
+
if (flag === '--dry-run' && subcommand === 'repin') {
|
|
68
|
+
if (dryRun)
|
|
69
|
+
throw new UsageError('Duplicate profile option');
|
|
70
|
+
dryRun = true;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (flag === '--provider' && subcommand === 'repin')
|
|
74
|
+
throw new UsageError('repin keeps the profile provider; --provider is not accepted');
|
|
75
|
+
if (!valued.includes(flag) || values.has(flag))
|
|
45
76
|
throw new UsageError('Unknown or duplicate profile option');
|
|
46
77
|
const value = args[++i];
|
|
47
78
|
if (!value || value.startsWith('-'))
|
|
48
79
|
throw new UsageError('Profile option requires a value');
|
|
49
80
|
values.set(flag, value);
|
|
50
81
|
}
|
|
51
|
-
const provider = values.get('--provider');
|
|
52
|
-
if (provider !== 'codex' && provider !== 'claude' && provider !== 'grok')
|
|
53
|
-
throw new UsageError('Expected codex, claude or grok provider');
|
|
54
82
|
const path = (flag) => {
|
|
55
83
|
const value = values.get(flag);
|
|
56
84
|
if (!value || !isAbsolute(value) || resolve(value) !== value || parsePath(value).root === value) {
|
|
@@ -58,28 +86,74 @@ function parse(args) {
|
|
|
58
86
|
}
|
|
59
87
|
return value;
|
|
60
88
|
};
|
|
61
|
-
|
|
89
|
+
if (subcommand === 'repin')
|
|
90
|
+
return { help: false, subcommand, json, dryRun, directory: path('--directory'), executable: path('--executable') };
|
|
91
|
+
const provider = values.get('--provider');
|
|
92
|
+
if (provider !== 'codex' && provider !== 'claude' && provider !== 'grok')
|
|
93
|
+
throw new UsageError('Expected codex, claude or grok provider');
|
|
94
|
+
return { help: false, subcommand, json, provider, directory: path('--directory'), executable: path('--executable') };
|
|
95
|
+
}
|
|
96
|
+
const quote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
|
|
97
|
+
async function prepare(options) {
|
|
98
|
+
const { prepareResourceNativeProfile } = await import('../core/resources/native-profile.js');
|
|
99
|
+
const report = prepareResourceNativeProfile({ provider: options.provider, directory: options.directory, executable: options.executable });
|
|
100
|
+
console.log(options.json ? JSON.stringify(report, null, 2) : [
|
|
101
|
+
`Native profile · ${report.provider} · prepared · authentication not checked`,
|
|
102
|
+
`Directory: ${report.directory}`, `Command file: ${report.commandPath}`,
|
|
103
|
+
`Separate interactive sign-in: ${report.loginCommand.map(quote).join(' ')}`,
|
|
104
|
+
'No login was executed. Verify native account, billing route and quota before enrolling capacity.',
|
|
105
|
+
].join('\n'));
|
|
106
|
+
}
|
|
107
|
+
async function repin(options) {
|
|
108
|
+
const { repinResourceNativeProfile, ResourceNativeProfileRepinError } = await import('../core/resources/native-profile.js');
|
|
109
|
+
let report;
|
|
110
|
+
try {
|
|
111
|
+
report = repinResourceNativeProfile({ directory: options.directory, executable: options.executable, dryRun: options.dryRun });
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
throw new RepinFailure(error instanceof ResourceNativeProfileRepinError ? error.message : REPIN_UNAVAILABLE);
|
|
115
|
+
}
|
|
116
|
+
if (options.json) {
|
|
117
|
+
console.log(JSON.stringify(report, null, 2));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const heading = report.status === 'repinned' ? (report.resumed ? 'repinned (finished an interrupted repin)' : 'repinned')
|
|
121
|
+
: report.status === 'would-repin' ? (report.resumed ? 'dry run · would finish an interrupted repin' : 'dry run · would repin')
|
|
122
|
+
: 'already pinned · nothing written';
|
|
123
|
+
const lines = [`Native profile · ${report.provider} · ${heading} · authentication not checked`, `Directory: ${report.directory}`];
|
|
124
|
+
if (report.status === 'unchanged')
|
|
125
|
+
lines.push(`Executable: ${report.executable}`);
|
|
126
|
+
else
|
|
127
|
+
lines.push(`Executable: ${report.previousExecutable} -> ${report.executable}`);
|
|
128
|
+
if (report.backups) {
|
|
129
|
+
lines.push(`Previous files kept: ${[report.backups.launcherPath, report.backups.manifestPath, report.backups.commandPath].map(quote).join(' ')}`);
|
|
130
|
+
lines.push('Sessions already running keep the binary they started with; the next launch through this profile uses the new one.');
|
|
131
|
+
}
|
|
132
|
+
if (report.status === 'would-repin')
|
|
133
|
+
lines.push('Nothing was written.');
|
|
134
|
+
lines.push(`Nothing was executed. Check the new binary with: ashlr resources launcher check --provider ${report.provider} --command ${quote(report.commandPath)} --cwd <private dir>`);
|
|
135
|
+
console.log(lines.join('\n'));
|
|
62
136
|
}
|
|
63
137
|
export async function cmdResourceProfile(args) {
|
|
138
|
+
let subcommand = null;
|
|
64
139
|
try {
|
|
65
140
|
const options = parse(args);
|
|
66
141
|
if (options.help) {
|
|
67
142
|
console.log(USAGE);
|
|
68
143
|
return 0;
|
|
69
144
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
`Directory: ${report.directory}`, `Command file: ${report.commandPath}`,
|
|
76
|
-
`Separate interactive sign-in: ${report.loginCommand.map(quote).join(' ')}`,
|
|
77
|
-
'No login was executed. Verify native account, billing route and quota before enrolling capacity.',
|
|
78
|
-
].join('\n'));
|
|
145
|
+
subcommand = options.subcommand;
|
|
146
|
+
if (options.subcommand === 'repin')
|
|
147
|
+
await repin(options);
|
|
148
|
+
else
|
|
149
|
+
await prepare(options);
|
|
79
150
|
return 0;
|
|
80
151
|
}
|
|
81
152
|
catch (error) {
|
|
82
|
-
|
|
153
|
+
// Repin failures carry fixed, path-free text that says whether the profile
|
|
154
|
+
// changed; anything else (and every prepare failure) stays generic.
|
|
155
|
+
const message = error instanceof UsageError || error instanceof RepinFailure ? error.message
|
|
156
|
+
: subcommand === 'repin' ? REPIN_UNAVAILABLE : 'Native profile preparation unavailable; inspect the selected target for partial files';
|
|
83
157
|
if (args.includes('--json'))
|
|
84
158
|
console.log(JSON.stringify({ error: message }));
|
|
85
159
|
else
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource-profile.js","sourceRoot":"","sources":["../../src/cli/resource-profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,IAAI,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpE,MAAM,KAAK,GAAG
|
|
1
|
+
{"version":3,"file":"resource-profile.js","sourceRoot":"","sources":["../../src/cli/resource-profile.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,9 +21,65 @@ export interface ResourceNativeProfile {
|
|
|
21
21
|
command: string[];
|
|
22
22
|
loginCommand: string[];
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Key order of profile.json, exactly as `prepareResourceNativeProfile` builds it.
|
|
26
|
+
* Exported so a test can pin prepare's output to it: repin refuses any other
|
|
27
|
+
* shape, so the two must never drift apart silently.
|
|
28
|
+
*/
|
|
29
|
+
export declare const RESOURCE_NATIVE_PROFILE_MANIFEST_KEYS: readonly ["schemaVersion", "scope", "status", "authentication", "provider", "directory", "executable", "nodeExecutable", "commandPath", "launcherPath", "nativeStatePath", "anthropicStatePath", "manifestPath", "command", "loginCommand"];
|
|
24
30
|
/**
|
|
25
31
|
* Exclusive private leaf only. Existing paths are never reused, removed, repaired
|
|
26
32
|
* or overwritten. A failed write may leave a partial directory for inspection.
|
|
27
33
|
* Native login remains a separate operation through the generated command.
|
|
28
34
|
*/
|
|
29
35
|
export declare function prepareResourceNativeProfile(options: ResourceNativeProfileOptions): ResourceNativeProfile;
|
|
36
|
+
export interface ResourceNativeProfileRepinOptions {
|
|
37
|
+
directory: string;
|
|
38
|
+
executable: string;
|
|
39
|
+
/** Validate everything and report what would change; write nothing. */
|
|
40
|
+
dryRun?: boolean;
|
|
41
|
+
}
|
|
42
|
+
export interface ResourceNativeProfileRepin {
|
|
43
|
+
schemaVersion: 1;
|
|
44
|
+
scope: 'native-profile-repin';
|
|
45
|
+
/**
|
|
46
|
+
* `repinned` — launcher.mjs and profile.json now name `executable`.
|
|
47
|
+
* `unchanged` — both already named `executable`; nothing was written.
|
|
48
|
+
* `would-repin` — dry run: every check passed; nothing was written.
|
|
49
|
+
*/
|
|
50
|
+
status: 'repinned' | 'unchanged' | 'would-repin';
|
|
51
|
+
authentication: 'not-checked';
|
|
52
|
+
provider: ResourceNativeProfileProvider;
|
|
53
|
+
directory: string;
|
|
54
|
+
previousExecutable: string;
|
|
55
|
+
executable: string;
|
|
56
|
+
launcherPath: string;
|
|
57
|
+
manifestPath: string;
|
|
58
|
+
commandPath: string;
|
|
59
|
+
/** The `*.prev` copies of the three files as they stood before this repin; null when nothing was repinned. */
|
|
60
|
+
backups: {
|
|
61
|
+
launcherPath: string;
|
|
62
|
+
manifestPath: string;
|
|
63
|
+
commandPath: string;
|
|
64
|
+
} | null;
|
|
65
|
+
/** True when this call finished (or, dry, would finish) a repin interrupted between its launcher and profile.json publishes. */
|
|
66
|
+
resumed: boolean;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* - `invalid` — options, executable, runtime, private directories or file modes failed validation. Nothing written.
|
|
70
|
+
* - `inconsistent` — the files are not an unmodified prepared profile, or disagree with each other. Nothing written.
|
|
71
|
+
* - `failed-unchanged` — a write failed before launcher.mjs changed; the profile still runs its previous executable.
|
|
72
|
+
* - `failed-partial` — launcher.mjs changed but the rest did not complete; rerun the same repin, or restore `*.prev`.
|
|
73
|
+
*/
|
|
74
|
+
export type ResourceNativeProfileRepinFailure = 'invalid' | 'inconsistent' | 'failed-unchanged' | 'failed-partial';
|
|
75
|
+
export declare class ResourceNativeProfileRepinError extends Error {
|
|
76
|
+
readonly failure: ResourceNativeProfileRepinFailure;
|
|
77
|
+
constructor(failure: ResourceNativeProfileRepinFailure);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Re-pin one existing prepared profile to a different native executable.
|
|
81
|
+
* Rewrites only the executable locator (see the section comment above);
|
|
82
|
+
* idempotent when already pinned; resumes its own interrupted run; never
|
|
83
|
+
* executes anything and never reads native state or credentials.
|
|
84
|
+
*/
|
|
85
|
+
export declare function repinResourceNativeProfile(options: ResourceNativeProfileRepinOptions): ResourceNativeProfileRepin;
|