@coreplane/switchboard 1.227.0 → 1.228.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/assets/deploy/cloudflare-memory/worker.ts +157 -3
  2. package/dist/assets/deploy/cloudflare-resident/worker.ts +129 -14
  3. package/dist/assets/deploy/cloudflare-sandbox/Dockerfile +22 -18
  4. package/dist/assets/deploy/cloudflare-sandbox/package.json +1 -1
  5. package/dist/assets/deploy/cloudflare-sandbox/runtime-supervisor.sh +11 -10
  6. package/dist/assets/deploy/cloudflare-sandbox/worker.ts +332 -299
  7. package/dist/assets/deploy/cloudflare-sandbox/wrangler.template.jsonc +2 -2
  8. package/dist/assets/package-lock.json +7 -48
  9. package/dist/assets/package.json +1 -1
  10. package/dist/assets/project.json +2 -2
  11. package/dist/assets/source.json +3 -3
  12. package/dist/assets/src/agents/registry.ts +15 -0
  13. package/dist/assets/src/core/coordinator/contract.ts +6 -0
  14. package/dist/assets/src/core/coordinator/driver.ts +8 -6
  15. package/dist/assets/src/core/runEvents.ts +34 -1
  16. package/dist/assets/src/core/runFriction.ts +2 -1
  17. package/dist/assets/src/core/runRecord.ts +46 -3
  18. package/dist/assets/src/core/runUsage.ts +199 -0
  19. package/dist/assets/src/core/ship/coordinator.ts +4 -2
  20. package/dist/assets/src/execution/residentRebind.ts +84 -7
  21. package/dist/assets/src/execution/sandboxErrors.ts +14 -38
  22. package/dist/assets/src/execution/sandboxLifecycle.ts +78 -0
  23. package/dist/assets/web/dist/.vite/manifest.json +18 -18
  24. package/dist/assets/web/dist/assets/{ResidentDetailPage-Chvll3wy.js → ResidentDetailPage-B1Q9pabX.js} +1 -1
  25. package/dist/assets/web/dist/assets/{ResidentsIndexPage-B5f8IwGF.js → ResidentsIndexPage-CP7U_4aK.js} +1 -1
  26. package/dist/assets/web/dist/assets/{RunRoutePage-CRvmCuXh.js → RunRoutePage-dCC25f_b.js} +4 -4
  27. package/dist/assets/web/dist/assets/{RunsIndexPage-BTJuKFTv.js → RunsIndexPage-Cgp4t4C8.js} +1 -1
  28. package/dist/assets/web/dist/assets/{ScheduledPage-BVfgUBvP.js → ScheduledPage-DthDA2xG.js} +1 -1
  29. package/dist/assets/web/dist/assets/{StatusDot-CFXbAw7S.js → StatusDot-DDc88Kbs.js} +1 -1
  30. package/dist/assets/web/dist/assets/{Tooltip-DcHMtbHJ.js → Tooltip-CBapNhsh.js} +1 -1
  31. package/dist/assets/web/dist/assets/{dist-DKhqHu0V.js → dist-BnwSD1cL.js} +1 -1
  32. package/dist/assets/web/dist/assets/{main-CveRd2yk.js → main-ZhQGbZ2E.js} +2 -2
  33. package/dist/cli.js +808 -155
  34. package/package.json +1 -1
  35. package/dist/assets/src/execution/sandboxKeepalive.ts +0 -118
