salidium 0.1.0 → 0.2.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/README.md +50 -99
- package/bundle/salidium.mjs +131 -6
- package/bundle/ui/assets/index-Bob9Rxh_.css +1 -0
- package/bundle/ui/assets/index-DPH48dJH.js +86 -0
- package/bundle/ui/index.html +2 -2
- package/package.json +2 -2
- package/bundle/ui/assets/index-B5glzwgK.css +0 -1
- package/bundle/ui/assets/index-kZRmL4Sh.js +0 -87
package/README.md
CHANGED
|
@@ -1,122 +1,73 @@
|
|
|
1
1
|
# Salidium
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
- **What** the agent is doing and what changed
|
|
6
|
-
- **Why** (the user's ask and the agent's stated discoveries — always attributed)
|
|
7
|
-
- **How** (plan and approach)
|
|
8
|
-
- **Verified** — what evidence actually shows (test/build/typecheck/lint runs parsed from real output)
|
|
9
|
-
- **Left** — what remains
|
|
10
|
-
- **Review** — what needs a human (waiting for permission, failing checks, unverified changes, destructive commands, claims without evidence)
|
|
11
|
-
|
|
12
|
-
The daemon, event store, deterministic report, and interface run entirely on your machine with no Salidium telemetry or hosted service. Salidium observes the agent you already run through supported integration points (hooks and the agent's own session logs), derives facts deterministically, and relays the agent's claims verbatim and labelled. Every observed statement links back to the raw record it came from.
|
|
13
|
-
|
|
14
|
-
The optional visual explanation uses your selected installed Claude Code or Codex CLI. Once per completed turn, Salidium sends that agent a bounded, redacted summary of the ask, statements, file names, and check outcomes; the CLI may contact its provider and consume your existing plan or API allowance. The invocation is tool-free, treats the session evidence as untrusted data, and accepts only a bounded, runtime-validated result. Older Codex versions that do not support the tool-disable flags fail closed and simply omit the generated block. Set `SALIDIUM_EXPLAINER=off` (or the legacy `SALIDIUM_EXPLAIN=0`) to send nothing to an agent. The deterministic report still works when explanation is off, unavailable, or fails.
|
|
15
|
-
|
|
16
|
-
It is also allowed to say nothing. A claim the classifier cannot place is recorded and reachable through `record`, and filed under no heading — Salidium may say less than it knows, and may not say something it does not know.
|
|
17
|
-
|
|
18
|
-
The session page is laid out as a written document rather than a dashboard: the product mark, the session title, the facts that identify the run, and the **badges** — did it work, what needs a human, what is unfinished — then a rule, then the **explanation**: one sentence saying what the session is about, followed by the diagrams that carry the meaning. Supporting facts stay behind their toolbar controls so the explanation remains the canvas.
|
|
19
|
-
|
|
20
|
-
Detail is opened by section rather than by one global depth control. **Evidence** opens coverage, checks, changes, and the event record; **Rewind** reconstructs the session at a chosen moment; and **Quantities** and **History** share one supporting inspector beside the page, replacing one another without squeezing the explanation into a third column.
|
|
21
|
-
|
|
22
|
-
The session list groups by the question it answers — **Needs you**, **Working**, **Recent** — because you are usually running more than one agent at a time. It folds away with `[`, and the sessions that started and ended without running a turn are collapsed behind one line. Light, dark and system themes are all first-class and the choice is remembered.
|
|
23
|
-
|
|
24
|
-
Providers today: **Claude Code** (hooks + transcript, primary) and **Codex** (rollout files + hooks).
|
|
25
|
-
|
|
26
|
-
## Run it
|
|
27
|
-
|
|
28
|
-
Requirements: Node ≥ 24, because the daemon uses the built-in `node:sqlite`.
|
|
3
|
+
**Understand what your coding agent did.** Salidium turns Claude Code and Codex sessions into a
|
|
4
|
+
clear, evidence-linked report of what changed, why, what was verified, and what needs you.
|
|
29
5
|
|
|
30
6
|
```bash
|
|
31
7
|
npx salidium
|
|
32
8
|
```
|
|
33
9
|
|
|
34
|
-
|
|
10
|
+
Salidium is [MIT-licensed](LICENSE), open source, and local-first. The report, event store, and
|
|
11
|
+
interface run on your machine with no Salidium telemetry. Raw transcripts stay local. Optional
|
|
12
|
+
generated explanations send a bounded, redacted excerpt through your installed agent CLI, which
|
|
13
|
+
may contact its provider; they can be turned off.
|
|
35
14
|
|
|
36
|
-
|
|
15
|
+
## See the work without reading every line
|
|
37
16
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
salidium install-hooks # connect detected agents manually
|
|
44
|
-
salidium uninstall-hooks
|
|
45
|
-
salidium doctor # check or troubleshoot the local setup
|
|
46
|
-
salidium show # print the same report as text (--detail=summary|detail|source)
|
|
47
|
-
salidium audit-claims # measure the claim classifier against every session in your own store
|
|
48
|
-
salidium reingest --all # re-read your session files after an upgrade taught the adapters something new
|
|
49
|
-
salidium retention # preview/set forever, 30, 90, or 365 day local history retention
|
|
50
|
-
salidium retention compact # offline integrity-check and return reusable database pages to the OS
|
|
51
|
-
salidium pin [session] # exempt a session from automatic retention
|
|
52
|
-
salidium forget <id> # remove a session while preventing source-file resurrection
|
|
53
|
-
salidium status # daemon and hook state
|
|
54
|
-
salidium restart # stop it, start it again, and open the UI on the new token
|
|
55
|
-
salidium stop
|
|
56
|
-
```
|
|
17
|
+
```text
|
|
18
|
+
Agent response Salidium report
|
|
19
|
+
────────────────────────────── ──────────────────────────────
|
|
20
|
+
"The cursor advanced before the WHY
|
|
21
|
+
storage transaction committed..." → Evidence could be lost before storage was durable.
|
|
57
22
|
|
|
58
|
-
|
|
23
|
+
"I now queue the record, flush, HOW
|
|
24
|
+
then advance the cursor." → Queue the record. Flush storage. Advance the cursor.
|
|
59
25
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
## Development
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
pnpm install
|
|
66
|
-
pnpm build # typecheck + build every package and the UI
|
|
67
|
-
pnpm salidium # run the CLI from source (Node type stripping)
|
|
68
|
-
pnpm typecheck # tsc --build (project references)
|
|
69
|
-
pnpm lint # biome check
|
|
70
|
-
pnpm format # biome format --write
|
|
71
|
-
pnpm test # vitest: unit, adapter fixtures, daemon integration, performance
|
|
72
|
-
pnpm test:e2e # real-daemon Chromium + automated accessibility checks
|
|
73
|
-
pnpm test:e2e:full # Chromium, Firefox, and WebKit portability matrix
|
|
74
|
-
pnpm package # build the publishable bundle into packages/cli/bundle
|
|
75
|
-
pnpm --filter @salidium/ui dev # Vite dev server for the UI, proxied to the running daemon (open it with #token=… from ~/.salidium/daemon.json)
|
|
26
|
+
test/build output → VERIFIED 42 tests passed
|
|
27
|
+
unsupported agent claim → REVIEW Claim needs evidence
|
|
76
28
|
```
|
|
77
29
|
|
|
78
|
-
|
|
79
|
-
Windows checks. It then packs the tarball, unpacks it somewhere with no workspace above it and
|
|
80
|
-
starts the daemon from it — because the published bundle and the checkout resolve paths
|
|
81
|
-
differently, and only the second arrangement is what a user gets.
|
|
82
|
-
|
|
83
|
-
Release preparation, the manual-only publish workflow, and rollback steps are documented in
|
|
84
|
-
[`docs/releasing.md`](docs/releasing.md).
|
|
30
|
+
Salidium gives you:
|
|
85
31
|
|
|
86
|
-
|
|
32
|
+
- **What changed** across the agent's work and files.
|
|
33
|
+
- **Why and how**, with reported reasoning kept clearly attributed.
|
|
34
|
+
- **Verified results** parsed from real test, build, typecheck, and lint output.
|
|
35
|
+
- **Left and Review** for unfinished work, failures, unknowns, and claims needing a person.
|
|
36
|
+
- **Evidence and Rewind** to inspect the original record or reconstruct an earlier moment.
|
|
87
37
|
|
|
88
|
-
|
|
38
|
+
Supported agents: **Claude Code** and **Codex**. On first run, Salidium finds them, shows the local
|
|
39
|
+
settings it wants to update, asks permission, and opens the local interface. Node.js 24 or newer is
|
|
40
|
+
required.
|
|
89
41
|
|
|
90
|
-
|
|
91
|
-
salidium audit-claims # counts, plus 8 sampled claims per rule
|
|
92
|
-
salidium audit-claims --only=discovery --sample=20
|
|
93
|
-
salidium audit-claims --json # for a script
|
|
94
|
-
```
|
|
42
|
+
## Trust model
|
|
95
43
|
|
|
96
|
-
|
|
44
|
+
The complete account-free local product lives in this repository. A hosted Salidium service may
|
|
45
|
+
later provide cross-device or team coordination, but the local product does not require it and raw
|
|
46
|
+
provider evidence remains local by default. Read the
|
|
47
|
+
[open-source and hosted-service boundary](docs/open-source-boundary.md) for the exact public and
|
|
48
|
+
private split.
|
|
97
49
|
|
|
98
|
-
|
|
50
|
+
Optional generated explanations send a bounded, locally redacted excerpt through the Claude or
|
|
51
|
+
Codex CLI you selected; that CLI may contact its provider and use your plan or API allowance. Set
|
|
52
|
+
`SALIDIUM_EXPLAINER=off` to disable them. The fact-based report still works.
|
|
99
53
|
|
|
100
|
-
|
|
101
|
-
agent runtime ──hooks (async sh relay)──▶ ┐
|
|
102
|
-
──session log (tailed)────▶ ├─▶ provider adapter → canonical events → dedupe → redact → reducer → semantic state + change log
|
|
103
|
-
┘ │
|
|
104
|
-
SQLite (events, changes, checkpoints) ◀─┘─▶ SSE → UI (same reducer)
|
|
105
|
-
```
|
|
54
|
+
## Learn more
|
|
106
55
|
|
|
107
|
-
-
|
|
108
|
-
-
|
|
109
|
-
-
|
|
110
|
-
-
|
|
111
|
-
-
|
|
112
|
-
- `packages/cli` — `salidium` command.
|
|
56
|
+
- [Using Salidium](docs/using-salidium.md): setup, report guide, commands, privacy, and recovery
|
|
57
|
+
- [Architecture](docs/architecture.md): evidence, replay, storage, and extension boundaries
|
|
58
|
+
- [Long-term intelligence](docs/long-term-intelligence.md): memory, retrieval, consent, and evaluation
|
|
59
|
+
- [Evaluation protocol](docs/evaluation-protocol.md): how a future recall claim would have to be proven
|
|
60
|
+
- [Contributing](CONTRIBUTING.md) and [security policy](SECURITY.md)
|
|
113
61
|
|
|
114
|
-
|
|
62
|
+
## Development
|
|
115
63
|
|
|
116
|
-
|
|
64
|
+
```bash
|
|
65
|
+
pnpm install --frozen-lockfile
|
|
66
|
+
pnpm lint
|
|
67
|
+
pnpm typecheck
|
|
68
|
+
pnpm test
|
|
69
|
+
pnpm build
|
|
70
|
+
```
|
|
117
71
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
behavior may vary across providers and writing styles; `audit-claims` is how to evaluate it on your
|
|
121
|
-
own store. Native Windows history import is supported, but live hooks still require POSIX `sh` and
|
|
122
|
-
`curl`. See the architecture document for the complete limitations.
|
|
72
|
+
Run from source with `pnpm salidium`. The public CLI is bundled as one self-contained script; the
|
|
73
|
+
separately releasable `@salidium/sync-contract` contains only strict interoperability schemas.
|
package/bundle/salidium.mjs
CHANGED
|
@@ -1114,7 +1114,8 @@ function applyVerificationReview(state, event, log) {
|
|
|
1114
1114
|
epistemic: v.outcomeEpistemic
|
|
1115
1115
|
});
|
|
1116
1116
|
} else if (v.outcome === "pass" && v.scope !== "partial") {
|
|
1117
|
-
|
|
1117
|
+
const covers = v.method !== "lint";
|
|
1118
|
+
resolve(state, event, (r) => r.id === `verification-failed:${v.method}` || covers && r.rule === "changes-unverified");
|
|
1118
1119
|
}
|
|
1119
1120
|
}
|
|
1120
1121
|
function applyReviewRulesAfterEvent(state, event, log) {
|
|
@@ -23044,6 +23045,7 @@ var SessionCoordinator = class _SessionCoordinator {
|
|
|
23044
23045
|
cadence: envAllows ? "turn" : "off",
|
|
23045
23046
|
idleEndMs: IDLE_END_MS,
|
|
23046
23047
|
explainSession: explainWithStatus,
|
|
23048
|
+
now: Date.now,
|
|
23047
23049
|
...args.options
|
|
23048
23050
|
};
|
|
23049
23051
|
const cp = store.latestCheckpoint(sessionId, REDUCER_VERSION);
|
|
@@ -23083,7 +23085,7 @@ var SessionCoordinator = class _SessionCoordinator {
|
|
|
23083
23085
|
return coord;
|
|
23084
23086
|
}
|
|
23085
23087
|
get summary() {
|
|
23086
|
-
const s = summarizeSession(this.state,
|
|
23088
|
+
const s = summarizeSession(this.state, this.opts.now());
|
|
23087
23089
|
s.explanationStatus = this.explanationIsCurrent() ? "generated" : this.explanationStatus;
|
|
23088
23090
|
return s;
|
|
23089
23091
|
}
|
|
@@ -23397,10 +23399,13 @@ var SessionRegistry = class {
|
|
|
23397
23399
|
* load: it is one value for the whole daemon, and a coordinator is created on the ingest path.
|
|
23398
23400
|
*/
|
|
23399
23401
|
explainerCadence = "turn";
|
|
23402
|
+
/** Handed to every coordinator this registry loads; see `CoordinatorOptions.now`. */
|
|
23403
|
+
now;
|
|
23400
23404
|
constructor(store, opts = {}) {
|
|
23401
23405
|
this.store = store;
|
|
23402
23406
|
if (opts.explainerCadence)
|
|
23403
23407
|
this.explainerCadence = opts.explainerCadence;
|
|
23408
|
+
this.now = opts.now;
|
|
23404
23409
|
this.listener = {
|
|
23405
23410
|
onEvents: (sessionId, events, changes) => {
|
|
23406
23411
|
for (const s of this.allSubscribers) {
|
|
@@ -23444,7 +23449,7 @@ var SessionRegistry = class {
|
|
|
23444
23449
|
cwd: hint?.cwd,
|
|
23445
23450
|
store: this.store,
|
|
23446
23451
|
listener: this.listener,
|
|
23447
|
-
options: { cadence: this.explainerCadence }
|
|
23452
|
+
options: { cadence: this.explainerCadence, ...this.now ? { now: this.now } : {} }
|
|
23448
23453
|
});
|
|
23449
23454
|
c.onError = (err) => this.onPersistError?.(sessionId, err);
|
|
23450
23455
|
this.live.set(sessionId, c);
|
|
@@ -24169,7 +24174,7 @@ import { dirname as dirname2 } from "node:path";
|
|
|
24169
24174
|
import { DatabaseSync } from "node:sqlite";
|
|
24170
24175
|
import { isDeepStrictEqual } from "node:util";
|
|
24171
24176
|
import { gunzipSync, gzipSync } from "node:zlib";
|
|
24172
|
-
var SCHEMA_VERSION =
|
|
24177
|
+
var SCHEMA_VERSION = 6;
|
|
24173
24178
|
var INGEST_PARSER_REVISION = "2026-08-19.1";
|
|
24174
24179
|
function existingSchemaVersion(db) {
|
|
24175
24180
|
try {
|
|
@@ -24312,6 +24317,109 @@ CREATE TABLE IF NOT EXISTS usage_rollups (
|
|
|
24312
24317
|
cache_write_tokens INTEGER NOT NULL DEFAULT 0
|
|
24313
24318
|
);
|
|
24314
24319
|
`;
|
|
24320
|
+
var SCHEMA_6_DDL = `
|
|
24321
|
+
CREATE TABLE IF NOT EXISTS sync_identity (
|
|
24322
|
+
singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
|
|
24323
|
+
replica_id TEXT NOT NULL UNIQUE,
|
|
24324
|
+
created_at TEXT NOT NULL
|
|
24325
|
+
);
|
|
24326
|
+
CREATE TABLE IF NOT EXISTS sync_streams (
|
|
24327
|
+
stream_id TEXT PRIMARY KEY,
|
|
24328
|
+
replica_id TEXT NOT NULL,
|
|
24329
|
+
-- Positions are unique per generation, not per replica. A replica restored from an older backup
|
|
24330
|
+
-- bumps this so its reused positions are a declared restart rather than a content conflict.
|
|
24331
|
+
replica_generation INTEGER NOT NULL DEFAULT 1,
|
|
24332
|
+
destination_id TEXT NOT NULL UNIQUE,
|
|
24333
|
+
next_control_position INTEGER NOT NULL DEFAULT 0,
|
|
24334
|
+
next_data_position INTEGER NOT NULL DEFAULT 0,
|
|
24335
|
+
acknowledged_control_position INTEGER NOT NULL DEFAULT -1,
|
|
24336
|
+
acknowledged_data_position INTEGER NOT NULL DEFAULT -1,
|
|
24337
|
+
previous_control_operation_id TEXT,
|
|
24338
|
+
previous_data_operation_id TEXT,
|
|
24339
|
+
created_at TEXT NOT NULL
|
|
24340
|
+
);
|
|
24341
|
+
CREATE TABLE IF NOT EXISTS sync_consent_revisions (
|
|
24342
|
+
stream_id TEXT NOT NULL,
|
|
24343
|
+
grant_id TEXT NOT NULL,
|
|
24344
|
+
revision INTEGER NOT NULL,
|
|
24345
|
+
status TEXT NOT NULL CHECK (status IN ('active', 'revoked')),
|
|
24346
|
+
destination_id TEXT NOT NULL,
|
|
24347
|
+
json TEXT NOT NULL,
|
|
24348
|
+
recorded_at TEXT NOT NULL,
|
|
24349
|
+
PRIMARY KEY (stream_id, grant_id, revision),
|
|
24350
|
+
FOREIGN KEY (stream_id) REFERENCES sync_streams(stream_id)
|
|
24351
|
+
);
|
|
24352
|
+
CREATE INDEX IF NOT EXISTS sync_consent_current
|
|
24353
|
+
ON sync_consent_revisions(stream_id, grant_id, revision DESC);
|
|
24354
|
+
CREATE TABLE IF NOT EXISTS intelligence_records (
|
|
24355
|
+
stream_id TEXT NOT NULL,
|
|
24356
|
+
item_id TEXT NOT NULL,
|
|
24357
|
+
revision INTEGER NOT NULL,
|
|
24358
|
+
kind TEXT NOT NULL,
|
|
24359
|
+
grant_id TEXT NOT NULL,
|
|
24360
|
+
grant_revision INTEGER NOT NULL,
|
|
24361
|
+
current INTEGER NOT NULL CHECK (current IN (0, 1)),
|
|
24362
|
+
json TEXT NOT NULL,
|
|
24363
|
+
recorded_at TEXT NOT NULL,
|
|
24364
|
+
PRIMARY KEY (stream_id, item_id, revision),
|
|
24365
|
+
FOREIGN KEY (stream_id) REFERENCES sync_streams(stream_id)
|
|
24366
|
+
);
|
|
24367
|
+
CREATE UNIQUE INDEX IF NOT EXISTS intelligence_one_current_revision
|
|
24368
|
+
ON intelligence_records(stream_id, item_id) WHERE current = 1;
|
|
24369
|
+
CREATE TABLE IF NOT EXISTS intelligence_evidence_map (
|
|
24370
|
+
evidence_id TEXT PRIMARY KEY,
|
|
24371
|
+
independence_id TEXT NOT NULL,
|
|
24372
|
+
session_id TEXT,
|
|
24373
|
+
event_id TEXT,
|
|
24374
|
+
authority TEXT NOT NULL,
|
|
24375
|
+
role TEXT NOT NULL,
|
|
24376
|
+
captured_at TEXT NOT NULL,
|
|
24377
|
+
descriptor_digest TEXT NOT NULL,
|
|
24378
|
+
created_at TEXT NOT NULL
|
|
24379
|
+
);
|
|
24380
|
+
CREATE TABLE IF NOT EXISTS intelligence_tombstones (
|
|
24381
|
+
stream_id TEXT NOT NULL,
|
|
24382
|
+
item_id TEXT NOT NULL,
|
|
24383
|
+
delete_through_revision INTEGER NOT NULL,
|
|
24384
|
+
reason TEXT NOT NULL,
|
|
24385
|
+
requested_at TEXT NOT NULL,
|
|
24386
|
+
receipt_id TEXT,
|
|
24387
|
+
completed_at TEXT,
|
|
24388
|
+
PRIMARY KEY (stream_id, item_id),
|
|
24389
|
+
FOREIGN KEY (stream_id) REFERENCES sync_streams(stream_id)
|
|
24390
|
+
);
|
|
24391
|
+
CREATE TABLE IF NOT EXISTS sync_outbox (
|
|
24392
|
+
stream_id TEXT NOT NULL,
|
|
24393
|
+
lane TEXT NOT NULL CHECK (lane IN ('control', 'data')),
|
|
24394
|
+
position INTEGER NOT NULL,
|
|
24395
|
+
operation_id TEXT NOT NULL UNIQUE,
|
|
24396
|
+
operation_type TEXT NOT NULL,
|
|
24397
|
+
content_digest TEXT NOT NULL,
|
|
24398
|
+
grant_id TEXT,
|
|
24399
|
+
item_id TEXT,
|
|
24400
|
+
json TEXT NOT NULL,
|
|
24401
|
+
created_at TEXT NOT NULL,
|
|
24402
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
24403
|
+
next_attempt_at TEXT,
|
|
24404
|
+
acknowledged_at TEXT,
|
|
24405
|
+
-- A destination can refuse an operation permanently. That is a distinct outcome from durable
|
|
24406
|
+
-- acceptance and must never be recorded as one, or a refused record would read as delivered.
|
|
24407
|
+
refused_at TEXT,
|
|
24408
|
+
refusal_code TEXT,
|
|
24409
|
+
PRIMARY KEY (stream_id, lane, position),
|
|
24410
|
+
FOREIGN KEY (stream_id) REFERENCES sync_streams(stream_id)
|
|
24411
|
+
);
|
|
24412
|
+
CREATE INDEX IF NOT EXISTS sync_outbox_pending
|
|
24413
|
+
ON sync_outbox(stream_id, lane, acknowledged_at, position);
|
|
24414
|
+
CREATE TABLE IF NOT EXISTS sync_deletion_receipts (
|
|
24415
|
+
receipt_id TEXT PRIMARY KEY,
|
|
24416
|
+
stream_id TEXT NOT NULL,
|
|
24417
|
+
operation_id TEXT NOT NULL,
|
|
24418
|
+
json TEXT NOT NULL,
|
|
24419
|
+
completed_at TEXT NOT NULL,
|
|
24420
|
+
FOREIGN KEY (stream_id) REFERENCES sync_streams(stream_id)
|
|
24421
|
+
);
|
|
24422
|
+
`;
|
|
24315
24423
|
function canonicalizeTimestamp(value) {
|
|
24316
24424
|
if (typeof value !== "string" || value.length === 0)
|
|
24317
24425
|
return void 0;
|
|
@@ -24579,6 +24687,10 @@ function migrateToSchema5(db, migratedAt = (/* @__PURE__ */ new Date()).toISOStr
|
|
|
24579
24687
|
enqueueMissing.run(source.path, source.sessionId, source.provider, source.agentId ?? null, INGEST_PARSER_REVISION, migratedAt);
|
|
24580
24688
|
db.prepare("INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)").run("schema_5_migrated_at", migratedAt);
|
|
24581
24689
|
}
|
|
24690
|
+
function migrateToSchema6(db, migratedAt = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
24691
|
+
db.exec(SCHEMA_6_DDL);
|
|
24692
|
+
db.prepare("INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)").run("schema_6_migrated_at", migratedAt);
|
|
24693
|
+
}
|
|
24582
24694
|
var SESSION_PAGE = 500;
|
|
24583
24695
|
var REAL_SESSION = `COALESCE(json_extract(summary_json, '$.internal'), 0) = 0
|
|
24584
24696
|
AND instr(COALESCE(title, ''), '[salidium-explainer]') = 0`;
|
|
@@ -24632,6 +24744,8 @@ var SqliteStore = class {
|
|
|
24632
24744
|
}
|
|
24633
24745
|
this.db.exec("PRAGMA journal_mode = WAL; PRAGMA synchronous = NORMAL; PRAGMA temp_store = MEMORY; PRAGMA foreign_keys = ON;");
|
|
24634
24746
|
this.db.exec(DDL);
|
|
24747
|
+
if (priorVersion === void 0 && !hadLegacyTables)
|
|
24748
|
+
this.db.exec(SCHEMA_6_DDL);
|
|
24635
24749
|
try {
|
|
24636
24750
|
this.db.exec("ALTER TABLE changes ADD COLUMN reducer_version TEXT");
|
|
24637
24751
|
} catch {
|
|
@@ -24647,6 +24761,8 @@ var SqliteStore = class {
|
|
|
24647
24761
|
migrateToSchema4(this.db);
|
|
24648
24762
|
if ((priorVersion ?? 0) < 5)
|
|
24649
24763
|
migrateToSchema5(this.db);
|
|
24764
|
+
if ((priorVersion ?? 0) < 6)
|
|
24765
|
+
migrateToSchema6(this.db);
|
|
24650
24766
|
this.db.exec("COMMIT");
|
|
24651
24767
|
} catch (error51) {
|
|
24652
24768
|
try {
|
|
@@ -25336,7 +25452,8 @@ async function startDaemon(overrides = {}) {
|
|
|
25336
25452
|
const stored = readSettings(config2.home, (reason) => log.warn("settings invalid; optional explanations disabled", { reason }));
|
|
25337
25453
|
const envOff = configuredExplainerMode(process.env) === "off";
|
|
25338
25454
|
const registry2 = new SessionRegistry(store, {
|
|
25339
|
-
explainerCadence: effectiveCadence(stored.explainerCadence)
|
|
25455
|
+
explainerCadence: effectiveCadence(stored.explainerCadence),
|
|
25456
|
+
...overrides.now ? { now: overrides.now } : {}
|
|
25340
25457
|
});
|
|
25341
25458
|
const explainerSettings = () => {
|
|
25342
25459
|
const usage = registry2.explainerUsage();
|
|
@@ -25937,7 +26054,11 @@ function createIntegration(definition) {
|
|
|
25937
26054
|
];
|
|
25938
26055
|
}
|
|
25939
26056
|
if (inspection.status === "configured") {
|
|
25940
|
-
|
|
26057
|
+
const ok = {
|
|
26058
|
+
level: "ok",
|
|
26059
|
+
message: `${definition.name} connection is configured`
|
|
26060
|
+
};
|
|
26061
|
+
return definition.standingNote ? [ok, { level: "info", message: definition.standingNote }] : [ok];
|
|
25941
26062
|
}
|
|
25942
26063
|
if (inspection.status === "partial") {
|
|
25943
26064
|
return [
|
|
@@ -25978,6 +26099,7 @@ var codex = createIntegration({
|
|
|
25978
26099
|
id: "codex",
|
|
25979
26100
|
name: "Codex",
|
|
25980
26101
|
command: "codex",
|
|
26102
|
+
standingNote: "Codex honours a hook only once it has been trusted there: open /hooks in Codex. Salidium cannot tell whether that has been done",
|
|
25981
26103
|
stateDirectory(context) {
|
|
25982
26104
|
return environment(context).CODEX_HOME ?? join11(context.userHome, ".codex");
|
|
25983
26105
|
},
|
|
@@ -26570,6 +26692,9 @@ ${uiUrl(running)}
|
|
|
26570
26692
|
for (const validation of provider.validate(context)) {
|
|
26571
26693
|
if (validation.level === "attention")
|
|
26572
26694
|
process.stdout.write(` needs attention: ${validation.message}
|
|
26695
|
+
`);
|
|
26696
|
+
else if (validation.level === "info")
|
|
26697
|
+
process.stdout.write(` note: ${validation.message}
|
|
26573
26698
|
`);
|
|
26574
26699
|
}
|
|
26575
26700
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--font-sans:ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--font-mono:ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;--brand-charcoal:#344047;--brand-warm-white:#f5f4ef;--gray-1:#fff;--gray-2:#f7f7f5;--gray-3:#eae9e6;--gray-4:#e3e2e0;--gray-5:#d0cec9;--gray-6:#b4b3ae;--gray-7:#8b8a85;--gray-8:#5f5e5b;--gray-9:#48463f;--gray-10:#37352f;--bg:var(--gray-1);--bg-subtle:var(--gray-2);--bg-muted:var(--gray-3);--border:var(--gray-4);--border-strong:var(--gray-5);--text:var(--gray-10);--text-secondary:var(--gray-8);--text-tertiary:#66655f;--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial}:root:not([data-theme=light]){--gray-1:#191919;--gray-2:#202020;--gray-3:#2c2c2c;--gray-4:#2f2f2f;--gray-5:#3d3d3d;--gray-6:#525252;--gray-7:#7a7a7a;--gray-8:#b4b4b2;--gray-9:#d4d4d3;--gray-10:#ededec;--text-tertiary:#9a9a9a}}:root[data-theme=dark]{--gray-1:#191919;--gray-2:#202020;--gray-3:#2c2c2c;--gray-4:#2f2f2f;--gray-5:#3d3d3d;--gray-6:#525252;--gray-7:#7a7a7a;--gray-8:#b4b4b2;--gray-9:#d4d4d3;--gray-10:#ededec;--text-tertiary:#9a9a9a}:root{--z-toolbar:5;--z-float:6;--z-panel:30;--z-drawer:40;--text-xs:11px;--text-sm:12.5px;--text-base:14px;--text-md:15px;--text-lg:19px;--text-xl:23px;--text-display:30px;--leading:1.5;--space-1:4px;--space-2:8px;--space-3:12px;--space-4:16px;--space-5:20px;--space-6:24px;--space-8:32px;--space-10:40px;--radius-xs:4px;--radius-sm:6px;--radius-md:10px;--radius-lg:16px;--row-h:28px;--ease:cubic-bezier(.2, 0, 0, 1);--motion-fast:.12s;--motion-base:.18s;--control-h:28px;--control-px:9px;--control-radius:var(--radius-sm);--control-gap:6px;--icon:14px;--foot-h:42px;--page-w:1000px;--float-bg:color-mix(in srgb, var(--bg) 82%, transparent);--float-blur:blur(12px) saturate(1.6);--scroll-thumb:#37352f33;--scroll-thumb-hover:#37352f61;--measure:68ch;--accent:#3b5bdb;--accent-fg:#fff;--accent-soft:#3b5bdb1a;--ok:#147638;--ok-soft:#15803d1f;--warn:#8a5a12;--warn-soft:#b7791f24;--danger:#c0392b;--danger-soft:#c0392b1f;--facet-why:#7c4bb0;--facet-how:#25708a;--brand-claude:#a8452a;--brand-claude-soft:#d9775724;--brand-codex:#0b7a5e;--brand-codex-soft:#10a37f24;--diff-add-bg:#15803d1f;--diff-del-bg:#c0392b1f;--shadow:0 1px 2px #0000000f;--shadow-float:0 6px 24px #0000001a, 0 1px 3px #00000014;--shadow-float-sm:0 2px 8px #00000012, 0 1px 2px #0000000f}@media (prefers-color-scheme:dark){:root:not([data-theme=light]){--accent:#8fa6ff;--accent-fg:#191919;--accent-soft:#8fa6ff24;--ok:#5fcf88;--ok-soft:#5fcf8824;--warn:#e0a83c;--warn-soft:#e0a83c29;--danger:#f0736a;--danger-soft:#f0736a29;--facet-why:#b98ce0;--facet-how:#57b0c9;--brand-claude:#e79b7d;--brand-claude-soft:#d9775729;--brand-codex:#4fc4a3;--brand-codex-soft:#10a37f29;--diff-add-bg:#5fcf8824;--diff-del-bg:#f0736a24;--shadow:0 1px 2px #0006;--shadow-float:0 6px 24px #00000070, 0 1px 3px #0000004d;--shadow-float-sm:0 2px 8px #00000057, 0 1px 2px #0000003d;--scroll-thumb:#ededec2e;--scroll-thumb-hover:#ededec57}}:root[data-theme=dark]{--accent:#8fa6ff;--accent-fg:#191919;--accent-soft:#8fa6ff24;--ok:#5fcf88;--ok-soft:#5fcf8824;--warn:#e0a83c;--warn-soft:#e0a83c29;--danger:#f0736a;--danger-soft:#f0736a29;--facet-why:#b98ce0;--facet-how:#57b0c9;--brand-claude:#e79b7d;--brand-claude-soft:#d9775729;--brand-codex:#4fc4a3;--brand-codex-soft:#10a37f29;--diff-add-bg:#5fcf8824;--diff-del-bg:#f0736a24;--shadow:0 1px 2px #0006;--shadow-float:0 6px 24px #00000070, 0 1px 3px #0000004d;--shadow-float-sm:0 2px 8px #00000057, 0 1px 2px #0000003d;--scroll-thumb:#ededec2e;--scroll-thumb-hover:#ededec57}*,:before,:after{box-sizing:border-box}@supports (corner-shape:squircle){*,:before,:after{corner-shape:squircle}[class*=dot],[class*=mark],[class*=pulse],.opt-mark,.pop-help{corner-shape:round}}.arrives{--leave-delay:0s;opacity:0;transform:translate(var(--slide,0), var(--rise,0));transition:opacity var(--motion-base) var(--ease), transform var(--motion-base) var(--ease), visibility var(--motion-base) var(--ease), position 0s var(--leave-delay) allow-discrete}.arrives:not(.is-open){--leave-delay:var(--motion-base);visibility:hidden;pointer-events:none}.arrives.is-open{opacity:1;transform:none}@starting-style{.arrives.is-open{opacity:0;transform:translate(var(--slide,0), var(--rise,0))}}html,body,#root{height:100%;margin:0;overflow:hidden}body{background:var(--bg);color:var(--text);font-family:var(--font-sans);font-size:var(--text-base);font-weight:400;line-height:var(--leading);-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility}h1,h2,h3{letter-spacing:-.01em;margin:0;font-weight:500}button,input,select{font:inherit;color:inherit}button{cursor:pointer;background:0 0;border:0;padding:0}a{color:var(--accent);text-decoration:none}code,.mono{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:.94em}.num{font-variant-numeric:tabular-nums}:focus-visible{outline:2px solid var(--accent);outline-offset:1px}@media (prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}:root{--hover-row:var(--bg-subtle)}*{scrollbar-width:thin;scrollbar-color:transparent transparent}::-webkit-scrollbar{width:12px;height:12px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-corner{background:0 0}::-webkit-scrollbar-thumb{transition:background var(--motion-base) var(--ease);background:padding-box padding-box;border:3px solid #0000;border-radius:8px}[data-scrolling]::-webkit-scrollbar-thumb{background:var(--scroll-thumb);background-clip:padding-box}[data-scrolling]{scrollbar-color:var(--scroll-thumb) transparent}::-webkit-scrollbar-thumb:hover{background:var(--scroll-thumb-hover);background-clip:padding-box}@property --fade-top{syntax:"<length>";inherits:false;initial-value:0}@property --fade-bottom{syntax:"<length>";inherits:false;initial-value:0}.scroll-fade{--fade:24px;--fade-top:0px;--fade-bottom:0px;-webkit-mask-image:linear-gradient(to bottom, transparent, #000 var(--fade-top), #000 calc(100% - var(--fade-bottom)), transparent);mask-image:linear-gradient(to bottom, transparent, #000 var(--fade-top), #000 calc(100% - var(--fade-bottom)), transparent);transition:--fade-top var(--motion-fast) var(--ease), --fade-bottom var(--motion-fast) var(--ease)}.scroll-fade[data-fade=top],.scroll-fade[data-fade=both]{--fade-top:var(--fade)}.scroll-fade[data-fade=bottom],.scroll-fade[data-fade=both]{--fade-bottom:var(--fade)}.scroll-fade.at-bottom-only{--fade-top:0px}.field{min-width:0;height:var(--control-h);padding:0 var(--control-px);border:1px solid var(--border);border-radius:var(--control-radius);background:var(--bg);color:var(--text);font-size:var(--text-sm)}.field::placeholder{color:var(--text-tertiary)}.field:focus-visible{outline:2px solid var(--accent);outline-offset:-1px}.btn{justify-content:center;align-items:center;gap:var(--control-gap);height:var(--control-h);padding:0 var(--control-px);border-radius:var(--control-radius);color:var(--text-secondary);font-size:var(--text-sm);white-space:nowrap;transition:background var(--motion-fast) var(--ease), color var(--motion-fast) var(--ease);background:0 0;border:0;line-height:1;display:inline-flex}.btn:hover,.btn.is-on{background:var(--bg-muted);color:var(--text)}.btn[aria-disabled=true],.btn:disabled{opacity:.45;pointer-events:none}.btn-icon{width:var(--control-h);padding:0}.btn-accent{background:var(--accent);color:var(--accent-fg)}.btn-float{width:var(--foot-h);height:var(--foot-h);pointer-events:auto;border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--float-bg);box-shadow:var(--shadow-float-sm);-webkit-backdrop-filter:var(--float-blur);backdrop-filter:var(--float-blur);padding:0}.btn-float:hover{background:var(--bg-muted);color:var(--text)}.btn-accent:hover{background:var(--accent);color:var(--accent-fg);filter:brightness(1.08)}.btn-pill{border-radius:var(--radius-xs);background:var(--bg-muted);height:18px;color:var(--text);font-size:var(--text-xs);align-items:center;padding:0 7px;line-height:1;display:inline-flex}.btn:hover .btn-pill,.btn.is-on .btn-pill{background:var(--bg)}.ico{width:var(--icon);height:var(--icon);stroke:currentColor;stroke-width:1.6px;stroke-linecap:round;stroke-linejoin:round;fill:none;flex-shrink:0;display:block}.chip{align-items:center;gap:var(--space-1);padding:2px var(--space-2);border-radius:var(--radius-sm);color:var(--text-tertiary);font-size:var(--text-xs);transition:background var(--motion-fast) var(--ease);background:0 0;display:inline-flex}.chip.is-on{background:var(--bg-muted);color:var(--text-secondary)}.tag{--tone:var(--border-strong);align-items:baseline;gap:var(--space-2);max-width:100%;padding:3px var(--space-3);border-radius:var(--radius-sm);background:var(--bg-subtle);color:var(--text-secondary);font-size:var(--text-sm);line-height:1.4;display:inline-flex}.tag-strong{color:var(--text)}.tag-key{font-size:var(--text-xs);letter-spacing:.06em;text-transform:uppercase;color:var(--text-tertiary)}.tag-note{color:var(--text-tertiary)}.tag-ev{border:1px solid var(--border-strong);border-radius:var(--radius-sm);color:var(--text-secondary);font-size:var(--text-xs);align-items:center;gap:4px;padding:1px 6px 1px 5px;text-decoration:none;display:inline-flex}.tag-ev:hover{border-color:var(--accent);color:var(--accent)}.tag-ev .ico{width:11px;height:11px}.tag[data-tone=pass]{--tone:var(--ok)}.tag[data-tone=fail]{--tone:var(--danger)}.tag[data-tone=attention]{--tone:var(--warn)}.tag[data-tone=working]{--tone:var(--accent)}.tag[data-tone=pass]{background:var(--ok-soft);color:var(--ok)}.tag[data-tone=fail]{background:var(--danger-soft);color:var(--danger)}.tag[data-tone=attention]{background:var(--warn-soft);color:var(--warn)}.tag[data-tone=working]{background:var(--accent-soft);color:var(--accent)}.tag[data-tone] .tag-strong{color:inherit;font-weight:500}.tag[data-tone] .tag-note,.tag[data-tone] .tag-ev{color:var(--text-secondary)}.tag.is-claude-code{background:var(--brand-claude-soft);color:var(--brand-claude)}.tag.is-codex{background:var(--brand-codex-soft);color:var(--brand-codex)}.link{color:var(--text-tertiary);text-decoration:underline;-webkit-text-decoration-color:var(--border-strong);text-decoration-color:var(--border-strong);text-underline-offset:2px;transition:color var(--motion-fast) var(--ease)}.link:hover{color:var(--accent)}.pop{display:inline-flex;position:relative}.pop-panel.is-up{--rise:4px;top:auto;bottom:calc(100% + 6px)}.pop-panel.is-narrow{min-width:0}.pop-panel{z-index:var(--z-drawer);width:max-content;min-width:236px;max-width:320px;padding:var(--space-2);border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg);--rise:-4px;position:absolute;top:calc(100% + 6px);right:0;box-shadow:0 4px 16px #0000001f,0 1px 3px #00000014}.pop-head{align-items:center;gap:var(--space-2);padding:2px var(--space-2) var(--space-2);font-size:var(--text-xs);letter-spacing:.06em;text-transform:uppercase;color:var(--text-tertiary);font-weight:500;display:flex}.pop-help{border:1px solid var(--border-strong);width:20px;height:20px;color:var(--text-tertiary);transition:background var(--motion-fast) var(--ease), color var(--motion-fast) var(--ease);border-radius:50%;place-items:center;margin-left:auto;font-size:10px;line-height:1;display:grid}.pop-help:hover,.pop-help.is-on{background:var(--bg-muted);color:var(--text)}.pop-help .ico{width:12px;height:12px}.pop-note{margin:0 0 var(--space-2);padding:var(--space-2);border-radius:var(--radius-sm);background:var(--bg-subtle);font-size:var(--text-xs);color:var(--text-secondary);line-height:1.45}.opts{border:0;flex-direction:column;margin:0;padding:0;display:flex}.opt{cursor:pointer;gap:var(--space-2);padding:var(--space-2);border-radius:var(--control-radius);text-align:left;transition:background var(--motion-fast) var(--ease);display:flex}.opt:hover{background:var(--bg-muted)}.opt:has(:focus-visible){outline:2px solid var(--accent);outline-offset:-2px}.opt-mark{border:1px solid var(--border-strong);width:12px;height:12px;transition:border-color var(--motion-fast) var(--ease), box-shadow var(--motion-fast) var(--ease);border-radius:50%;flex-shrink:0;margin-top:2px}.opt.is-on .opt-mark{border-color:var(--accent);box-shadow:inset 0 0 0 3px var(--accent)}.opt-text{min-width:0;display:block}.opt-name{font-size:var(--text-sm);color:var(--text-secondary);display:block}.opt.is-on .opt-name{color:var(--text);font-weight:500}.opt-adds{font-size:var(--text-xs);color:var(--text-tertiary);margin-top:1px;line-height:1.4;display:block}.toolbar{align-items:center;gap:2px;display:flex}.toolbar-sep{width:1px;height:16px;margin:0 var(--space-2);background:var(--border)}.app{grid-template-columns:288px minmax(0,1fr);height:100%;display:grid;overflow:hidden}.app.no-side{grid-template-columns:minmax(0,1fr)}.side{--hover-row:var(--bg-muted);border-right:1px solid var(--border);background:var(--bg-subtle);flex-direction:column;min-height:0;display:flex}@media (min-width:901px){.side{transition:none}.side:not(.is-open){position:absolute}}.side-backdrop,.mobile-side-trigger{display:none}.raw-layer,.side-head>[data-modal-initial]{display:contents}.side-head{align-items:center;gap:var(--space-2);min-height:calc(var(--control-h) + var(--space-4));padding:var(--space-2) var(--space-2) var(--space-2) var(--space-3);display:flex}.side-mark{color:var(--text);flex-shrink:0}.side-head-title{font-size:var(--text-sm);color:var(--text);white-space:nowrap;text-overflow:ellipsis;margin-right:auto;font-weight:500;overflow:hidden}.side-head .pop-panel{max-width:236px}.usage{padding:var(--space-1) var(--space-2) var(--space-2);margin:0}.usage>div{justify-content:space-between;align-items:baseline;gap:var(--space-3);display:flex}.usage dt{font-size:var(--text-xs);color:var(--text-tertiary)}.usage dd{font-size:var(--text-xs);color:var(--text-secondary);margin:0}.side-find{padding:0 var(--space-2) var(--space-2);align-items:center;display:flex}.side-find-mark{z-index:1;width:var(--control-h);height:var(--control-h);margin-right:calc(var(--control-h) * -1);color:var(--text-tertiary);pointer-events:none;place-items:center;display:grid;position:relative}.side-find-field{padding-left:var(--control-h);flex:1}.side-find-clear{margin-left:var(--space-1);flex-shrink:0}.side-scroll{min-height:0;padding:0 var(--space-2) var(--space-4);flex:1;overflow-y:auto}.side-none,.side-hidden{margin:var(--space-3) 0 0;padding:0 var(--space-2);font-size:var(--text-xs);color:var(--text-tertiary)}.side-none{color:var(--text-secondary)}.side-section+.side-section{margin-top:var(--space-4)}.side-section-h{font-size:inherit;font-weight:inherit;letter-spacing:normal;margin:0}.side-section-head{align-items:center;gap:var(--space-2);width:100%;padding:var(--space-1) var(--space-2);font-size:var(--text-xs);color:var(--text-tertiary);text-align:left;margin:0;font-weight:500;display:flex}.side-section-head .num{font-variant-numeric:tabular-nums;margin-left:auto}.side-section-head.is-toggle:hover{color:var(--text-secondary)}.session-list{margin:0;padding:0;list-style:none}.session-list.is-quiet .session-title{font-family:var(--font-mono);color:var(--text-tertiary)}.side-empty{padding:var(--space-4);font-size:var(--text-sm);color:var(--text-secondary)}.side-empty p{margin:0 0 var(--space-2)}.side-error{margin:var(--space-2);padding:var(--space-2) var(--space-3);border-radius:var(--radius-sm);background:var(--danger-soft);color:var(--danger);font-size:var(--text-sm)}.side-error p{margin:0}.side-error p+p{margin-top:var(--space-1)}.side-error-title{font-weight:500}.marks-key dl{gap:var(--space-1);padding:0 var(--space-2) var(--space-1);margin:0;display:grid}.marks-key dl>div{align-items:center;gap:var(--space-2);font-size:var(--text-sm);color:var(--text-secondary);display:flex}.marks-key dt{place-items:center;width:22px;margin:0;display:grid}.marks-key dd{margin:0}.marks-key .attn-badge{height:15px;padding:0 5px 0 3px;font-size:10px}.marks-key .attn-badge .ico{width:9px;height:9px}.main{min-width:0;height:100%;overflow:hidden}.main-empty{height:100%;color:var(--text-secondary);place-items:center;display:grid}.main-empty-first{gap:var(--space-3);max-width:42ch;padding:0 var(--space-4);text-align:center;flex-direction:column;display:flex}.main-empty-first p{margin:0}.main-empty-first .link{align-self:center}.session-row{align-items:center;gap:var(--space-2);width:100%;height:var(--row-h);padding:0 var(--space-2);border-radius:var(--radius-md);color:var(--text-secondary);text-align:left;transition:background var(--motion-fast) var(--ease);display:flex}.session-row:hover{background:var(--hover-row)}.session-row.is-selected{background:var(--bg-muted);color:var(--text)}.session-title{min-width:0;font-size:var(--text-sm);white-space:nowrap;text-overflow:ellipsis;flex:1;overflow:hidden}.is-selected .session-title{font-weight:500}.session-when{font-size:var(--text-xs);color:var(--text-tertiary);font-variant-numeric:tabular-nums;flex-shrink:0}.attn-badge{border-radius:var(--radius-xs);background:var(--bg-muted);height:18px;color:var(--text-tertiary);font-size:var(--text-xs);flex-shrink:0;align-items:center;gap:3px;padding:0 6px 0 4px;line-height:1;display:inline-flex}.attn-badge .ico{width:11px;height:11px}.session-row:hover .attn-badge,.session-row.is-selected .attn-badge{background:var(--bg)}.attn-badge.is-live{background:var(--warn-soft);color:var(--warn)}.status-dot{font-size:9px;line-height:1}.status-dot.st-working{color:var(--ok)}.status-dot.st-waiting{color:var(--warn)}.status-dot.st-idle,.status-dot.st-ended,.status-dot.st-unknown{color:var(--text-tertiary)}.session{grid-template-rows:minmax(0,1fr);grid-template-columns:minmax(0,1fr);height:100%;display:grid;overflow:hidden}.session.has-inspector{grid-template-columns:minmax(0,1fr) 320px}.session-foot{--rise:var(--space-2);z-index:var(--z-float);padding:0 var(--page-gutter) var(--space-4);pointer-events:none;justify-content:center;align-items:center;display:flex;position:absolute;bottom:0;left:0;right:0}.session-foot:empty{padding:0}.session-main{--page-gutter:var(--space-6);--foot-space:0px;flex-direction:column;min-width:0;min-height:0;display:flex;position:relative}.session-content{min-width:0;min-height:0;padding:0 var(--page-gutter) calc(var(--space-10) + var(--foot-space));scrollbar-gutter:stable both-edges;flex:1;overflow-y:auto}.session-actions{z-index:var(--z-toolbar);align-items:center;gap:var(--space-4);padding:var(--space-2) var(--space-3);background:var(--bg);display:flex;position:sticky;top:0}.session-actions-end{flex-wrap:wrap;justify-content:flex-end;margin-left:auto}.page{max-width:var(--page-w);padding-top:var(--space-10);margin:0 auto;container:page/inline-size}.masthead{text-align:center}.masthead-mark{color:var(--text-tertiary);margin:0 auto;display:block}.brand-lockup{color:inherit;font-family:var(--font-sans);align-items:center;gap:.48em;display:inline-flex}.brand-lockup-mark{flex-shrink:0}.brand-lockup-name{line-height:1}.masthead-title{max-width:42ch;margin:var(--space-4) auto 0;font-size:var(--text-display);letter-spacing:-.02em;text-wrap:balance;font-weight:300;line-height:1.12}.masthead-meta{justify-content:center;gap:var(--space-2);margin:var(--space-4) 0 0;flex-wrap:wrap;display:flex}.tag.is-status{align-items:center;gap:5px}.masthead-path{text-overflow:ellipsis;white-space:nowrap;direction:rtl;max-width:46ch;overflow:hidden}.masthead-badges{justify-content:center;align-items:stretch;gap:var(--space-2);margin-top:var(--space-3);padding-bottom:var(--space-8);border-bottom:1px solid var(--border);flex-wrap:wrap;display:flex}.fresh{height:var(--control-h);margin-right:var(--space-2);padding:0 var(--control-px);border-radius:var(--control-radius);background:var(--accent-soft);color:var(--accent);font-size:var(--text-xs);white-space:nowrap;transition:background var(--motion-fast) var(--ease);align-items:center;display:inline-flex}.fresh:hover{background:var(--accent);color:var(--accent-fg)}.timeline{--tl-lane:9px;max-width:var(--measure);margin-bottom:var(--space-8)}.tl-track{height:18px;margin-bottom:var(--tl-lane);border-bottom:1px solid var(--border);position:relative}.tl-marks{position:absolute;inset:0}.tl-mark{background:var(--text-tertiary);border-radius:0 0 1px 1px;width:2px;height:5px;margin-left:-1px;position:absolute;top:100%}.tl-mark.tl-pass{background:var(--ok);height:5px}.tl-mark.tl-fail{width:3px;height:var(--tl-lane);background:var(--danger);margin-left:-1.5px}.tl-mark.tl-commit{background:var(--text-secondary);border-radius:0;width:5px;height:5px;margin-left:-2.5px;top:calc(100% + 1px);transform:rotate(45deg)}.tl-future{background:var(--bg);opacity:.66;pointer-events:none;position:absolute;top:0;bottom:0;right:0}.tl-range{appearance:none;cursor:ew-resize;background:0 0;width:100%;height:100%;margin:0;position:absolute;inset:0}.tl-range::-webkit-slider-thumb{border:3px solid var(--bg);background:var(--text);width:16px;height:16px;box-shadow:var(--shadow-float-sm);appearance:none;cursor:grab;border-radius:50%}.tl-range::-moz-range-thumb{border:3px solid var(--bg);background:var(--text);width:16px;height:16px;box-shadow:var(--shadow-float-sm);cursor:grab;border-radius:50%}.tl-range:active::-webkit-slider-thumb{cursor:grabbing}.tl-range:focus-visible{outline:none}.tl-range:focus-visible::-webkit-slider-thumb{outline:2px solid var(--accent);outline-offset:2px}.tl-range:focus-visible::-moz-range-thumb{outline:2px solid var(--accent);outline-offset:2px}.tl-stem{background:var(--text-tertiary);pointer-events:none;width:2px;position:absolute;top:0;bottom:0}.tl-legend{justify-content:space-between;align-items:baseline;gap:var(--space-3);margin-top:var(--space-2);font-size:var(--text-xs);color:var(--text-tertiary);display:flex}.tl-legend-mid{align-items:baseline;gap:var(--space-2);display:flex}.tl-legend-mid strong{color:var(--text-secondary);font-weight:400}.viz-title{align-items:baseline;gap:var(--space-2);margin-bottom:var(--space-3);font-size:var(--text-xs);letter-spacing:.09em;text-transform:uppercase;color:var(--text-tertiary);font-weight:500;display:flex}.viz-count{font-family:var(--font-mono);letter-spacing:0;color:var(--text-secondary)}.viz-foot{margin:var(--space-2) 0 0;font-size:var(--text-xs);color:var(--text-tertiary)}.flow{margin:0;padding:0;list-style:none}.flow-turn+.flow-turn{margin-top:var(--space-4)}.flow-ask{align-items:baseline;gap:var(--space-2);width:100%;margin:0 0 var(--space-2);padding:2px var(--space-2) 2px 0;border-radius:var(--radius-sm);text-align:left;transition:background var(--motion-fast) var(--ease);display:flex}.flow-ask:hover{background:var(--hover-row)}.flow-sum{font-size:var(--text-xs);color:var(--text-tertiary);white-space:nowrap;flex-shrink:0;margin-left:auto}.flow-sum-ok{color:var(--ok)}.flow-sum-bad{color:var(--danger)}.flow-sum-gap{color:var(--warn)}.flow{--flow-marker:18px;--flow-indent:calc(var(--flow-marker) / 2);--flow-gutter:var(--space-5)}.flow-ask-n{width:var(--flow-marker);height:var(--flow-marker);background:var(--bg-muted);color:var(--text-secondary);font-family:var(--font-mono);font-size:var(--text-xs);line-height:var(--flow-marker);text-align:center;border-radius:50%;flex-shrink:0}.flow-ask-text{font-size:var(--text-sm);color:var(--text-secondary);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.flow-steps{margin:0 0 0 var(--flow-indent);padding:var(--space-1) 0 var(--space-1) var(--flow-gutter);border-left:1px solid var(--border);list-style:none}.flow-step{align-items:baseline;gap:var(--space-2);padding:2px 0;display:flex;position:relative}.flow-node{left:calc((var(--flow-gutter) + var(--flow-indent)) * -1);box-sizing:border-box;width:var(--flow-marker);height:var(--flow-marker);border:1px solid var(--border);background:var(--bg);color:var(--text-tertiary);font-family:var(--font-mono);font-size:10px;line-height:calc(var(--flow-marker) - 2px);text-align:center;border-radius:50%;position:absolute}.flow-label{font-size:var(--text-sm);color:var(--text-secondary);text-align:left}:is(.flow-step:has(.flow-label.as-button:hover),.flow-step:has(.flow-label.as-button:focus-visible)){background:var(--hover-row)}.flow-label.as-button:focus-visible{outline:none}.flow-detail{margin-left:var(--space-2);font-size:var(--text-xs);color:var(--text-tertiary)}.flow-at{padding-left:var(--space-3);font-size:var(--text-xs);color:var(--text-tertiary);margin-left:auto}.flow-derived{margin-left:var(--space-2);font-size:var(--text-xs);color:var(--text-tertiary);border-bottom:1px dashed var(--border-strong)}.flow-step.is-check .flow-label{color:var(--text)}.flow-step.is-check.v-pass .flow-node{border-color:var(--ok);color:var(--ok)}.flow-step.is-check.v-fail .flow-node{border-color:var(--danger);color:var(--danger)}.flow-step.is-check.v-unknown .flow-node,.flow-step.is-check.v-partial .flow-node{border-color:var(--warn);color:var(--warn)}.flow-step.is-commit .flow-node{border-color:var(--accent);color:var(--accent)}.flow-step.is-gap .flow-node{border-style:dashed;border-color:var(--warn);color:var(--warn)}.flow-step.is-gap .flow-label{color:var(--warn)}.flow-step.is-quiet .flow-label,.flow-step.is-quiet .flow-node{color:var(--text-tertiary);border-color:var(--border)}.flow-more{margin-bottom:var(--space-3);font-size:var(--text-xs);color:var(--text-tertiary);text-underline-offset:2px;text-decoration:underline}.churn{margin:0;padding:0;list-style:none}.churn-main{align-items:center;gap:var(--space-3);text-align:left;grid-template-columns:minmax(0,15ch) minmax(0,1fr) 11ch 1ch;width:100%;padding:3px 0;display:grid}.churn-main:hover .churn-name{color:var(--text)}.churn-name{align-items:baseline;gap:var(--space-2);font-size:var(--text-xs);color:var(--text-secondary);white-space:nowrap;display:flex;overflow:hidden}.churn-dir{min-width:0;color:var(--text-tertiary);text-overflow:ellipsis;overflow:hidden}.churn-bar{background:var(--bg-subtle);border-radius:2px;height:9px;display:flex;overflow:hidden}.churn-add{background:var(--ok)}.churn-del{background:var(--danger)}.churn-num{justify-content:flex-end;gap:var(--space-2);font-family:var(--font-mono);font-size:var(--text-xs);display:flex}.churn-flag{color:var(--warn);font-family:var(--font-mono);font-size:var(--text-xs);text-align:center}.lane{align-items:center;gap:var(--space-3);grid-template-columns:9ch minmax(0,1fr) 2ch;height:22px;display:grid}.viz-root{margin:0 0 var(--space-2);font-size:var(--text-xs);color:var(--text-tertiary);overflow-wrap:anywhere}.sections{max-width:var(--measure);margin-top:var(--space-8);border-top:1px solid var(--border)}.sec{border-bottom:1px solid var(--border)}.chev{color:var(--text-tertiary);transition:transform var(--motion-base) var(--ease);display:inline-block}.chev.is-open{transform:rotate(90deg)}.sec-review{max-width:var(--measure);margin-bottom:var(--space-8);border-bottom:0}.rows{margin:0;padding:0;list-style:none}.row{gap:var(--space-2);padding:var(--space-2) 0 var(--space-2) var(--space-3);border-left:2px solid var(--border);display:flex}.row+.row{border-top:1px solid var(--bg-muted)}.row.ep-inferred{background-position:0 0;background-repeat:no-repeat;background-size:2px 100%;background-image:repeating-linear-gradient(var(--border-strong) 0 8px, transparent 8px 13px);border-left-color:#0000}.row-flat{font-size:var(--text-sm);align-items:baseline}.bad{color:var(--danger)}.bad-title{margin:0 0 var(--space-1);font-weight:500}.bad p+button{margin-top:var(--space-3)}.running{color:var(--accent)}.disclosure{margin-top:var(--space-3)}.disclosure-toggle{align-items:center;gap:var(--space-2);font-size:var(--text-sm);color:var(--text-secondary);display:flex}.disclosure-toggle:hover{color:var(--text)}.disclosure-body{visibility:hidden;transition:grid-template-rows var(--motion-base) var(--ease), visibility var(--motion-base) var(--ease);grid-template-rows:0fr;display:grid}.disclosure-body>*{overflow:hidden}.disclosure-body.is-open{visibility:visible;grid-template-rows:1fr}.turns{margin:0;padding:0;list-style:none}.turn{padding:var(--space-3) 0;border-top:1px solid var(--bg-muted)}.turn:first-child{border-top:0}.activities{margin:var(--space-2) 0 0;padding:0;list-style:none}.activity{border-left:2px solid var(--border)}.inspector{border-left:1px solid var(--border);background:var(--bg-subtle);flex-direction:column;min-width:0;min-height:0;display:flex}.inspector-head{align-items:center;gap:var(--space-1);min-height:calc(var(--control-h) + var(--space-4));padding:var(--space-2) var(--space-3) var(--space-2) var(--space-2);display:flex}.inspector-title{font-size:var(--text-sm);color:var(--text);white-space:nowrap;margin-left:auto;font-weight:500}.inspector-title .num{margin-left:var(--space-1);color:var(--text-tertiary);font-weight:400}.htab{min-height:0;padding:0 var(--space-6) calc(var(--space-4) + var(--foot-space));flex-direction:column;flex:1;display:flex}.htab-head{align-items:center;gap:var(--space-3);padding:var(--space-5) 0 var(--space-4);flex-wrap:wrap;display:flex}.htab-title{font-size:var(--text-lg);margin-right:auto;font-weight:500}.htab-title .num{margin-left:var(--space-2);color:var(--text-tertiary);font-weight:400}.htab-grid{flex-direction:column;flex:1;min-height:0;display:flex}.htab-row{align-items:baseline;gap:var(--space-4);padding:var(--space-2) var(--space-3);border-radius:var(--control-radius);text-align:left;grid-template-columns:64px 112px minmax(0,1fr) 96px 64px;display:grid}.htab-row.is-head{border-bottom:1px solid var(--border);font-size:var(--text-xs);letter-spacing:.06em;text-transform:uppercase;color:var(--text-tertiary);border-radius:0;flex-shrink:0;font-weight:500}.htab-scroll{flex:1;min-height:0;overflow-y:auto}.htab-row:not(.is-head):hover{background:var(--hover-row)}.htab-row.is-scrub{background:var(--accent-soft)}.htab-row.is-future{opacity:.4}.htab-when{color:var(--text-tertiary);font-size:var(--text-sm);text-align:left}.htab-when:hover{color:var(--accent)}.htab-kind{align-items:center;gap:var(--space-2);font-size:var(--text-sm);color:var(--text-secondary);display:flex}.htab-text{font-size:var(--text-sm);overflow-wrap:anywhere;line-height:1.45}.htab-prov{font-size:var(--text-xs);color:var(--text-tertiary)}.history-scope{gap:var(--space-1);padding:0 var(--space-2) var(--space-2);flex-wrap:wrap;display:flex}.pop-panel.is-left{left:0;right:auto}.opt-swatch{border:1.5px solid var(--facet,var(--border-strong));border-radius:var(--radius-xs);width:12px;height:12px;transition:background var(--motion-fast) var(--ease);background:0 0;flex-shrink:0}.opt.is-on .opt-swatch{background:var(--facet,var(--border-strong))}.opt.is-tight{align-items:center;gap:var(--space-3);padding:5px var(--space-2)}.history-list{min-height:0;padding:0 var(--space-2) var(--space-4);overscroll-behavior:contain;flex:1;overflow-y:auto}.facet-status{--facet:var(--gray-6)}.facet-what{--facet:var(--accent)}.facet-why{--facet:var(--facet-why)}.facet-how{--facet:var(--facet-how)}.facet-verified{--facet:var(--ok)}.facet-left{--facet:var(--gray-7)}.facet-review{--facet:var(--warn)}.hist-item{padding:2px 0;position:relative}.hist-item.is-future{opacity:.35}.hist-main{width:100%;padding:var(--space-2);border-radius:var(--control-radius);text-align:left;transition:background var(--motion-fast) var(--ease);display:block}.hist-main:hover{background:var(--bg-muted)}.hist-item.is-scrub .hist-main{background:var(--accent-soft)}.hist-meta{align-items:center;gap:var(--space-2);font-size:var(--text-xs);color:var(--text-tertiary);white-space:nowrap;display:flex}.hist-prov{border-bottom:1px dashed var(--border-strong);line-height:1.2}.hist-dot{background:var(--facet,var(--border-strong));border-radius:50%;flex-shrink:0;width:6px;height:6px}.hist-facet{color:var(--text-secondary)}.hist-time{font-variant-numeric:tabular-nums;margin-left:auto}.hist-text{font-size:var(--text-sm);color:var(--text);overflow-wrap:anywhere;margin-top:3px;line-height:1.4;display:block}.hist-record{right:var(--space-2);bottom:var(--space-2);font-size:var(--text-xs);opacity:0;transition:opacity var(--motion-fast) var(--ease);position:absolute}.hist-item:hover .hist-record,.hist-record:focus-visible{opacity:1}.prov{font-size:var(--text-xs);color:var(--text-tertiary)}.gate{height:100%;padding:var(--space-8) var(--space-6);flex-direction:column;justify-content:safe center;align-items:center;display:flex;overflow-y:auto}.gate-inner{width:100%;max-width:46ch}.gate-mark{margin:0 0 var(--space-6);font-size:var(--text-xl);font-weight:300}.gate-lede{margin:0 0 var(--space-2);font-size:var(--text-md)}.gate-note{margin:0 0 var(--space-6);color:var(--text-secondary)}.gate-cmd{align-items:center;gap:var(--space-2);padding:var(--space-2);padding-left:var(--space-4);border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg-muted);display:flex}.gate-cmd code{min-width:0;font-family:var(--font-mono);font-size:var(--text-sm);white-space:nowrap;scrollbar-width:none;flex:1;overflow-x:auto}.gate-cmd code::-webkit-scrollbar{display:none}.gate-hint{margin:var(--space-2) 0 0;font-size:var(--text-sm);color:var(--text-tertiary)}.gate-paste{gap:var(--space-2);margin-top:var(--space-6);padding-top:var(--space-6);border-top:1px solid var(--border);display:flex}.gate-field{font-family:var(--font-mono);flex:1}.gate-field::placeholder{font-family:var(--font-sans)}.gate-bad{margin:var(--space-3) 0 0;color:var(--danger);font-size:var(--text-sm)}.gate-bad code{font-family:var(--font-mono)}.session-error{text-align:left;max-width:52ch}.session-error-title{margin:0 0 var(--space-2);font-size:var(--text-md)}.session-error-actions{gap:var(--space-2);margin-top:var(--space-4);display:flex}.drawer{z-index:var(--z-drawer);border-top:1px solid var(--border);border-left:1px solid var(--border);background:var(--bg);width:min(760px,100vw);max-height:70vh;box-shadow:var(--shadow);flex-direction:column;display:flex;position:fixed;bottom:0;right:0}.drawer-head{justify-content:space-between;align-items:center;gap:var(--space-3);padding:var(--space-2) var(--space-3) var(--space-2) var(--space-4);border-bottom:1px solid var(--border);display:flex}.drawer-title{min-width:0;font-size:var(--text-md);white-space:nowrap;text-overflow:ellipsis;margin:0;overflow:hidden}.drawer-acts{align-items:center;gap:var(--space-1);flex-shrink:0;display:flex}.drawer-panes{align-items:center;gap:var(--space-1);padding:var(--space-2) var(--space-4);border-bottom:1px solid var(--border);display:flex}.drawer-id{min-width:0;font-size:var(--text-xs);color:var(--text-tertiary);white-space:nowrap;text-overflow:ellipsis;margin-left:auto;overflow:hidden}.drawer-body{padding:var(--space-4);overflow:auto}.drawer-sub{margin:var(--space-5) 0 var(--space-2);font-size:var(--text-xs);letter-spacing:.06em;color:var(--text-tertiary);text-transform:uppercase;font-weight:500}.facts{margin:0}.fact{gap:var(--space-3);grid-template-columns:8.5em minmax(0,1fr);padding:3px 0;display:grid}.fact.is-block{padding:var(--space-2) 0;grid-template-columns:minmax(0,1fr);gap:2px}.fact-label{font-size:var(--text-xs);color:var(--text-tertiary);margin:0}.fact-value{align-items:baseline;gap:2px var(--space-2);min-width:0;font-size:var(--text-sm);overflow-wrap:anywhere;flex-wrap:wrap;margin:0;display:flex}.fact.is-block .fact-value{padding:var(--space-2) var(--space-3);border-radius:var(--radius-sm);background:var(--bg-subtle);white-space:pre-wrap;overflow-wrap:anywhere;display:block}.fact-note{font-size:var(--text-xs);color:var(--text-tertiary)}.fact.is-block .fact-note{margin-top:var(--space-1);font-family:var(--font-sans);display:block}.fact-copy{opacity:0;transition:opacity var(--motion-fast) var(--ease);flex-shrink:0}.fact:hover .fact-copy,.fact-copy:focus-visible{opacity:1}.fact.is-block .fact-copy{float:right;margin-left:var(--space-2)}@media (max-width:560px){.fact{padding:var(--space-2) 0;grid-template-columns:minmax(0,1fr);gap:0}}.drawer-full{margin-top:var(--space-5);padding-top:var(--space-3);border-top:1px solid var(--border)}.drawer-full summary{font-size:var(--text-xs);color:var(--text-tertiary);cursor:pointer}.drawer-full summary:hover{color:var(--text-secondary)}.drawer-full pre{margin-top:var(--space-3)}.drawer-body pre{font-size:var(--text-xs);white-space:pre-wrap;overflow-wrap:anywhere;margin:0;line-height:1.5}.diff{margin:var(--space-2) 0;border:1px solid var(--border);border-radius:var(--radius-sm);font-size:var(--text-xs);line-height:1.5;overflow-x:auto}.diff-add{background:var(--diff-add-bg)}.diff-del{background:var(--diff-del-bg)}.muted{color:var(--text-tertiary)}.sr-only{clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;margin:-1px;padding:0;position:fixed;top:0;left:0;overflow:hidden}@media (max-width:900px){.app{grid-template-columns:minmax(0,1fr)}.side{z-index:calc(var(--z-panel) + 1);width:min(320px,100vw - 48px);box-shadow:var(--shadow-float);--slide:-12px;display:flex;position:fixed;inset:0 auto 0 0}.side-backdrop{z-index:var(--z-panel);cursor:default;background:#00000052;border:0;width:100%;height:100%;padding:0;display:block;position:fixed;inset:0}.mobile-side-trigger{top:var(--space-2);left:var(--space-2);z-index:calc(var(--z-toolbar) + 1);display:block;position:fixed}.app.no-side .session-actions>.btn:first-child{display:none}.app.no-side .session-actions{padding-left:calc(var(--space-2) + var(--control-h) + var(--space-2))}.session.has-inspector{grid-template-rows:minmax(0,1fr) minmax(0,min(320px,40%));grid-template-columns:minmax(0,1fr)}.inspector{border-top:1px solid var(--border);border-left:0}.session-main{--page-gutter:var(--space-4)}.page{padding-top:var(--space-6)}.masthead-title{font-size:var(--text-xl)}.masthead-path{max-width:30ch}}.report{margin-top:var(--space-10)}.rp-cols{gap:var(--space-6) var(--space-8);grid-template-columns:repeat(3,minmax(0,1fr));align-items:start;display:grid}.rp-cols>*{min-width:0}.rp-title{margin-bottom:var(--space-3);font-size:var(--text-xs);letter-spacing:.1em;text-transform:uppercase;color:var(--text-tertiary);font-weight:500}.rp-statement{margin:0 0 var(--space-3);padding-left:var(--space-3);border-left:2px solid var(--border);font-size:var(--text-sm);color:var(--text)}.rp-statement-body{-webkit-line-clamp:4;line-clamp:4;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.rp-statement-body.is-open{display:block;overflow:visible}.rp-ev{margin-left:var(--space-2);font-size:var(--text-xs)}.rp-none{font-size:var(--text-sm);color:var(--text-tertiary);margin:0}.rp-status{margin:0 0 var(--space-3);font-size:var(--text-sm);padding:0;list-style:none}.rp-status li{gap:var(--space-2);flex-wrap:wrap;align-items:baseline;padding:2px 0;display:flex}.rp-mark{width:1em;font-family:var(--font-mono);color:var(--text-tertiary);text-align:center;flex-shrink:0}.rp-status .v-pass .rp-mark{color:var(--ok)}.rp-status .v-fail .rp-mark{color:var(--danger)}.rp-status .is-attn .rp-mark{color:var(--warn)}.rp-status-label{text-align:left;color:inherit}.rp-counts{margin-left:var(--space-2);color:var(--text-tertiary)}.rp-derived{font-size:var(--text-xs);color:var(--text-tertiary);border-bottom:1px dashed var(--border-strong)}.rp-subset,.rp-caveat{font-size:var(--text-xs);color:var(--text-tertiary)}.rp-stale{margin-left:var(--space-2);font-size:var(--text-xs);color:var(--warn);white-space:nowrap}.rp-group{align-items:start}.rp-group-body{flex:1;min-width:0}.rp-group-head{align-items:baseline;gap:var(--space-3);text-align:left;width:100%;color:inherit;display:flex}.rp-group-label{min-width:0}.rp-group-count{color:var(--text-tertiary);white-space:nowrap;margin-left:auto}.rp-group-distinct{font-family:var(--font-sans)}.rp-group-head:hover{background:var(--hover-row)}.rp-group-items{margin:var(--space-1) 0 0;padding:0 0 0 var(--space-1);border-left:1px solid var(--border);list-style:none}.rp-group-items li{align-items:baseline;gap:var(--space-2);padding:2px 0 2px var(--space-3);color:var(--text-secondary);display:flex}.rp-group-items .mono{overflow-wrap:break-word;min-width:0}.rp-group-repeats{color:var(--text-tertiary);flex-shrink:0}.rp-empty{max-width:var(--measure);margin:var(--space-6) 0;font-size:var(--text-sm);color:var(--text-tertiary)}.quantities-body{min-height:0;padding:var(--space-2) var(--space-5) var(--space-6);overflow-y:auto}.tm{min-width:0}.tm-group{padding:var(--space-5) 0}.tm-group:first-child{padding-top:var(--space-3)}.tm-group+.tm-group{border-top:1px solid var(--border)}.tm-title{margin:0 0 var(--space-4);font-size:var(--text-xs);letter-spacing:.08em;text-transform:uppercase;color:var(--text-tertiary);font-weight:500}.tm-grid{gap:var(--space-2);grid-template-columns:repeat(3,minmax(0,1fr));margin:0;display:grid}.tm-grid.is-wide{grid-template-columns:repeat(2,minmax(0,1fr))}.tm-grid.is-wide dd{white-space:nowrap;overflow-x:auto}.tm-quantity{flex-direction:column;min-width:0;display:flex}.tm-quantity dt{margin-top:var(--space-2);font-size:var(--text-xs);color:var(--text-tertiary)}.tm-quantity dd{font-family:var(--font-mono);font-size:var(--text-lg);color:var(--text);overflow-wrap:anywhere;order:-1;margin:0;line-height:1.15}.tm .num{font-family:var(--font-mono);color:var(--text)}.tm-unknown{font-family:var(--font-sans);font-size:var(--text-sm);color:var(--text-tertiary)}.tm-add{color:var(--ok);font-family:var(--font-mono)}.tm-del{color:var(--danger);font-family:var(--font-mono)}.tm .v-pass{color:var(--ok)}.tm .v-fail{color:var(--danger)}.tm .v-partial,.tm .v-unknown{color:var(--warn)}.tm-check{align-items:baseline;gap:var(--space-2);font-size:var(--text-sm);color:var(--text);grid-template-columns:minmax(0,1fr) auto auto;display:grid}.tm-check-method{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.tm-check>[class^=v-]{padding:2px var(--space-2);border-radius:var(--radius-xs);background:var(--bg-muted);font-size:var(--text-xs);letter-spacing:.05em;text-transform:uppercase;font-weight:600}.tm-note-list{gap:var(--space-2);font-size:var(--text-xs);color:var(--text-tertiary);margin:0;padding:0;list-style:none;display:grid}.tm-note-list li{padding-left:var(--space-4);position:relative}.tm-note-list li:before{content:"";background:currentColor;border-radius:50%;width:4px;height:4px;position:absolute;top:.55em;left:0}.ex{margin:var(--space-8) calc(var(--page-gutter) * -1) 0;padding:var(--space-6) var(--page-gutter) var(--space-5);background:var(--bg-subtle)}.ex-what{max-width:56ch;font-size:var(--text-xl);letter-spacing:-.01em;text-align:center;text-wrap:pretty;margin:0 auto;font-weight:300;line-height:1.35}.ex-now{gap:var(--space-2);max-width:68ch;margin:var(--space-4) auto 0;font-size:var(--text-sm);color:var(--text-secondary);text-align:center;justify-content:center;align-items:baseline;display:flex}.ex-now-key{font-size:var(--text-xs);letter-spacing:.08em;text-transform:uppercase;color:var(--text-tertiary);flex-shrink:0}.ex-block{margin-top:var(--space-10)}.ex-head{margin-bottom:var(--space-6)}.ex-title{padding-bottom:var(--space-2);border-bottom:1px solid var(--border-strong);font-size:var(--text-xs);letter-spacing:.14em;text-transform:uppercase;color:var(--text-secondary);font-weight:500}.ex-summary{max-width:var(--measure);margin:var(--space-3) 0 0;font-size:var(--text-sm);color:var(--text-secondary)}.ex-foot{justify-content:space-between;align-items:baseline;gap:var(--space-3) var(--space-6);margin-top:var(--space-8);padding-top:var(--space-3);border-top:1px dashed var(--border-strong);flex-wrap:wrap;display:flex}.ex-mark{font-size:var(--text-xs);color:var(--text-tertiary);margin:0}.ex-pending{max-width:var(--measure);margin:var(--space-8) auto 0;padding:var(--space-5);border:1px dashed var(--border-strong);border-radius:var(--radius-md);font-size:var(--text-sm);color:var(--text-tertiary);text-align:center}.ex-pending p{margin:0}.ex-pending-main{font-size:var(--text-md);color:var(--text-secondary);margin-bottom:var(--space-2)!important}.ex-pending.is-running{border-style:solid;border-color:var(--border)}.shimmer{background:linear-gradient(90deg, var(--text-tertiary) 0%, var(--text-tertiary) 35%, var(--text) 50%, var(--text-tertiary) 65%, var(--text-tertiary) 100%) 0 0 / 300% 100%;color:#0000;-webkit-background-clip:text;background-clip:text;animation:2.4s linear infinite shimmer}@keyframes shimmer{0%{background-position:100% 0}to{background-position:-100% 0}}@media (prefers-reduced-motion:reduce){.shimmer{color:var(--text-secondary);background:0 0}.ex-pending.is-running{border-color:var(--border-strong)}}.fd-node{padding:var(--space-3) var(--space-3);border:1px solid var(--border-strong);border-radius:var(--radius-sm);background:var(--bg);font-size:var(--text-sm);text-wrap:pretty;line-height:1.35;position:relative}.fd-chain{gap:var(--space-6);margin:0;padding:0;list-style:none;display:flex}.fd-chain>.fd-node{flex:1 1 0;min-width:0}.fd-chain>.fd-node+.fd-node:before{content:"";top:50%;left:calc(var(--space-6) * -1 - 1px);width:var(--space-6);background:var(--border-strong);height:1px;position:absolute}.fd-chain>.fd-node+.fd-node:after{content:"";border-left:7px solid var(--border-strong);border-top:4px solid #0000;border-bottom:4px solid #0000;margin-top:-4px;position:absolute;top:50%;left:-8px}.fd-chain.end-accent>.fd-node:last-child{border-color:var(--accent);color:var(--text)}.fd-chain.end-good>.fd-node:last-child{border-color:var(--ok)}.fd-chain.end-bad>.fd-node:last-child{border-color:var(--danger)}.fd-converge,.fd-tree{--fd-pad:var(--space-3)}.fd-lanes{margin:0 calc(var(--fd-pad) * -1);display:grid}.fd-lane{min-width:0;margin:0 var(--fd-pad);padding:var(--space-3) var(--space-4) var(--space-4);border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--bg)}.fd-lane-title{margin:0 0 var(--space-3);padding-bottom:var(--space-2);border-bottom:1px solid var(--border);font-size:var(--text-xs);letter-spacing:.08em;text-transform:uppercase;color:var(--text-secondary);font-weight:500}.fd-lane-steps{margin:0;padding:0;list-style:none}.fd-lane-steps li{padding:var(--space-1) 0 var(--space-1) var(--space-4);font-size:var(--text-sm);color:var(--text-secondary);position:relative}.fd-lane-steps li:before{content:"";background:var(--border);width:1px;position:absolute;top:0;bottom:0;left:3px}.fd-lane-steps li:first-child:before{top:50%}.fd-lane-steps li:last-child:before{bottom:50%}.fd-lane-steps li:after{content:"";background:var(--border-strong);border-radius:50%;width:7px;height:7px;margin-top:-3px;position:absolute;top:50%;left:0}.fd-junction{height:52px;margin:var(--space-2) calc(var(--fd-pad) * -1);position:relative}.fd-trunk,.fd-bus{background:var(--border-strong);position:absolute}.fd-trunk{width:1px;top:26px;bottom:0;left:50%}.fd-trunk:after{content:"";border-top:7px solid var(--border-strong);border-left:4px solid #0000;border-right:4px solid #0000;position:absolute;bottom:0;left:-4px}.fd-bus{top:26px;left:calc(50% / var(--lanes));right:calc(50% / var(--lanes));height:1px}.fd-stems{grid-template-columns:repeat(var(--lanes), minmax(0, 1fr));height:26px;display:grid;position:absolute;top:0;left:0;right:0}.fd-stems>span{background:var(--border-strong);justify-self:center;width:1px;position:relative}.fd-junction.is-fan .fd-trunk{height:26px;top:0;bottom:auto}.fd-junction.is-fan .fd-trunk:after{display:none}.fd-junction.is-fan .fd-stems{top:26px}.fd-junction.is-fan .fd-stems>span:after{content:"";border-top:7px solid var(--border-strong);border-left:4px solid #0000;border-right:4px solid #0000;position:absolute;bottom:0;left:-4px}.fd-root{width:-moz-fit-content;width:fit-content;max-width:100%;padding:var(--space-2) var(--space-4);border:1px solid var(--border-strong);border-radius:var(--radius-sm);background:var(--bg);font-size:var(--text-sm);color:var(--text);overflow-wrap:anywhere;text-align:center;margin:0 auto;display:block}.fd-branches{margin:0 calc(var(--fd-pad) * -1);padding:0;list-style:none;display:grid}.fd-branches>.fd-node{margin:0 var(--fd-pad)}.fd-ba-label{margin:0 0 var(--space-1);font-size:var(--text-xs);letter-spacing:.08em;text-transform:uppercase;color:var(--text-tertiary)}.fd-ba-head{margin:0 0 var(--space-3);font-size:var(--text-md)}.fd-ba-side.is-was .fd-ba-head{color:var(--text-tertiary)}.fd-ba-side.is-was .fd-node{color:var(--text-tertiary);border-style:dashed}.fd-ba-why{gap:var(--space-3);margin:var(--space-5) 0;padding-left:var(--space-2);font-size:var(--text-sm);color:var(--text-secondary);align-items:center;display:flex}.fd-ba-pivot{background:linear-gradient(var(--warn), var(--warn)) 4px 0 / 1px 20px no-repeat;flex-shrink:0;width:9px;height:26px;position:relative}.fd-ba-pivot:after{content:"";border-top:7px solid var(--warn);border-left:4px solid #0000;border-right:4px solid #0000;position:absolute;bottom:0;left:0}.fd-legend{gap:var(--space-2) var(--space-5);font-size:var(--text-xs);color:var(--text-tertiary);flex-wrap:wrap;margin:0;padding:0;list-style:none;display:flex}.fd-legend li{align-items:center;gap:var(--space-2);display:flex}.fd-key{flex-shrink:0;width:22px;height:10px;position:relative}.fd-key-junction{background:linear-gradient(var(--border-strong), var(--border-strong)) 3px 0 / 1px 5px no-repeat, linear-gradient(var(--border-strong), var(--border-strong)) 18px 0 / 1px 5px no-repeat, linear-gradient(var(--border-strong), var(--border-strong)) 3px 5px / 16px 1px no-repeat, linear-gradient(var(--border-strong), var(--border-strong)) 11px 5px / 1px 5px no-repeat}.fd-key-outcome{background:linear-gradient(var(--danger), var(--danger)) 0 4px / 8px 2px no-repeat, linear-gradient(var(--ok), var(--ok)) 14px 4px / 8px 2px no-repeat}@container page (width<=860px){.fd-chain{gap:var(--space-5);flex-direction:column}.fd-chain>.fd-node+.fd-node:before{top:calc(var(--space-5) * -1 - 1px);left:var(--space-5);width:1px;height:var(--space-5)}.fd-chain>.fd-node+.fd-node:after{top:-8px;left:calc(var(--space-5) - 3px);border-left:4px solid #0000;border-right:4px solid #0000;border-top:7px solid var(--border-strong);border-bottom:0;margin-top:0}.fd-lanes,.fd-branches{gap:var(--space-4);margin:0;grid-template-columns:minmax(0,1fr)!important}.fd-lane,.fd-branches>.fd-node{margin:0}.fd-tree.has-root .fd-root{text-align:left;width:100%;margin:0}.fd-tree.has-root .fd-junction{display:none}.fd-tree.has-root .fd-branches{margin:var(--space-4) 0 0 var(--space-6)}.fd-tree.has-root .fd-branches>.fd-node:before{content:"";top:calc(var(--space-4) * -1);bottom:50%;left:calc(var(--space-6) * -1);background:var(--border-strong);width:1px;position:absolute}.fd-tree.has-root .fd-branches>.fd-node:after{content:"";top:50%;left:calc(var(--space-6) * -1);width:var(--space-6);background:var(--border-strong);height:1px;position:absolute}.fd-junction{height:30px}.fd-stems,.fd-bus{display:none}.fd-junction .fd-trunk,.fd-junction.is-fan .fd-trunk{height:auto;top:0;bottom:0}.fd-junction.is-fan .fd-trunk:after{display:block}.rp-cols{grid-template-columns:minmax(0,1fr)}}.panel-scrim{z-index:var(--z-panel);padding:var(--space-5);justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.panel-backdrop{cursor:default;background:#00000052;border:0;position:absolute;inset:0}.panel-card{border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--bg);width:min(880px,100%);max-height:min(80vh,720px);box-shadow:var(--shadow-float);-webkit-backdrop-filter:var(--float-blur);backdrop-filter:var(--float-blur);flex-direction:column;display:flex;position:relative}.panel-head{justify-content:space-between;align-items:center;gap:var(--space-3);padding:var(--space-4) var(--space-5);border-bottom:1px solid var(--border);display:flex}.panel-title{font-size:var(--text-sm);letter-spacing:.04em;text-transform:uppercase;color:var(--text-secondary);margin:0;font-weight:600}.panel-close{width:var(--control-h);height:var(--control-h);border-radius:var(--control-radius);color:var(--text-secondary);cursor:pointer;background:0 0;border:0;place-items:center;display:grid}.panel-close:hover{background:var(--bg-muted);color:var(--text)}.panel-body{padding:var(--space-5);overflow:auto}.panel-split{grid-template-columns:168px minmax(0,1fr);min-height:0;display:grid}.panel-rail{padding:var(--space-3);border-right:1px solid var(--border);flex-direction:column;gap:2px;display:flex;overflow:auto}.panel-rail-item{justify-content:space-between;align-items:center;gap:var(--space-2);padding:var(--space-2) var(--space-3);border-radius:var(--control-radius);color:var(--text-secondary);font:inherit;font-size:var(--text-sm);text-align:left;cursor:pointer;background:0 0;border:0;display:flex}.panel-rail-item:hover{background:var(--bg-muted);color:var(--text)}.panel-rail-item.is-on{background:var(--bg-muted);color:var(--text);font-weight:600}.panel-rail-count{color:var(--text-tertiary);font-size:var(--text-xs)}.panel-body>.viz>.viz-title,.panel-body>.report .viz-title{display:none}.panel-body>.viz{margin:0}@media (max-width:720px){.panel-split{grid-template-columns:minmax(0,1fr)}.panel-rail{border-right:0;border-bottom:1px solid var(--border);flex-direction:row}}.rp-cols.is-single{display:block}.rp-cols.is-single>.rp-block>.rp-title{display:none}.tag.is-open{cursor:pointer;font:inherit;text-align:left}.tag.is-open:hover{border-color:var(--border-strong)}.cov-lead{margin:0 0 var(--space-2)}.cov-held{margin:0 0 var(--space-2);color:var(--danger)}.cov-scope{margin:0 0 var(--space-3);color:var(--text-tertiary)}.cov-grid{margin:0 0 var(--space-4);flex-wrap:wrap;gap:5px;padding:0;list-style:none;display:flex}.cov-cell{border-radius:var(--radius-xs);background:var(--ok);border:1px solid #0000;width:22px;height:22px;padding:0;display:block}button.cov-cell{cursor:pointer}button.cov-cell:hover{border-color:var(--text)}.cov-cell.is-stale{border-color:var(--warn);background:var(--warn-soft)}.cov-key{gap:var(--space-2) var(--space-4);color:var(--text-secondary);font-size:var(--text-sm);flex-wrap:wrap;margin:0;padding:0;list-style:none;display:flex}.cov-key li{align-items:center;gap:var(--space-2);display:flex}.cov-key .cov-cell{width:14px;height:14px}.cov-key-n{color:var(--text-tertiary)}.cov-more{margin:0 0 var(--space-3);color:var(--text-tertiary);font-size:var(--text-sm)}.checks-rows{align-items:baseline;gap:var(--space-2) var(--space-4);margin:0 0 var(--space-4);grid-template-columns:max-content max-content minmax(0,1fr) max-content max-content;padding:0;list-style:none;display:grid}.checks-row{display:contents}.checks-method{font-weight:600}.checks-now{align-items:baseline;gap:var(--space-1);white-space:nowrap;display:inline-flex}.checks-now.v-pass{color:var(--ok)}.checks-now.v-fail{color:var(--danger)}.checks-counts,.checks-runs,.checks-when{color:var(--text-tertiary);font-size:var(--text-sm);white-space:nowrap}.checks-strip{flex-wrap:wrap;gap:4px;display:flex}.checks-tick{border-radius:var(--radius-xs);background:var(--gray-4);cursor:pointer;border:1px solid #0000;width:14px;height:14px;padding:0}.checks-tick.v-pass{background:var(--ok)}.checks-tick.v-fail{background:var(--danger)}.checks-tick.is-derived{background:0 0}.checks-tick.is-derived.v-pass{border-color:var(--ok)}.checks-tick.is-derived.v-fail{border-color:var(--danger)}.checks-tick.is-derived:not(.v-pass):not(.v-fail){border-color:var(--border-strong)}.checks-tick:hover{outline:2px solid var(--text);outline-offset:1px}.checks-key{color:var(--text-tertiary);font-size:var(--text-xs);margin:0}.flow-ask-caret{width:1em;color:var(--text-tertiary);text-align:center;transition:transform var(--motion-fast) var(--ease);flex-shrink:0}.flow-turn.is-open .flow-ask-caret{transform:rotate(90deg)}.flow-ask-text{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.flow-sum{gap:var(--space-1);flex-wrap:wrap;flex-shrink:0;justify-content:flex-end;margin-left:auto;display:flex}.flow-chip{padding:1px var(--space-2);border-radius:var(--radius-xs);background:var(--bg-muted);color:var(--text-tertiary);font-size:var(--text-xs);white-space:nowrap}.rewind{align-items:center;gap:var(--space-2);width:100%;max-width:var(--page-w);pointer-events:auto;display:flex}.rewind:not(.is-open){position:absolute}.rewind .timeline{min-width:0;max-width:none;padding:var(--space-3) var(--space-4);border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--bg);box-shadow:var(--shadow-float);-webkit-backdrop-filter:var(--float-blur);backdrop-filter:var(--float-blur);flex:1;margin:0}.loading{align-items:center;gap:var(--space-2);display:inline-flex}.orb{width:1em;height:1em;color:inherit;flex-shrink:0}.orb-dot{transform-origin:50%;animation:1.4s ease-in-out infinite orb-pulse}.orb-dot:nth-child(2){animation-delay:.18s}.orb-dot:nth-child(3){animation-delay:.36s}@keyframes orb-pulse{0%,to{opacity:.25;transform:scale(.7)}40%{opacity:1;transform:scale(1)}}@media (prefers-reduced-motion:reduce){.orb-dot{animation:none}.orb-dot:first-child{opacity:1}.orb-dot:nth-child(2){opacity:.6}.orb-dot:nth-child(3){opacity:.3}}
|