@@ -424,7 +424,9 @@ export interface UnitPipelineInput {
424
424
  /** Each child preset's own wall-clock budget (its `maxMinutes`), the number a
425
425
  * round's budget is clipped from — supplied by the bot, which holds the registry. */
426
426
  childMinutes: Readonly<Record<ChildPreset, number>>;
427
- /** Who merges: the runner (a plan branch, under its grant) or a person (any other branch). */
427
+ /** Who merges: the instance's `merge` field as the plan route answers it —
428
+ * `runner` (a seeded plan, under its grant) or `person` (a task, or a
429
+ * record without the field). */
428
430
  merge: "runner" | "person";
429
431
  /** Resume at review: an open pull request of ship's own the requester named. */
430
432
  resume?: { pr: number; headSha?: string; url?: string };
@@ -1102,7 +1104,7 @@ export function renderUnitReport(s: UnitPipelineState): string {
1102
1104
  `✅ Merge-ready after ${rounds}: ${e.pr.url}`,
1103
1105
  verdictLine,
1104
1106
  declinedLine,
1105
- "Remaining gate: a person's merge — the runner merges only a plan branch's pull request, and ship never approves.",
1107
+ "Remaining gate: a person's merge — the runner merges only when the instance's `merge` field says runner, and ship never approves.",
1106
1108
  ].join("\n");
1107
1109
  case "merge_refused":
1108
1110
  return join([
@@ -65,6 +65,66 @@ export function parseRefByDefault(value: unknown): ParsedRefByDefault {
65
65
  return { error: "refByDefault must be a boolean when present" };
66
66
  }
67
67
 
68
+ /** A branch a run pushed and the pull request it heads — what the run's
69
+ * release hands the resident (`/detach` body `pushed`), read off the run's
70
+ * own `pr_opened` events. */
71
+ export interface PushedBranch {
72
+ ref: string;
73
+ pr: number;
74
+ }
75
+
76
+ /** The same fact as the binding remembers it, with when it was told. */
77
+ export interface OwnBranch extends PushedBranch {
78
+ at: string;
79
+ }
80
+
81
+ /** The most branches one release may hand over: a run pushes a handful at most. */
82
+ export const PUSHED_MAX = 20;
83
+ /** The most branches a binding remembers: the newest are kept. */
84
+ export const OWN_BRANCHES_MAX = 50;
85
+
86
+ export type ParsedPushed = { pushed: PushedBranch[] } | { error: string };
87
+
88
+ const PUSHED_ERROR = "pushed must be a list of {ref: <branch>, pr: <positive integer>} when present";
89
+
90
+ /** `/detach` body field `pushed`: absent → nothing (the body every bot always
91
+ * sent); a list of up to `PUSHED_MAX` well-formed `{ref, pr}` → itself;
92
+ * anything else → a 400-shaped error. Each ref's PATTERN is the Worker's to
93
+ * check (`parseRef`), like every ref. */
94
+ export function parsePushed(value: unknown): ParsedPushed {
95
+ if (value === undefined) return { pushed: [] };
96
+ if (!Array.isArray(value) || value.length > PUSHED_MAX) return { error: PUSHED_ERROR };
97
+ const pushed: PushedBranch[] = [];
98
+ for (const entry of value) {
99
+ if (typeof entry !== "object" || entry === null) return { error: PUSHED_ERROR };
100
+ const { ref, pr } = entry as { ref?: unknown; pr?: unknown };
101
+ if (typeof ref !== "string" || ref.length === 0) return { error: PUSHED_ERROR };
102
+ if (typeof pr !== "number" || !Number.isSafeInteger(pr) || pr <= 0) return { error: PUSHED_ERROR };
103
+ pushed.push({ ref, pr });
104
+ }
105
+ return { pushed };
106
+ }
107
+
108
+ /** The binding's memory after a release: every branch handed over is
109
+ * remembered once — a branch pushed again moves to the end with its current
110
+ * pull request and time — and only the newest `OWN_BRANCHES_MAX` are kept.
111
+ * Stored BEFORE any eviction decision, so the fact survives the tree. */
112
+ export function rememberOwnBranches(
113
+ existing: readonly OwnBranch[] | undefined,
114
+ pushed: readonly PushedBranch[],
115
+ at: string,
116
+ ): OwnBranch[] {
117
+ const refs = new Set(pushed.map((p) => p.ref));
118
+ const kept = (existing ?? []).filter((b) => !refs.has(b.ref));
119
+ const added = pushed.map((p) => ({ ref: p.ref, pr: p.pr, at }));
120
+ return [...kept, ...added].slice(-OWN_BRANCHES_MAX);
121
+ }
122
+
123
+ /** Whether the thread's own runs pushed `ref`, as the binding remembers it. */
124
+ export function isOwnBranch(binding: { ownBranches?: readonly OwnBranch[] }, ref: string): boolean {
125
+ return (binding.ownBranches ?? []).some((b) => b.ref === ref);
126
+ }
127
+
68
128
  /** How a binding's ref was chosen: the repo default for want of a named
69
129
  * branch, or a branch someone named. */
70
130
  export type BoundBy = "default" | "name";
@@ -109,6 +169,8 @@ export interface RebindableBinding {
109
169
  evicted?: boolean;
110
170
  boundBy?: BoundBy;
111
171
  rebound?: Rebound;
172
+ /** The branches the thread's own runs pushed, handed over at each release. */
173
+ ownBranches?: OwnBranch[];
112
174
  }
113
175
 
114
176
  export type RebindPlan =
@@ -117,8 +179,14 @@ export type RebindPlan =
117
179
  | { kind: "none" }
118
180
  /** The binding alone rules it out; nothing on disk is consulted. */
119
181
  | { kind: "refuse"; refused: RebindRefused }
120
- /** The binding allows it; the tree decides (`rebindVerdict`). */
121
- | { kind: "measure"; from: string; to: string; pr: number };
182
+ /** The binding allows it and has a live tree; the tree decides
183
+ * (`rebindVerdict`). `own`: the thread's own runs pushed the branch, so a
184
+ * tree that turns out missing may still be recreated at it. */
185
+ | { kind: "measure"; from: string; to: string; pr: number; own: boolean }
186
+ /** The binding allows it, its tree was evicted, and the thread's own runs
187
+ * pushed the branch: the binding moves and the attach recreates the tree
188
+ * at the branch — once the mirror is known to hold it. */
189
+ | { kind: "recreate"; from: string; to: string; pr: number };
122
190
 
123
191
  export function rebindRefused(plan: { to: string; pr: number }, reason: RebindRefusal, why: string): RebindRefused {
124
192
  return { to: plan.to, pr: plan.pr, reason, why };
@@ -157,17 +225,19 @@ export function rebindPlan(input: {
157
225
  ),
158
226
  };
159
227
  }
228
+ const own = isOwnBranch(binding, plan.to);
160
229
  if (binding.evicted || !binding.user) {
230
+ if (own) return { kind: "recreate", from: binding.ref, ...plan };
161
231
  return {
162
232
  kind: "refuse",
163
233
  refused: rebindRefused(
164
234
  plan,
165
235
  "branch-absent",
166
- "the thread's worktree was evicted; the branch cannot be verified there",
236
+ `the thread's worktree was evicted and none of its runs pushed ${JSON.stringify(plan.to)}; only a branch this thread's own run pushed moves it`,
167
237
  ),
168
238
  };
169
239
  }
170
- return { kind: "measure", from: binding.ref, ...plan };
240
+ return { kind: "measure", from: binding.ref, ...plan, own };
171
241
  }
172
242
 
173
243
  /** What the attach measured about the thread's tree, as the thread user. Each
@@ -185,17 +255,24 @@ export interface RebindTreeFacts {
185
255
  dirty?: boolean;
186
256
  }
187
257
 
188
- export type RebindVerdict = { kind: "rebind" } | { kind: "refuse"; refused: RebindRefused };
258
+ export type RebindVerdict =
259
+ /** Check the branch out in the existing tree. */
260
+ | { kind: "rebind" }
261
+ /** The tree is gone (a slept container) and the thread's own runs pushed the
262
+ * branch: move the binding and let the attach recreate the tree at it. */
263
+ | { kind: "recreate" }
264
+ | { kind: "refuse"; refused: RebindRefused };
189
265
 
190
266
  /** The tree's verdict on a measured plan. */
191
- export function rebindVerdict(plan: { to: string; pr: number }, tree: RebindTreeFacts): RebindVerdict {
267
+ export function rebindVerdict(plan: { to: string; pr: number; own?: boolean }, tree: RebindTreeFacts): RebindVerdict {
192
268
  if (!tree.exists) {
269
+ if (plan.own === true) return { kind: "recreate" };
193
270
  return {
194
271
  kind: "refuse",
195
272
  refused: rebindRefused(
196
273
  plan,
197
274
  "branch-absent",
198
- "the thread's worktree is missing; the branch cannot be verified there",
275
+ `the thread's worktree is missing and none of its runs pushed ${JSON.stringify(plan.to)}; the branch cannot be verified there`,
199
276
  ),
200
277
  };
201
278
  }
@@ -90,16 +90,6 @@ export function isFleetBusyError(err: unknown): boolean {
90
90
  );
91
91
  }
92
92
 
93
- /** The 0.12.x Durable Object's answer while its container is still booting:
94
- * no session exists yet and nothing ran, so the SAME request can be re-sent
95
- * after a short pause — the one retry the Worker still does itself. */
96
- export const CONTAINER_STARTING_PATTERN = /^Container is starting\. Please retry in a moment\.?$/i;
97
-
98
- export function isContainerStarting(err: unknown): boolean {
99
- const { message } = thrownShape(err);
100
- return !!message && CONTAINER_STARTING_PATTERN.test(message.trim());
101
- }
102
-
103
93
  /** The Worker's answer on /read and /write (sent as HTTP 503): the named
104
94
  * reason plus an `error` that keeps the SDK's own message as the cause, so
105
95
  * the logs and the model can still see what the platform actually said. */
@@ -160,35 +150,21 @@ export function thrownText(shape: ThrownShape): string {
160
150
 
161
151
  // ---- A runtime that did not answer (docs/reference/specs/execution.md item 9) ----
162
152
  //
163
- // The SDK proxies every command to the container's port through the
164
- // `@cloudflare/containers` base class. When nothing answers there — the SDK's
165
- // server exited (an uncaught exception ends it), or is being started again by
166
- // the image's PID 1 — that class answers HTTP 500 with a plain-text body, not
167
- // the JSON the SDK client expects, and the client renders it as the bare
168
- // `HTTP error! status: 500`: no container, no cause, nothing a card can act
169
- // on. The Worker reads the body first and names the condition instead.
153
+ // Every command and file operation reaches the container through the SDK's
154
+ // control connection to the container's port. When nothing answers there —
155
+ // the SDK's server exited, or the image's PID 1 is starting it again — the
156
+ // SDK's connect aborts after 30 s with a bare `The operation was aborted`:
157
+ // no container, no cause, nothing a card can act on. The Durable Object
158
+ // names the condition instead, with the facts a reader needs.
170
159
 
171
160
  /** The named reason the Worker answers with, like `fleet-busy`: a machine
172
- * token the executor and the harness match on, never the SDK's text. */
161
+ * token the executor matches on, never the SDK's text. */
173
162
  export const RUNTIME_UNREACHABLE_REASON = "runtime-unreachable" as const;
174
163
 
175
164
  /** The name the Worker's typed error carries across the Durable Object RPC
176
165
  * boundary (which keeps `name`/`message` and drops the prototype). */
177
166
  export const RUNTIME_UNREACHABLE_ERROR_NAME = "SandboxRuntimeUnreachableError";
178
167
 
179
- /** The base class's two plain-text 500 bodies for a failed proxy to the
180
- * container's port: the fetch itself failed (nothing listening — the server
181
- * exited, or has not come back yet), and a connection lost mid-request. A
182
- * JSON 500 from the server itself is neither: that server was alive. */
183
- const PROXY_FAILURE_BODIES: readonly RegExp[] = [
184
- /^Error proxying request to container\b/,
185
- /^Container suddenly disconnected\b/,
186
- ];
187
-
188
- export function isRuntimeProxyFailure(status: number, body: string): boolean {
189
- return status === 500 && PROXY_FAILURE_BODIES.some((re) => re.test(body.trim()));
190
- }
191
-
192
168
  export interface RuntimeUnreachableFacts {
193
169
  /** The Durable Object's id — the same word the `containers` log dataset carries as the container id. */
194
170
  containerId: string;
@@ -196,7 +172,7 @@ export interface RuntimeUnreachableFacts {
196
172
  running: boolean | undefined;
197
173
  /** The Worker's `@cloudflare/sandbox` pin, which is also the image tag. */
198
174
  sdkVersion: string;
199
- /** The base class's body, verbatim: what the platform said. */
175
+ /** The SDK's own text, verbatim: what it saw. */
200
176
  cause: string;
201
177
  }
202
178
 
@@ -209,13 +185,13 @@ export function runtimeUnreachableMessage(f: RuntimeUnreachableFacts): string {
209
185
  return (
210
186
  `${RUNTIME_UNREACHABLE_REASON}: the sandbox container's runtime did not answer ` +
211
187
  `(container ${f.containerId}, sandbox SDK ${f.sdkVersion}; the platform reports the container ${platform}) — ` +
212
- "its server exited and the image's PID 1 starts it again within seconds; this command may not have run and " +
213
- `/workspace is intact: wait a moment, check, then retry (${f.cause.trim() || "no detail from the platform"})`
188
+ "nothing ran; if the container still runs, /workspace is intact and its runtime is being started again: " +
189
+ `wait a moment, then retry (${f.cause.trim() || "no detail from the SDK"})`
214
190
  );
215
191
  }
216
192
 
217
- /** The Worker's typed error for a failed proxy: thrown from `containerFetch`
218
- * inside the Durable Object, caught by the Worker's routes on the other side
193
+ /** The Worker's typed error for a silent control port: built inside the
194
+ * Durable Object with its facts, read by the fetch handler on the other side
219
195
  * of the RPC boundary, so it is matched by name and by its message token,
220
196
  * never by `instanceof`. */
221
197
  export class SandboxRuntimeUnreachableError extends Error {
@@ -245,8 +221,8 @@ export function runtimeUnreachableAnswer(message: string): {
245
221
 
246
222
  /** The `/exec` answer, in-body under the streamed HTTP 200 like every other exec
247
223
  * failure: the dual `error` + exit-127/stderr shape (item 3) plus the reason.
248
- * Never re-sent by anyone: a command in flight when the server died may have
249
- * run; the text tells the model to check before it retries. */
224
+ * Never re-sent by anyone: the executor re-sends nothing in-body, and the
225
+ * text tells the model to wait, then retry. */
250
226
  export function runtimeUnreachableExecAnswer(message: string): {
251
227
  error: string;
252
228
  reason: typeof RUNTIME_UNREACHABLE_REASON;
@@ -0,0 +1,78 @@
1
+ // The per-thread sandbox's lifecycle facts the Worker and the bot share
2
+ // (docs/reference/specs/execution.md items 1, 2 and 9): how long an idle
3
+ // container stays warm, and how a container replaced or restarted under a
4
+ // command is recognized and named. Deliberately free of node: imports so
5
+ // wrangler can bundle it into the sandbox Worker.
6
+
7
+ /** How long an IDLE container stays warm before the Durable Object stops it,
8
+ * in the Container class's own `<n>[smh]` grammar. Idle means idle: the SDK
9
+ * renews the activity timeout every second while a command's stream is open
10
+ * (its control connection's busy poll), so a running command never counts
11
+ * toward it. 5 minutes frees a finished thread's slot (`max_instances`)
12
+ * sooner than the SDK default (10 min), while a follow-up inside 5 minutes
13
+ * still lands on the same warm workspace; a later one re-clones, which is the
14
+ * documented per-thread degradation (item 1). */
15
+ export const SANDBOX_SLEEP_AFTER = "5m";
16
+
17
+ /** The texts the SDK produces when the container is torn down under a
18
+ * command, across generations. 0.3.x: the exec handler's generic wrapper (its
19
+ * real cause, "Session terminated", sat in a field the client discarded), the
20
+ * cause itself, and the stale-session answer the same attempt got once the
21
+ * sessions were cleared. 0.12.x: the typed `SessionTerminatedError` text
22
+ * (`Session '<id>' shell exited (exit code: <n>)`) and the
23
+ * `OperationInterruptedError` text for a container that stopped under a
24
+ * pending call, and the disconnect text for a sandbox `destroy()`ed under a
25
+ * pending call. Anything else — a transport error, a file-op failure — is
26
+ * never recycle-shaped, whenever it arrives. */
27
+ const RECYCLE_SHAPED: readonly RegExp[] = [
28
+ /^Command execution failed$/,
29
+ /^Session terminated$/i,
30
+ /^Session '[^']*' not found$/i,
31
+ /^Session '[^']*' shell exited \(exit code: -?\d+\)$/i,
32
+ /^The sandbox container stopped while the operation was pending\.?$/i,
33
+ /^The sandbox was destroyed while the operation was pending\.?$/i,
34
+ ];
35
+
36
+ /** The typed errors that MEAN the container's runtime went away under the
37
+ * call, across the 0.12 and 0.13 lines. Matched by name, not `instanceof`:
38
+ * the fetch handler sees them after the Durable Object RPC boundary, which
39
+ * keeps `name`/`message` and drops the prototype (inside the Durable Object,
40
+ * `instanceof` holds and decides first). */
41
+ export const RECYCLE_ERROR_NAMES: readonly string[] = [
42
+ "SessionTerminatedError",
43
+ "OperationInterruptedError",
44
+ "StaleProcessHandleError",
45
+ "RuntimeIdentityInactiveError",
46
+ ];
47
+
48
+ /** Type first, text second: a typed recycle error, or a recycle-shaped text. */
49
+ export function isRecycleError(err: { name?: string; message?: string }): boolean {
50
+ if (err.name && RECYCLE_ERROR_NAMES.includes(err.name)) return true;
51
+ return !!err.message && RECYCLE_SHAPED.some((re) => re.test(err.message!.trim()));
52
+ }
53
+
54
+ /** Grace inside which a recycle-shaped TEXT is taken at face value: a session
55
+ * that fails to start does so in seconds, not minutes. A typed recycle error
56
+ * needs no grace — the SDK is stating the runtime went away. */
57
+ const RECYCLE_SUSPECT_AFTER_MS = 60_000;
58
+
59
+ /** The message `/exec` puts in-body when a command's failure looks like the
60
+ * container's runtime went away under it: a typed recycle error (`certain`),
61
+ * or a recycle-shaped text that arrived more than a minute into THIS attempt
62
+ * (a startup failure shows in seconds). Any other text, however late, is
63
+ * returned unchanged — timing alone never rewords an unrelated error. The
64
+ * exit code stays 127: it IS an infra failure and the command did not finish,
65
+ * so a faked exit 124 would tell the model to shorten a command that was
66
+ * never the problem. What the workspace holds afterwards depends on what
67
+ * went away: a replaced container has an empty `/workspace` (re-clone); a
68
+ * runtime the image's PID 1 started again (item 21) left it intact. The text
69
+ * says to look before assuming either. */
70
+ export function recycledMidCommandMessage(elapsedMs: number, msg: string, certain = false): string {
71
+ const shaped = RECYCLE_SHAPED.some((re) => re.test(msg.trim()));
72
+ if (!certain && (!shaped || elapsedMs <= RECYCLE_SUSPECT_AFTER_MS)) return msg;
73
+ const secs = Math.round(elapsedMs / 1_000);
74
+ return (
75
+ `sandbox recycled mid-command after ${secs}s — the container's runtime was replaced or restarted under the command, which did not finish; ` +
76
+ `check /workspace before continuing: it is empty if the container was replaced (re-clone), intact if only its runtime restarted (${msg})`
77
+ );
78
+ }
@@ -28,7 +28,7 @@
28
28
  "src": "../node_modules/@fontsource-variable/jetbrains-mono/files/jetbrains-mono-vietnamese-wght-normal.woff2"
29
29
  },
30
30
  "../node_modules/@pierre/diffs/dist/index.js": {
31
- "file": "assets/dist-DKhqHu0V.js",
31
+ "file": "assets/dist-BnwSD1cL.js",
32
32
  "name": "dist",
33
33
  "src": "../node_modules/@pierre/diffs/dist/index.js",
34
34
  "isDynamicEntry": true,
@@ -2562,16 +2562,16 @@
2562
2562
  "_seed-DeKSHrt2.js"
2563
2563
  ]
2564
2564
  },
2565
- "_StatusDot-CFXbAw7S.js": {
2566
- "file": "assets/StatusDot-CFXbAw7S.js",
2565
+ "_StatusDot-DDc88Kbs.js": {
2566
+ "file": "assets/StatusDot-DDc88Kbs.js",
2567
2567
  "name": "StatusDot",
2568
2568
  "imports": [
2569
2569
  "_seed-DeKSHrt2.js",
2570
- "_Tooltip-DcHMtbHJ.js"
2570
+ "_Tooltip-CBapNhsh.js"
2571
2571
  ]
2572
2572
  },
2573
- "_Tooltip-DcHMtbHJ.js": {
2574
- "file": "assets/Tooltip-DcHMtbHJ.js",
2573
+ "_Tooltip-CBapNhsh.js": {
2574
+ "file": "assets/Tooltip-CBapNhsh.js",
2575
2575
  "name": "Tooltip",
2576
2576
  "imports": [
2577
2577
  "_AppShell-lYVcj-k7.js",
@@ -2789,7 +2789,7 @@
2789
2789
  ]
2790
2790
  },
2791
2791
  "src/main.ts": {
2792
- "file": "assets/main-CveRd2yk.js",
2792
+ "file": "assets/main-ZhQGbZ2E.js",
2793
2793
  "name": "main",
2794
2794
  "src": "src/main.ts",
2795
2795
  "isEntry": true,
@@ -2841,19 +2841,19 @@
2841
2841
  ]
2842
2842
  },
2843
2843
  "src/pages/ResidentDetailPage.vue": {
2844
- "file": "assets/ResidentDetailPage-Chvll3wy.js",
2844
+ "file": "assets/ResidentDetailPage-B1Q9pabX.js",
2845
2845
  "name": "ResidentDetailPage",
2846
2846
  "src": "src/pages/ResidentDetailPage.vue",
2847
2847
  "isDynamicEntry": true,
2848
2848
  "imports": [
2849
2849
  "_AppShell-lYVcj-k7.js",
2850
2850
  "_seed-DeKSHrt2.js",
2851
- "_StatusDot-CFXbAw7S.js",
2851
+ "_StatusDot-DDc88Kbs.js",
2852
2852
  "_residentDiskBudget-BMBKlYRH.js"
2853
2853
  ]
2854
2854
  },
2855
2855
  "src/pages/ResidentsIndexPage.vue": {
2856
- "file": "assets/ResidentsIndexPage-B5f8IwGF.js",
2856
+ "file": "assets/ResidentsIndexPage-CP7U_4aK.js",
2857
2857
  "name": "ResidentsIndexPage",
2858
2858
  "src": "src/pages/ResidentsIndexPage.vue",
2859
2859
  "isDynamicEntry": true,
@@ -2861,20 +2861,20 @@
2861
2861
  "_AppShell-lYVcj-k7.js",
2862
2862
  "_seed-DeKSHrt2.js",
2863
2863
  "_wallClock-61NpVkY6.js",
2864
- "_StatusDot-CFXbAw7S.js",
2864
+ "_StatusDot-DDc88Kbs.js",
2865
2865
  "_residentDiskBudget-BMBKlYRH.js",
2866
2866
  "_indexFormat-B-pd4r7Y.js"
2867
2867
  ]
2868
2868
  },
2869
2869
  "src/pages/RunRoutePage.vue": {
2870
- "file": "assets/RunRoutePage-CRvmCuXh.js",
2870
+ "file": "assets/RunRoutePage-dCC25f_b.js",
2871
2871
  "name": "RunRoutePage",
2872
2872
  "src": "src/pages/RunRoutePage.vue",
2873
2873
  "isDynamicEntry": true,
2874
2874
  "imports": [
2875
2875
  "_AppShell-lYVcj-k7.js",
2876
2876
  "_seed-DeKSHrt2.js",
2877
- "_Tooltip-DcHMtbHJ.js",
2877
+ "_Tooltip-CBapNhsh.js",
2878
2878
  "src/main.ts",
2879
2879
  "_wallClock-61NpVkY6.js",
2880
2880
  "_NotFoundPage-BzWS4Ca1.js",
@@ -2890,31 +2890,31 @@
2890
2890
  ]
2891
2891
  },
2892
2892
  "src/pages/RunsIndexPage.vue": {
2893
- "file": "assets/RunsIndexPage-BTJuKFTv.js",
2893
+ "file": "assets/RunsIndexPage-Cgp4t4C8.js",
2894
2894
  "name": "RunsIndexPage",
2895
2895
  "src": "src/pages/RunsIndexPage.vue",
2896
2896
  "isDynamicEntry": true,
2897
2897
  "imports": [
2898
2898
  "_AppShell-lYVcj-k7.js",
2899
2899
  "_seed-DeKSHrt2.js",
2900
- "_Tooltip-DcHMtbHJ.js",
2900
+ "_Tooltip-CBapNhsh.js",
2901
2901
  "_wallClock-61NpVkY6.js",
2902
2902
  "_RunsTabs-DEICQ4FY.js",
2903
- "_StatusDot-CFXbAw7S.js",
2903
+ "_StatusDot-DDc88Kbs.js",
2904
2904
  "_indexFormat-B-pd4r7Y.js",
2905
2905
  "_favicon-CWPcvWvp.js",
2906
2906
  "_localIso-L06jV29p.js"
2907
2907
  ]
2908
2908
  },
2909
2909
  "src/pages/ScheduledPage.vue": {
2910
- "file": "assets/ScheduledPage-BVfgUBvP.js",
2910
+ "file": "assets/ScheduledPage-DthDA2xG.js",
2911
2911
  "name": "ScheduledPage",
2912
2912
  "src": "src/pages/ScheduledPage.vue",
2913
2913
  "isDynamicEntry": true,
2914
2914
  "imports": [
2915
2915
  "_AppShell-lYVcj-k7.js",
2916
2916
  "_seed-DeKSHrt2.js",
2917
- "_Tooltip-DcHMtbHJ.js",
2917
+ "_Tooltip-CBapNhsh.js",
2918
2918
  "_wallClock-61NpVkY6.js",
2919
2919
  "_RunsTabs-DEICQ4FY.js",
2920
2920
  "_indexFormat-B-pd4r7Y.js",
@@ -1 +1 @@
1
- import{t as e}from"./AppShell-lYVcj-k7.js";import{Lr as t,Xt as n,_n as r,cn as i,gn as a,ir as o,ln as ee,on as s,r as c,sn as l,un as u,ur as d,vi as f,wi as p,yn as te}from"./seed-DeKSHrt2.js";import{t as m}from"./StatusDot-CFXbAw7S.js";import{a as ne,c as re,d as ie,f as h,i as g,l as ae,n as oe,o as se,r as ce,s as _,t as le,u as ue}from"./residentDiskBudget-BMBKlYRH.js";var de={class:`mt-4 first:mt-0`},fe={class:`w-full border-collapse font-mono text-[0.8125rem]`},pe={class:`border-t border-muted`},me={class:`px-2 py-1 align-top`},v={class:`ml-1.5 font-medium`},y={class:`border-t border-muted`},b={class:`break-all px-2 py-1 align-top`},x={key:0},S={key:1,class:`text-dimmed`},C={class:`border-t border-muted`},w={class:`break-all px-2 py-1 align-top`},T={key:0},E={key:1,class:`text-dimmed`},D={class:`border-t border-muted`},O={class:`break-all px-2 py-1 align-top`},k={key:0},A={key:1,class:`text-dimmed`},j={class:`border-t border-muted`},M={class:`break-all px-2 py-1 align-top`},N={key:0},P={key:1,class:`text-dimmed`},F={class:`border-t border-muted`},I={class:`break-all px-2 py-1 align-top`},L={key:1,class:`text-dimmed`},R={class:`mt-4`},z={class:`w-full border-collapse font-mono text-[0.8125rem]`},he={class:`border-t border-muted`},ge={class:`break-all px-2 py-1 align-top`},_e=[`href`],ve={key:1},ye={class:`border-t border-muted`},be={class:`break-all px-2 py-1 align-top`},xe={class:`border-t border-muted`},Se={class:`break-all px-2 py-1 align-top`},Ce=[`href`],we={key:1},Te={key:2,class:`text-dimmed`},Ee={class:`border-t border-muted`},De={class:`break-all px-2 py-1 align-top`},Oe={key:0},ke={key:1,class:`text-dimmed`},Ae={class:`border-t border-muted`},je={class:`break-all px-2 py-1 align-top`},Me={key:0},Ne={key:1,class:`text-dimmed`},Pe={class:`border-t border-muted`},Fe={class:`break-all px-2 py-1 align-top`},Ie={key:0},Le={key:1,class:`text-dimmed`},Re={class:`mt-4`},ze={class:`w-full border-collapse font-mono text-[0.8125rem]`},Be={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},Ve={class:`break-all px-2 py-1 align-top`},He={class:`w-full border-collapse font-mono text-[0.8125rem]`},Ue={class:`w-32 break-all px-2 py-1 align-top text-muted sm:w-96 sm:break-words`},We={class:`px-2 py-1 align-top`},Ge={key:1,class:`text-xs text-muted`},Ke={class:`mt-4`},qe={key:0,class:`w-full border-collapse font-mono text-[0.8125rem]`},Je={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},Ye={class:`break-all px-2 py-1 align-top`},Xe={key:0},B={key:1,class:`text-dimmed`},Ze={key:1,class:`text-xs text-muted`},Qe={class:`mt-4`},$e={class:`mb-1 text-xs text-muted`},et={class:`overflow-x-auto`},tt={class:`w-full border-collapse font-mono text-[0.8125rem]`},nt={class:`break-all px-2 py-1 align-top`},rt={key:0,class:`text-xs text-muted`},it={class:`break-all px-2 py-1 align-top`},at=[`href`],ot={key:1},st={key:2,class:`text-dimmed`},ct={class:`break-all px-2 py-1 align-top`},lt={key:0},ut={key:1,class:`text-dimmed`},dt={key:2},ft={key:3,class:`text-dimmed`},pt={class:`break-all px-2 py-1 align-top`},mt={key:0},ht={key:1,class:`text-dimmed`},gt={key:2},_t={key:3,class:`text-dimmed`},vt={key:1,class:`text-xs text-muted`},yt={class:`mt-4`},bt={class:`w-full border-collapse font-mono text-[0.8125rem]`},xt={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},St={class:`px-2 py-1 align-top`},Ct={class:`mt-4`},wt={key:0,class:`w-full border-collapse font-mono text-[0.8125rem]`},Tt={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},Et={class:`break-all px-2 py-1 align-top`},Dt={class:`text-xs text-muted`},Ot={key:1,class:`text-xs text-muted`},kt={class:`mt-4`},At={class:`w-full border-collapse font-mono text-[0.8125rem]`},jt={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},Mt={class:`break-all px-2 py-1 align-top`},Nt={key:0},Pt={key:1,class:`text-dimmed`},Ft={class:`mt-4 text-xs text-muted`},It={class:`rounded bg-elevated px-1 py-0.5`},Lt={class:`rounded bg-elevated px-1 py-0.5`},Rt={class:`rounded bg-elevated px-1 py-0.5`},V=te({__name:`ResidentDetailPage`,setup(te){let V=c(`resident`),H=s(()=>V?.record??{}),U=s(()=>ae(H.value)),W=s(()=>ue(H.value)||(V?.slug??``)),G=s(()=>h(U.value.sha)),K=s(()=>se.test(W.value)?`https://github.com/${W.value}`:void 0),q=s(()=>K.value&&/^[0-9a-f]{7,40}$/.test(G.value)?`${K.value}/commit/${G.value}`:void 0),J=s(()=>{let e=U.value.snapshot;return e&&typeof e==`object`?_(e):void 0}),zt=s(()=>_(U.value.schedules)),Y=s(()=>{let e=_(H.value.commands),t=_(H.value.effects);return Object.keys(e).sort().map(n=>({name:n,command:h(e[n]),effect:h(t[n])||`readonly`}))}),X=s(()=>{let e=U.value.threads;return(Array.isArray(e)?e.map(_):[]).map(e=>{let t=h(e.sha);return{threadKey:h(e.threadKey)||`?`,ref:h(e.ref)||`?`,sha:t?t.slice(0,8):``,commitHref:K.value&&/^[0-9a-f]{7,40}$/.test(t)?`${K.value}/commit/${t}`:void 0,user:h(e.user),deps:h(e.deps),boundAt:h(e.boundAt),lastAttachAt:h(e.lastAttachAt),evicted:e.evicted===!0,evictedAt:h(e.evictedAt),evictedWhy:h(e.evictedWhy)}}).sort((e,t)=>t.lastAttachAt.localeCompare(e.lastAttachAt))}),Z=s(()=>X.value.filter(e=>!e.evicted).length),Q=s(()=>{let e=U.value.lastRestore;return e?JSON.stringify(e):``}),$=s(()=>re(H.value)),Bt=s(()=>typeof H.value.diskBudgetMb==`number`?H.value.diskBudgetMb:void 0),Vt=s(()=>{let e=$.value;if(!e)return[];let t=le(e),{freeKiB:n,capped:r,capacityKiB:i}=oe(e,Bt.value),a=n-t.totalKiB,o=t=>{let n=ne(e.parts,t);return n===null?`? (checkout not measured)`:n===0?`?`:`${Math.max(0,Math.floor(a/n))} more (${g(n)} each)`};return[[`used / total`,ce(e)],[`free`,`${g(n)}${r?` under the ${g(i)} diskBudgetMb cap`:``}`],[`reserve`,`${g(t.totalKiB)} (snapshot staging ${g(t.stagingKiB)} + floor ${g(t.floorKiB)})`],[`headroom`,`${g(Math.max(0,a))} — room for ${o(`hardlink`)} hardlinked trees, ${o(`reconcile`)} lockfile-diverged (reconciling)`],[`measured`,e.at||`—`]]}),Ht=s(()=>{let e=$.value;if(!e)return[];let t=[[`mirror`,g(e.parts.mirror)],[`checkout deps (node_modules)`,g(e.parts.deps)],[`checkout (history + tree + build)`,g(e.parts.checkout)]];for(let[n,r]of Object.entries(e.parts.threads).sort((e,t)=>t[1]-e[1]))t.push([`thread ${n}`,g(r)]);for(let[n,r]of Object.entries(e.parts.homes).sort((e,t)=>t[1]-e[1]))r>=1024&&t.push([`home ${n}`,g(r)]);return t.push([`other (image, /tmp, …)`,g(e.parts.other)]),t});return(s,c)=>(o(),i(e,{title:W.value||`Resident`,nav:`residents`},{leading:t(()=>[...c[0]||=[l(`a`,{class:`back text-sm text-muted no-underline hover:text-primary`,href:`/residents`},`← All residents`,-1)]]),default:t(()=>[l(`section`,de,[c[8]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Lifecycle`,-1),l(`table`,fe,[l(`tbody`,null,[l(`tr`,pe,[c[1]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`state`,-1),l(`td`,me,[r(m,{tone:f(ie)(U.value.state),label:U.value.state},null,8,[`tone`,`label`]),l(`span`,v,p(U.value.state),1)])]),l(`tr`,y,[c[2]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`reason`,-1),l(`td`,b,[U.value.reason?(o(),u(`span`,x,p(U.value.reason),1)):(o(),u(`span`,S,`—`))])]),l(`tr`,C,[c[3]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`last refresh error`,-1),l(`td`,w,[f(h)(U.value.lastRefreshError)?(o(),u(`span`,T,p(f(h)(U.value.lastRefreshError)),1)):(o(),u(`span`,E,`—`))])]),l(`tr`,D,[c[4]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`last restore`,-1),l(`td`,O,[Q.value?(o(),u(`span`,k,p(Q.value),1)):(o(),u(`span`,A,`—`))])]),l(`tr`,j,[c[5]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`state updated`,-1),l(`td`,M,[f(h)(U.value.updatedAt)?(o(),u(`span`,N,p(f(h)(U.value.updatedAt)),1)):(o(),u(`span`,P,`—`))])]),l(`tr`,F,[c[7]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`idle since`,-1),l(`td`,I,[f(h)(U.value.idleSince)?(o(),u(n,{key:0},[a(p(f(h)(U.value.idleSince))+` `,1),c[6]||=l(`span`,{class:`text-xs text-muted`},`(refresh parked; container may sleep)`,-1)],64)):(o(),u(`span`,L,`awake`))])])])])]),l(`section`,R,[c[15]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Pinned facts`,-1),l(`table`,z,[l(`tbody`,null,[l(`tr`,he,[c[9]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`repository`,-1),l(`td`,ge,[K.value?(o(),u(`a`,{key:0,class:`text-primary`,href:K.value},p(K.value),9,_e)):(o(),u(`span`,ve,p(f(h)(H.value.resource)||`—`),1))])]),l(`tr`,ye,[c[10]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`default ref`,-1),l(`td`,be,p(f(h)(U.value.defaultRef)||f(h)(H.value.defaultRef)||`—`),1)]),l(`tr`,xe,[c[11]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`pinned sha`,-1),l(`td`,Se,[q.value?(o(),u(`a`,{key:0,class:`text-primary`,href:q.value},p(G.value),9,Ce)):G.value?(o(),u(`span`,we,p(G.value),1)):(o(),u(`span`,Te,`—`))])]),l(`tr`,Ee,[c[12]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`lockfile hash`,-1),l(`td`,De,[f(h)(U.value.lockfileHash)?(o(),u(`span`,Oe,p(f(h)(U.value.lockfileHash)),1)):(o(),u(`span`,ke,`—`))])]),l(`tr`,Ae,[c[13]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`provisioned`,-1),l(`td`,je,[f(h)(U.value.provisionedAt)?(o(),u(`span`,Me,p(f(h)(U.value.provisionedAt)),1)):(o(),u(`span`,Ne,`—`))])]),l(`tr`,Pe,[c[14]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`last refresh`,-1),l(`td`,Fe,[f(h)(U.value.lastRefreshAt)?(o(),u(`span`,Ie,p(f(h)(U.value.lastRefreshAt)),1)):(o(),u(`span`,Le,`—`))])])])])]),l(`section`,Re,[c[17]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Disk`,-1),$.value?(o(),u(n,{key:0},[l(`table`,ze,[l(`tbody`,null,[(o(!0),u(n,null,d(Vt.value,([e,t])=>(o(),u(`tr`,{key:e,class:`border-t border-muted`},[l(`td`,Be,p(e),1),l(`td`,Ve,p(t),1)]))),128))])]),c[16]||=l(`p`,{class:`mb-1 mt-2 text-xs text-muted`},` components (one du, hardlinks counted once — a thread tree shows only what it does not share with the checkout) `,-1),l(`table`,He,[l(`tbody`,null,[(o(!0),u(n,null,d(Ht.value,([e,t])=>(o(),u(`tr`,{key:e,class:`border-t border-muted`},[l(`td`,Ue,p(e),1),l(`td`,We,p(t),1)]))),128))])])],64)):(o(),u(`p`,Ge,` not measured yet — the first refresh cycle or attach of this container measures it `))]),l(`section`,Ke,[c[18]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Snapshot stamp`,-1),J.value?(o(),u(`table`,qe,[l(`tbody`,null,[(o(),u(n,null,d([`ref`,`sha`,`lockfileHash`,`createdAt`,`mirrorBackupId`,`checkoutBackupId`],e=>l(`tr`,{key:e,class:`border-t border-muted`},[l(`td`,Je,p(e),1),l(`td`,Ye,[f(h)(J.value[e])?(o(),u(`span`,Xe,p(f(h)(J.value[e])),1)):(o(),u(`span`,B,`—`))])])),64))])])):(o(),u(`p`,Ze,`no snapshot recorded`))]),l(`section`,Qe,[c[22]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Thread worktrees`,-1),X.value.length>0?(o(),u(n,{key:0},[l(`p`,$e,p(Z.value)+` live · `+p(X.value.length-Z.value)+` evicted`,1),l(`div`,et,[l(`table`,tt,[l(`tbody`,null,[c[21]||=l(`tr`,{class:`text-xs text-muted`},[l(`td`,{class:`px-2 py-1`},`thread`),l(`td`,{class:`px-2 py-1`},`ref · sha`),l(`td`,{class:`px-2 py-1`},`user · deps`),l(`td`,{class:`px-2 py-1`},`bound · last attach`)],-1),(o(!0),u(n,null,d(X.value,e=>(o(),u(`tr`,{key:e.threadKey,class:`border-t border-muted`},[l(`td`,nt,[e.evicted?(o(),u(`span`,rt,[a(`evicted `+p(e.evictedAt||`—`),1),e.evictedWhy?(o(),u(n,{key:0},[a(` · `+p(e.evictedWhy),1)],64)):ee(``,!0)])):(o(),i(m,{key:1,tone:`green`,label:`live`,tip:`live`})),a(` `+p(e.threadKey),1)]),l(`td`,it,[a(p(e.ref)+` · `,1),e.commitHref?(o(),u(`a`,{key:0,class:`text-primary`,href:e.commitHref},p(e.sha),9,at)):e.sha?(o(),u(`span`,ot,p(e.sha),1)):(o(),u(`span`,st,`—`))]),l(`td`,ct,[e.user?(o(),u(`span`,lt,p(e.user),1)):(o(),u(`span`,ut,`—`)),c[19]||=a(` · `,-1),e.deps?(o(),u(`span`,dt,p(e.deps),1)):(o(),u(`span`,ft,`—`))]),l(`td`,pt,[e.boundAt?(o(),u(`span`,mt,p(e.boundAt),1)):(o(),u(`span`,ht,`—`)),c[20]||=a(` · `,-1),e.lastAttachAt?(o(),u(`span`,gt,p(e.lastAttachAt),1)):(o(),u(`span`,_t,`—`))])]))),128))])])])],64)):(o(),u(`p`,vt,`no thread worktrees`))]),l(`section`,yt,[c[23]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Pending schedules`,-1),l(`table`,bt,[l(`tbody`,null,[(o(),u(n,null,d([[`refresh`,`refresh`],[`provision run`,`provisionRun`],[`provision deadline`,`provisionDeadline`]],([e,t])=>l(`tr`,{key:t,class:`border-t border-muted`},[l(`td`,xt,p(e),1),l(`td`,St,p(f(h)(zt.value[t]??0)||`0`),1)])),64))])])]),l(`section`,Ct,[c[25]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Command table`,-1),Y.value.length>0?(o(),u(`table`,wt,[l(`tbody`,null,[(o(!0),u(n,null,d(Y.value,e=>(o(),u(`tr`,{key:e.name,class:`border-t border-muted`},[l(`td`,Tt,p(e.name),1),l(`td`,Et,[l(`code`,null,p(e.command),1),c[24]||=a(),l(`span`,Dt,p(e.effect),1)])]))),128))])])):(o(),u(`p`,Ot,`no command table`))]),l(`section`,kt,[c[26]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Registry settings`,-1),l(`table`,At,[l(`tbody`,null,[(o(!0),u(n,null,d([[`onboarded`,f(h)(H.value.onboardedAt)],[`record updated`,f(h)(H.value.updatedAt)],[`provisioning timeout (ms)`,f(h)(H.value.provisioningTimeoutMs)],[`disk budget (MB)`,f(h)(H.value.diskBudgetMb)],[`worktree TTL (days)`,f(h)(H.value.worktreeTtlDays??7)]],([e,t])=>(o(),u(`tr`,{key:e,class:`border-t border-muted`},[l(`td`,jt,p(e),1),l(`td`,Mt,[t?(o(),u(`span`,Nt,p(t),1)):(o(),u(`span`,Pt,`—`))])]))),128))])])]),l(`p`,Ft,[c[27]||=a(` Manage from chat: `,-1),l(`code`,It,`repo rebuild `+p(W.value),1),c[28]||=a(` · `,-1),l(`code`,Lt,`repo reconfigure `+p(W.value)+` …`,1),c[29]||=a(` · `,-1),l(`code`,Rt,`repo offboard `+p(W.value)+` --dry-run`,1)])]),_:1},8,[`title`]))}});export{V as default};
1
+ import{t as e}from"./AppShell-lYVcj-k7.js";import{Lr as t,Xt as n,_n as r,cn as i,gn as a,ir as o,ln as ee,on as s,r as c,sn as l,un as u,ur as d,vi as f,wi as p,yn as te}from"./seed-DeKSHrt2.js";import{t as m}from"./StatusDot-DDc88Kbs.js";import{a as ne,c as re,d as ie,f as h,i as g,l as ae,n as oe,o as se,r as ce,s as _,t as le,u as ue}from"./residentDiskBudget-BMBKlYRH.js";var de={class:`mt-4 first:mt-0`},fe={class:`w-full border-collapse font-mono text-[0.8125rem]`},pe={class:`border-t border-muted`},me={class:`px-2 py-1 align-top`},v={class:`ml-1.5 font-medium`},y={class:`border-t border-muted`},b={class:`break-all px-2 py-1 align-top`},x={key:0},S={key:1,class:`text-dimmed`},C={class:`border-t border-muted`},w={class:`break-all px-2 py-1 align-top`},T={key:0},E={key:1,class:`text-dimmed`},D={class:`border-t border-muted`},O={class:`break-all px-2 py-1 align-top`},k={key:0},A={key:1,class:`text-dimmed`},j={class:`border-t border-muted`},M={class:`break-all px-2 py-1 align-top`},N={key:0},P={key:1,class:`text-dimmed`},F={class:`border-t border-muted`},I={class:`break-all px-2 py-1 align-top`},L={key:1,class:`text-dimmed`},R={class:`mt-4`},z={class:`w-full border-collapse font-mono text-[0.8125rem]`},he={class:`border-t border-muted`},ge={class:`break-all px-2 py-1 align-top`},_e=[`href`],ve={key:1},ye={class:`border-t border-muted`},be={class:`break-all px-2 py-1 align-top`},xe={class:`border-t border-muted`},Se={class:`break-all px-2 py-1 align-top`},Ce=[`href`],we={key:1},Te={key:2,class:`text-dimmed`},Ee={class:`border-t border-muted`},De={class:`break-all px-2 py-1 align-top`},Oe={key:0},ke={key:1,class:`text-dimmed`},Ae={class:`border-t border-muted`},je={class:`break-all px-2 py-1 align-top`},Me={key:0},Ne={key:1,class:`text-dimmed`},Pe={class:`border-t border-muted`},Fe={class:`break-all px-2 py-1 align-top`},Ie={key:0},Le={key:1,class:`text-dimmed`},Re={class:`mt-4`},ze={class:`w-full border-collapse font-mono text-[0.8125rem]`},Be={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},Ve={class:`break-all px-2 py-1 align-top`},He={class:`w-full border-collapse font-mono text-[0.8125rem]`},Ue={class:`w-32 break-all px-2 py-1 align-top text-muted sm:w-96 sm:break-words`},We={class:`px-2 py-1 align-top`},Ge={key:1,class:`text-xs text-muted`},Ke={class:`mt-4`},qe={key:0,class:`w-full border-collapse font-mono text-[0.8125rem]`},Je={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},Ye={class:`break-all px-2 py-1 align-top`},Xe={key:0},B={key:1,class:`text-dimmed`},Ze={key:1,class:`text-xs text-muted`},Qe={class:`mt-4`},$e={class:`mb-1 text-xs text-muted`},et={class:`overflow-x-auto`},tt={class:`w-full border-collapse font-mono text-[0.8125rem]`},nt={class:`break-all px-2 py-1 align-top`},rt={key:0,class:`text-xs text-muted`},it={class:`break-all px-2 py-1 align-top`},at=[`href`],ot={key:1},st={key:2,class:`text-dimmed`},ct={class:`break-all px-2 py-1 align-top`},lt={key:0},ut={key:1,class:`text-dimmed`},dt={key:2},ft={key:3,class:`text-dimmed`},pt={class:`break-all px-2 py-1 align-top`},mt={key:0},ht={key:1,class:`text-dimmed`},gt={key:2},_t={key:3,class:`text-dimmed`},vt={key:1,class:`text-xs text-muted`},yt={class:`mt-4`},bt={class:`w-full border-collapse font-mono text-[0.8125rem]`},xt={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},St={class:`px-2 py-1 align-top`},Ct={class:`mt-4`},wt={key:0,class:`w-full border-collapse font-mono text-[0.8125rem]`},Tt={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},Et={class:`break-all px-2 py-1 align-top`},Dt={class:`text-xs text-muted`},Ot={key:1,class:`text-xs text-muted`},kt={class:`mt-4`},At={class:`w-full border-collapse font-mono text-[0.8125rem]`},jt={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},Mt={class:`break-all px-2 py-1 align-top`},Nt={key:0},Pt={key:1,class:`text-dimmed`},Ft={class:`mt-4 text-xs text-muted`},It={class:`rounded bg-elevated px-1 py-0.5`},Lt={class:`rounded bg-elevated px-1 py-0.5`},Rt={class:`rounded bg-elevated px-1 py-0.5`},V=te({__name:`ResidentDetailPage`,setup(te){let V=c(`resident`),H=s(()=>V?.record??{}),U=s(()=>ae(H.value)),W=s(()=>ue(H.value)||(V?.slug??``)),G=s(()=>h(U.value.sha)),K=s(()=>se.test(W.value)?`https://github.com/${W.value}`:void 0),q=s(()=>K.value&&/^[0-9a-f]{7,40}$/.test(G.value)?`${K.value}/commit/${G.value}`:void 0),J=s(()=>{let e=U.value.snapshot;return e&&typeof e==`object`?_(e):void 0}),zt=s(()=>_(U.value.schedules)),Y=s(()=>{let e=_(H.value.commands),t=_(H.value.effects);return Object.keys(e).sort().map(n=>({name:n,command:h(e[n]),effect:h(t[n])||`readonly`}))}),X=s(()=>{let e=U.value.threads;return(Array.isArray(e)?e.map(_):[]).map(e=>{let t=h(e.sha);return{threadKey:h(e.threadKey)||`?`,ref:h(e.ref)||`?`,sha:t?t.slice(0,8):``,commitHref:K.value&&/^[0-9a-f]{7,40}$/.test(t)?`${K.value}/commit/${t}`:void 0,user:h(e.user),deps:h(e.deps),boundAt:h(e.boundAt),lastAttachAt:h(e.lastAttachAt),evicted:e.evicted===!0,evictedAt:h(e.evictedAt),evictedWhy:h(e.evictedWhy)}}).sort((e,t)=>t.lastAttachAt.localeCompare(e.lastAttachAt))}),Z=s(()=>X.value.filter(e=>!e.evicted).length),Q=s(()=>{let e=U.value.lastRestore;return e?JSON.stringify(e):``}),$=s(()=>re(H.value)),Bt=s(()=>typeof H.value.diskBudgetMb==`number`?H.value.diskBudgetMb:void 0),Vt=s(()=>{let e=$.value;if(!e)return[];let t=le(e),{freeKiB:n,capped:r,capacityKiB:i}=oe(e,Bt.value),a=n-t.totalKiB,o=t=>{let n=ne(e.parts,t);return n===null?`? (checkout not measured)`:n===0?`?`:`${Math.max(0,Math.floor(a/n))} more (${g(n)} each)`};return[[`used / total`,ce(e)],[`free`,`${g(n)}${r?` under the ${g(i)} diskBudgetMb cap`:``}`],[`reserve`,`${g(t.totalKiB)} (snapshot staging ${g(t.stagingKiB)} + floor ${g(t.floorKiB)})`],[`headroom`,`${g(Math.max(0,a))} — room for ${o(`hardlink`)} hardlinked trees, ${o(`reconcile`)} lockfile-diverged (reconciling)`],[`measured`,e.at||`—`]]}),Ht=s(()=>{let e=$.value;if(!e)return[];let t=[[`mirror`,g(e.parts.mirror)],[`checkout deps (node_modules)`,g(e.parts.deps)],[`checkout (history + tree + build)`,g(e.parts.checkout)]];for(let[n,r]of Object.entries(e.parts.threads).sort((e,t)=>t[1]-e[1]))t.push([`thread ${n}`,g(r)]);for(let[n,r]of Object.entries(e.parts.homes).sort((e,t)=>t[1]-e[1]))r>=1024&&t.push([`home ${n}`,g(r)]);return t.push([`other (image, /tmp, …)`,g(e.parts.other)]),t});return(s,c)=>(o(),i(e,{title:W.value||`Resident`,nav:`residents`},{leading:t(()=>[...c[0]||=[l(`a`,{class:`back text-sm text-muted no-underline hover:text-primary`,href:`/residents`},`← All residents`,-1)]]),default:t(()=>[l(`section`,de,[c[8]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Lifecycle`,-1),l(`table`,fe,[l(`tbody`,null,[l(`tr`,pe,[c[1]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`state`,-1),l(`td`,me,[r(m,{tone:f(ie)(U.value.state),label:U.value.state},null,8,[`tone`,`label`]),l(`span`,v,p(U.value.state),1)])]),l(`tr`,y,[c[2]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`reason`,-1),l(`td`,b,[U.value.reason?(o(),u(`span`,x,p(U.value.reason),1)):(o(),u(`span`,S,`—`))])]),l(`tr`,C,[c[3]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`last refresh error`,-1),l(`td`,w,[f(h)(U.value.lastRefreshError)?(o(),u(`span`,T,p(f(h)(U.value.lastRefreshError)),1)):(o(),u(`span`,E,`—`))])]),l(`tr`,D,[c[4]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`last restore`,-1),l(`td`,O,[Q.value?(o(),u(`span`,k,p(Q.value),1)):(o(),u(`span`,A,`—`))])]),l(`tr`,j,[c[5]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`state updated`,-1),l(`td`,M,[f(h)(U.value.updatedAt)?(o(),u(`span`,N,p(f(h)(U.value.updatedAt)),1)):(o(),u(`span`,P,`—`))])]),l(`tr`,F,[c[7]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`idle since`,-1),l(`td`,I,[f(h)(U.value.idleSince)?(o(),u(n,{key:0},[a(p(f(h)(U.value.idleSince))+` `,1),c[6]||=l(`span`,{class:`text-xs text-muted`},`(refresh parked; container may sleep)`,-1)],64)):(o(),u(`span`,L,`awake`))])])])])]),l(`section`,R,[c[15]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Pinned facts`,-1),l(`table`,z,[l(`tbody`,null,[l(`tr`,he,[c[9]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`repository`,-1),l(`td`,ge,[K.value?(o(),u(`a`,{key:0,class:`text-primary`,href:K.value},p(K.value),9,_e)):(o(),u(`span`,ve,p(f(h)(H.value.resource)||`—`),1))])]),l(`tr`,ye,[c[10]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`default ref`,-1),l(`td`,be,p(f(h)(U.value.defaultRef)||f(h)(H.value.defaultRef)||`—`),1)]),l(`tr`,xe,[c[11]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`pinned sha`,-1),l(`td`,Se,[q.value?(o(),u(`a`,{key:0,class:`text-primary`,href:q.value},p(G.value),9,Ce)):G.value?(o(),u(`span`,we,p(G.value),1)):(o(),u(`span`,Te,`—`))])]),l(`tr`,Ee,[c[12]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`lockfile hash`,-1),l(`td`,De,[f(h)(U.value.lockfileHash)?(o(),u(`span`,Oe,p(f(h)(U.value.lockfileHash)),1)):(o(),u(`span`,ke,`—`))])]),l(`tr`,Ae,[c[13]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`provisioned`,-1),l(`td`,je,[f(h)(U.value.provisionedAt)?(o(),u(`span`,Me,p(f(h)(U.value.provisionedAt)),1)):(o(),u(`span`,Ne,`—`))])]),l(`tr`,Pe,[c[14]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`last refresh`,-1),l(`td`,Fe,[f(h)(U.value.lastRefreshAt)?(o(),u(`span`,Ie,p(f(h)(U.value.lastRefreshAt)),1)):(o(),u(`span`,Le,`—`))])])])])]),l(`section`,Re,[c[17]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Disk`,-1),$.value?(o(),u(n,{key:0},[l(`table`,ze,[l(`tbody`,null,[(o(!0),u(n,null,d(Vt.value,([e,t])=>(o(),u(`tr`,{key:e,class:`border-t border-muted`},[l(`td`,Be,p(e),1),l(`td`,Ve,p(t),1)]))),128))])]),c[16]||=l(`p`,{class:`mb-1 mt-2 text-xs text-muted`},` components (one du, hardlinks counted once — a thread tree shows only what it does not share with the checkout) `,-1),l(`table`,He,[l(`tbody`,null,[(o(!0),u(n,null,d(Ht.value,([e,t])=>(o(),u(`tr`,{key:e,class:`border-t border-muted`},[l(`td`,Ue,p(e),1),l(`td`,We,p(t),1)]))),128))])])],64)):(o(),u(`p`,Ge,` not measured yet — the first refresh cycle or attach of this container measures it `))]),l(`section`,Ke,[c[18]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Snapshot stamp`,-1),J.value?(o(),u(`table`,qe,[l(`tbody`,null,[(o(),u(n,null,d([`ref`,`sha`,`lockfileHash`,`createdAt`,`mirrorBackupId`,`checkoutBackupId`],e=>l(`tr`,{key:e,class:`border-t border-muted`},[l(`td`,Je,p(e),1),l(`td`,Ye,[f(h)(J.value[e])?(o(),u(`span`,Xe,p(f(h)(J.value[e])),1)):(o(),u(`span`,B,`—`))])])),64))])])):(o(),u(`p`,Ze,`no snapshot recorded`))]),l(`section`,Qe,[c[22]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Thread worktrees`,-1),X.value.length>0?(o(),u(n,{key:0},[l(`p`,$e,p(Z.value)+` live · `+p(X.value.length-Z.value)+` evicted`,1),l(`div`,et,[l(`table`,tt,[l(`tbody`,null,[c[21]||=l(`tr`,{class:`text-xs text-muted`},[l(`td`,{class:`px-2 py-1`},`thread`),l(`td`,{class:`px-2 py-1`},`ref · sha`),l(`td`,{class:`px-2 py-1`},`user · deps`),l(`td`,{class:`px-2 py-1`},`bound · last attach`)],-1),(o(!0),u(n,null,d(X.value,e=>(o(),u(`tr`,{key:e.threadKey,class:`border-t border-muted`},[l(`td`,nt,[e.evicted?(o(),u(`span`,rt,[a(`evicted `+p(e.evictedAt||`—`),1),e.evictedWhy?(o(),u(n,{key:0},[a(` · `+p(e.evictedWhy),1)],64)):ee(``,!0)])):(o(),i(m,{key:1,tone:`green`,label:`live`,tip:`live`})),a(` `+p(e.threadKey),1)]),l(`td`,it,[a(p(e.ref)+` · `,1),e.commitHref?(o(),u(`a`,{key:0,class:`text-primary`,href:e.commitHref},p(e.sha),9,at)):e.sha?(o(),u(`span`,ot,p(e.sha),1)):(o(),u(`span`,st,`—`))]),l(`td`,ct,[e.user?(o(),u(`span`,lt,p(e.user),1)):(o(),u(`span`,ut,`—`)),c[19]||=a(` · `,-1),e.deps?(o(),u(`span`,dt,p(e.deps),1)):(o(),u(`span`,ft,`—`))]),l(`td`,pt,[e.boundAt?(o(),u(`span`,mt,p(e.boundAt),1)):(o(),u(`span`,ht,`—`)),c[20]||=a(` · `,-1),e.lastAttachAt?(o(),u(`span`,gt,p(e.lastAttachAt),1)):(o(),u(`span`,_t,`—`))])]))),128))])])])],64)):(o(),u(`p`,vt,`no thread worktrees`))]),l(`section`,yt,[c[23]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Pending schedules`,-1),l(`table`,bt,[l(`tbody`,null,[(o(),u(n,null,d([[`refresh`,`refresh`],[`provision run`,`provisionRun`],[`provision deadline`,`provisionDeadline`]],([e,t])=>l(`tr`,{key:t,class:`border-t border-muted`},[l(`td`,xt,p(e),1),l(`td`,St,p(f(h)(zt.value[t]??0)||`0`),1)])),64))])])]),l(`section`,Ct,[c[25]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Command table`,-1),Y.value.length>0?(o(),u(`table`,wt,[l(`tbody`,null,[(o(!0),u(n,null,d(Y.value,e=>(o(),u(`tr`,{key:e.name,class:`border-t border-muted`},[l(`td`,Tt,p(e.name),1),l(`td`,Et,[l(`code`,null,p(e.command),1),c[24]||=a(),l(`span`,Dt,p(e.effect),1)])]))),128))])])):(o(),u(`p`,Ot,`no command table`))]),l(`section`,kt,[c[26]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Registry settings`,-1),l(`table`,At,[l(`tbody`,null,[(o(!0),u(n,null,d([[`onboarded`,f(h)(H.value.onboardedAt)],[`record updated`,f(h)(H.value.updatedAt)],[`provisioning timeout (ms)`,f(h)(H.value.provisioningTimeoutMs)],[`disk budget (MB)`,f(h)(H.value.diskBudgetMb)],[`worktree TTL (days)`,f(h)(H.value.worktreeTtlDays??7)]],([e,t])=>(o(),u(`tr`,{key:e,class:`border-t border-muted`},[l(`td`,jt,p(e),1),l(`td`,Mt,[t?(o(),u(`span`,Nt,p(t),1)):(o(),u(`span`,Pt,`—`))])]))),128))])])]),l(`p`,Ft,[c[27]||=a(` Manage from chat: `,-1),l(`code`,It,`repo rebuild `+p(W.value),1),c[28]||=a(` · `,-1),l(`code`,Lt,`repo reconfigure `+p(W.value)+` …`,1),c[29]||=a(` · `,-1),l(`code`,Rt,`repo offboard `+p(W.value)+` --dry-run`,1)])]),_:1},8,[`title`]))}});export{V as default};
@@ -1 +1 @@
1
- import{t as e}from"./AppShell-lYVcj-k7.js";import{Lr as t,Xt as n,_n as r,cn as i,gn as a,ir as o,ln as s,mr as c,on as l,r as u,sn as d,un as f,ur as p,wi as m,xi as h,yn as g}from"./seed-DeKSHrt2.js";import{n as _}from"./wallClock-61NpVkY6.js";import{t as v}from"./StatusDot-CFXbAw7S.js";import{c as y,d as b,f as x,l as S,o as C,r as w,u as T}from"./residentDiskBudget-BMBKlYRH.js";import{n as E}from"./indexFormat-B-pd4r7Y.js";var D={class:`mb-2 text-xs text-muted`},O={class:`m-0 list-none p-0`},k={class:`font-mono font-medium text-primary`},A={class:`font-medium`},j=[`title`],M=[`title`],N={key:0,class:`basis-full pl-5 text-xs text-warn`},P={key:1,class:`px-2 py-1.5 text-muted`},F=g({__name:`ResidentsIndexPage`,setup(g){let F=u(`residents`),I=_(),L=l(()=>(F?.residents??[]).map((e,t)=>{let n=e,r=T(n),i=S(n),a=x(i.sha),o=x(i.lastRefreshAt),s=o?Date.parse(o):NaN,c=y(n);return{key:`${r||`?`}-${t}`,display:r||x(n.resource)||`?`,state:i.state,tone:b(i.state),reason:i.reason,ref:x(n.defaultRef)||`?`,sha:a?a.slice(0,8):``,refreshed:o,refreshedLabel:Number.isFinite(s)?E(s,I):o,disk:c?w(c):``,diskAt:c?.at??``,href:C.test(r)?`/residents/${r}`:null}})),R=l(()=>x(F?.cap)||`?`),z=l(()=>x(F?.count)||String(L.value.length));return(l,u)=>(o(),i(e,{title:`Resident repos`,nav:`residents`},{default:t(()=>[L.value.length>0?(o(),f(n,{key:0},[d(`p`,D,m(z.value)+`/`+m(R.value)+` resident slots in use · live registry read, not cached `,1),d(`ul`,O,[(o(!0),f(n,null,p(L.value,e=>(o(),f(`li`,{key:e.key,class:`border-b border-muted first:border-t`},[(o(),i(c(e.href?`a`:`span`),{class:h([`row flex flex-wrap items-center gap-2.5 rounded-md px-2 py-1.5 text-inherit no-underline`,e.href?`hover:bg-elevated`:``]),href:e.href??void 0},{default:t(()=>[r(v,{tone:e.tone,label:e.state,tip:e.state},null,8,[`tone`,`label`,`tip`]),d(`span`,k,m(e.display),1),d(`span`,A,m(e.state),1),d(`span`,{class:`font-mono text-xs text-muted max-sm:basis-full max-sm:pl-5`,title:e.refreshed||void 0},[a(` ref `+m(e.ref),1),e.sha?(o(),f(n,{key:0},[a(` · sha `+m(e.sha),1)],64)):s(``,!0),e.refreshedLabel?(o(),f(n,{key:1},[a(` · refreshed `+m(e.refreshedLabel),1)],64)):s(``,!0),e.disk?(o(),f(n,{key:2},[u[0]||=a(` · `,-1),d(`span`,{title:e.diskAt?`measured ${e.diskAt}`:void 0},`disk `+m(e.disk),9,M)],64)):s(``,!0)],8,j),e.reason?(o(),f(`span`,N,m(e.reason),1)):s(``,!0)]),_:2},1032,[`class`,`href`]))]))),128))])],64)):(o(),f(`p`,P,[a(` No repos onboarded (0/`+m(R.value)+`). Onboard one from chat: `,1),u[1]||=d(`code`,{class:`rounded bg-elevated px-1.5 py-0.5`},`repo onboard <owner/name>`,-1),u[2]||=a(`. `,-1)]))]),_:1}))}});export{F as default};
1
+ import{t as e}from"./AppShell-lYVcj-k7.js";import{Lr as t,Xt as n,_n as r,cn as i,gn as a,ir as o,ln as s,mr as c,on as l,r as u,sn as d,un as f,ur as p,wi as m,xi as h,yn as g}from"./seed-DeKSHrt2.js";import{n as _}from"./wallClock-61NpVkY6.js";import{t as v}from"./StatusDot-DDc88Kbs.js";import{c as y,d as b,f as x,l as S,o as C,r as w,u as T}from"./residentDiskBudget-BMBKlYRH.js";import{n as E}from"./indexFormat-B-pd4r7Y.js";var D={class:`mb-2 text-xs text-muted`},O={class:`m-0 list-none p-0`},k={class:`font-mono font-medium text-primary`},A={class:`font-medium`},j=[`title`],M=[`title`],N={key:0,class:`basis-full pl-5 text-xs text-warn`},P={key:1,class:`px-2 py-1.5 text-muted`},F=g({__name:`ResidentsIndexPage`,setup(g){let F=u(`residents`),I=_(),L=l(()=>(F?.residents??[]).map((e,t)=>{let n=e,r=T(n),i=S(n),a=x(i.sha),o=x(i.lastRefreshAt),s=o?Date.parse(o):NaN,c=y(n);return{key:`${r||`?`}-${t}`,display:r||x(n.resource)||`?`,state:i.state,tone:b(i.state),reason:i.reason,ref:x(n.defaultRef)||`?`,sha:a?a.slice(0,8):``,refreshed:o,refreshedLabel:Number.isFinite(s)?E(s,I):o,disk:c?w(c):``,diskAt:c?.at??``,href:C.test(r)?`/residents/${r}`:null}})),R=l(()=>x(F?.cap)||`?`),z=l(()=>x(F?.count)||String(L.value.length));return(l,u)=>(o(),i(e,{title:`Resident repos`,nav:`residents`},{default:t(()=>[L.value.length>0?(o(),f(n,{key:0},[d(`p`,D,m(z.value)+`/`+m(R.value)+` resident slots in use · live registry read, not cached `,1),d(`ul`,O,[(o(!0),f(n,null,p(L.value,e=>(o(),f(`li`,{key:e.key,class:`border-b border-muted first:border-t`},[(o(),i(c(e.href?`a`:`span`),{class:h([`row flex flex-wrap items-center gap-2.5 rounded-md px-2 py-1.5 text-inherit no-underline`,e.href?`hover:bg-elevated`:``]),href:e.href??void 0},{default:t(()=>[r(v,{tone:e.tone,label:e.state,tip:e.state},null,8,[`tone`,`label`,`tip`]),d(`span`,k,m(e.display),1),d(`span`,A,m(e.state),1),d(`span`,{class:`font-mono text-xs text-muted max-sm:basis-full max-sm:pl-5`,title:e.refreshed||void 0},[a(` ref `+m(e.ref),1),e.sha?(o(),f(n,{key:0},[a(` · sha `+m(e.sha),1)],64)):s(``,!0),e.refreshedLabel?(o(),f(n,{key:1},[a(` · refreshed `+m(e.refreshedLabel),1)],64)):s(``,!0),e.disk?(o(),f(n,{key:2},[u[0]||=a(` · `,-1),d(`span`,{title:e.diskAt?`measured ${e.diskAt}`:void 0},`disk `+m(e.disk),9,M)],64)):s(``,!0)],8,j),e.reason?(o(),f(`span`,N,m(e.reason),1)):s(``,!0)]),_:2},1032,[`class`,`href`]))]))),128))])],64)):(o(),f(`p`,P,[a(` No repos onboarded (0/`+m(R.value)+`). Onboard one from chat: `,1),u[1]||=d(`code`,{class:`rounded bg-elevated px-1.5 py-0.5`},`repo onboard <owner/name>`,-1),u[2]||=a(`. `,-1)]))]),_:1}))}});export{F as default};