@specship/specship-win32-arm64 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/lib/dist/bin/specship.js +48 -12
  2. package/lib/dist/bin/specship.js.map +1 -1
  3. package/lib/dist/db/migrations.d.ts +1 -1
  4. package/lib/dist/db/migrations.d.ts.map +1 -1
  5. package/lib/dist/db/migrations.js +16 -1
  6. package/lib/dist/db/migrations.js.map +1 -1
  7. package/lib/dist/db/schema.sql +10 -0
  8. package/lib/dist/db/spec-queries.d.ts +6 -0
  9. package/lib/dist/db/spec-queries.d.ts.map +1 -1
  10. package/lib/dist/db/spec-queries.js +8 -0
  11. package/lib/dist/db/spec-queries.js.map +1 -1
  12. package/lib/dist/index.d.ts +8 -0
  13. package/lib/dist/index.d.ts.map +1 -1
  14. package/lib/dist/index.js +9 -0
  15. package/lib/dist/index.js.map +1 -1
  16. package/lib/dist/server/cli.js +9 -7
  17. package/lib/dist/server/product-version.js +44 -0
  18. package/lib/dist/server/routes/claude.js +153 -42
  19. package/lib/dist/server/routes/config.js +35 -0
  20. package/lib/dist/server/routes/graph.js +22 -1
  21. package/lib/dist/server/routes/mcp.js +510 -0
  22. package/lib/dist/server/routes/projects.js +31 -3
  23. package/lib/dist/server/routes/status.js +3 -0
  24. package/lib/dist/server/routes/workflow.js +44 -3
  25. package/lib/dist/server/server-config.js +38 -0
  26. package/lib/dist/server/server.js +128 -58
  27. package/lib/dist/statusline/active-run.d.ts +2 -2
  28. package/lib/dist/statusline/active-run.d.ts.map +1 -1
  29. package/lib/dist/statusline/active-run.js +2 -2
  30. package/lib/dist/statusline/active-run.js.map +1 -1
  31. package/lib/dist/statusline/render.d.ts.map +1 -1
  32. package/lib/dist/statusline/render.js +41 -5
  33. package/lib/dist/statusline/render.js.map +1 -1
  34. package/lib/dist/statusline/types.d.ts +15 -0
  35. package/lib/dist/statusline/types.d.ts.map +1 -1
  36. package/lib/dist/ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  37. package/lib/dist/ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  38. package/lib/dist/ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  39. package/lib/dist/ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  40. package/lib/dist/ui/assets/geist-mono-cyrillic-ext-wght-normal-I4S5GZfc.woff2 +0 -0
  41. package/lib/dist/ui/assets/geist-mono-cyrillic-wght-normal-BmXc_FBt.woff2 +0 -0
  42. package/lib/dist/ui/assets/geist-mono-latin-ext-wght-normal-DrnZ1wKl.woff2 +0 -0
  43. package/lib/dist/ui/assets/geist-mono-latin-wght-normal-B_7UjwxQ.woff2 +0 -0
  44. package/lib/dist/ui/assets/geist-mono-symbols2-wght-normal-GZpp1pK2.woff2 +0 -0
  45. package/lib/dist/ui/assets/geist-mono-vietnamese-wght-normal-D8KDMBhC.woff2 +0 -0
  46. package/lib/dist/ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  47. package/lib/dist/ui/assets/index-D8e4LiVb.js +51 -0
  48. package/lib/dist/ui/assets/index-ezwX2EfG.css +1 -0
  49. package/lib/dist/ui/favicon-16.png +0 -0
  50. package/lib/dist/ui/favicon-180.png +0 -0
  51. package/lib/dist/ui/favicon-32.png +0 -0
  52. package/lib/dist/ui/favicon.svg +20 -0
  53. package/lib/dist/ui/index.html +17 -0
  54. package/lib/dist/update/resolve-latest.d.ts +14 -0
  55. package/lib/dist/update/resolve-latest.d.ts.map +1 -0
  56. package/lib/dist/update/resolve-latest.js +29 -0
  57. package/lib/dist/update/resolve-latest.js.map +1 -0
  58. package/lib/dist/update/run-installer.d.ts +13 -0
  59. package/lib/dist/update/run-installer.d.ts.map +1 -0
  60. package/lib/dist/update/run-installer.js +43 -0
  61. package/lib/dist/update/run-installer.js.map +1 -0
  62. package/lib/dist/update/updater.d.ts +53 -0
  63. package/lib/dist/update/updater.d.ts.map +1 -0
  64. package/lib/dist/update/updater.js +164 -0
  65. package/lib/dist/update/updater.js.map +1 -0
  66. package/lib/dist/workflows/eta.d.ts +42 -0
  67. package/lib/dist/workflows/eta.d.ts.map +1 -0
  68. package/lib/dist/workflows/eta.js +146 -0
  69. package/lib/dist/workflows/eta.js.map +1 -0
  70. package/lib/dist/workflows/executor.d.ts.map +1 -1
  71. package/lib/dist/workflows/executor.js +25 -6
  72. package/lib/dist/workflows/executor.js.map +1 -1
  73. package/lib/dist/workflows/runners/prompt.d.ts +6 -0
  74. package/lib/dist/workflows/runners/prompt.d.ts.map +1 -1
  75. package/lib/dist/workflows/runners/prompt.js +10 -0
  76. package/lib/dist/workflows/runners/prompt.js.map +1 -1
  77. package/lib/dist/workflows/runners/types.d.ts +12 -0
  78. package/lib/dist/workflows/runners/types.d.ts.map +1 -1
  79. package/lib/node_modules/.package-lock.json +1 -1
  80. package/lib/package.json +3 -2
  81. package/package.json +1 -1
  82. package/lib/dist/server/ssr/md.mjs +0 -83
  83. package/lib/dist/server/ssr/public/app.css +0 -1
  84. package/lib/dist/server/ssr/render.mjs +0 -564
  85. package/lib/dist/server/ssr/routes.js +0 -73
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Persisted server runtime config — the settings the dashboard can change
3
+ * at runtime and that must survive a restart (REQ-DESKTOP-028.A2). Lives at
4
+ * `~/.specship/server-config.json` (user-level, not per-project: the ingest
5
+ * watcher reads every project's transcripts). `SPECSHIP_SERVER_CONFIG`
6
+ * overrides the path so tests never touch the real home directory.
7
+ */
8
+ import * as fs from 'node:fs';
9
+ import * as os from 'node:os';
10
+ import * as path from 'node:path';
11
+ export function serverConfigPath() {
12
+ return process.env.SPECSHIP_SERVER_CONFIG
13
+ ?? path.join(os.homedir(), '.specship', 'server-config.json');
14
+ }
15
+ export function readServerConfig() {
16
+ try {
17
+ const raw = fs.readFileSync(serverConfigPath(), 'utf-8');
18
+ const parsed = JSON.parse(raw);
19
+ if (parsed && typeof parsed === 'object')
20
+ return parsed;
21
+ }
22
+ catch { /* missing or corrupt → defaults */ }
23
+ return {};
24
+ }
25
+ /**
26
+ * Merge `patch` into the stored config and write it back atomically:
27
+ * write to a sibling temp file, then rename over the target. A crash
28
+ * mid-write can never leave a truncated JSON file behind.
29
+ */
30
+ export function writeServerConfig(patch) {
31
+ const merged = { ...readServerConfig(), ...patch };
32
+ const file = serverConfigPath();
33
+ fs.mkdirSync(path.dirname(file), { recursive: true });
34
+ const tmp = `${file}.${process.pid}.tmp`;
35
+ fs.writeFileSync(tmp, JSON.stringify(merged, null, 2) + '\n', 'utf-8');
36
+ fs.renameSync(tmp, file);
37
+ return merged;
38
+ }
@@ -33,6 +33,9 @@ import { registerReflectRoutes } from './routes/reflect.js';
33
33
  import { registerMaintainabilityRoutes } from './routes/maintainability.js';
34
34
  import { registerDomainRoutes } from './routes/domain.js';
35
35
  import { registerChatRoutes } from './routes/chat.js';
36
+ import { registerMcpRoutes } from './routes/mcp.js';
37
+ import { registerConfigRoutes } from './routes/config.js';
38
+ import { readServerConfig } from './server-config.js';
36
39
  /**
37
40
  * Lazy-import the specship core. Two delivery shapes are supported:
38
41
  *
@@ -43,11 +46,37 @@ import { registerChatRoutes } from './routes/chat.js';
43
46
  * resolution finding `@specship/specship` (it won't, the
44
47
  * bundle stages a single package by name `@specship/specship`).
45
48
  *
46
- * 2. **Workspace / dev** — `packages/server/dist/server.js` imports via
47
- * the workspace `file:../..` dep. Falls through to the named import.
49
+ * 2. **Workspace / dev** — `server/dist/server.js` imports via
50
+ * the workspace `file:..` dep. Falls through to the named import.
48
51
  *
49
52
  * The function caches the resolved module so the lookup only runs once.
50
53
  */
54
+ /**
55
+ * Locate the built desktop SPA (REQ-DESKTOP-017.A1) when the caller didn't
56
+ * pass an explicit `webDir`. Two delivery shapes, probed relative to this
57
+ * file so cwd never matters:
58
+ *
59
+ * 1. **Bundled** — `build-server-bundle.mjs` copies `ui/dist/**` to the
60
+ * root `dist/ui/`, which the platform tarball ships as
61
+ * `<bundle>/lib/dist/ui/` next to `dist/server/` (this file).
62
+ * 2. **Workspace / dev** — `server/{src,dist}/server.*` →
63
+ * repo root → `ui/dist/` (present only after `cd ui && npm run build`).
64
+ *
65
+ * Returns null when neither exists — the server then simply has no SPA
66
+ * mount, same as `webDir: null`.
67
+ */
68
+ export function resolveDefaultWebDir() {
69
+ const here = path.dirname(fileURLToPath(import.meta.url));
70
+ const candidates = [
71
+ path.resolve(here, '..', 'ui'), // bundled: dist/server → dist/ui
72
+ path.resolve(here, '..', '..', 'ui', 'dist'), // workspace: server/dist → <root>/ui/dist
73
+ ];
74
+ for (const dir of candidates) {
75
+ if (existsSync(path.join(dir, 'index.html')))
76
+ return dir;
77
+ }
78
+ return null;
79
+ }
51
80
  let cachedSpecShip = null;
52
81
  async function loadSpecShip() {
53
82
  if (cachedSpecShip)
@@ -110,59 +139,102 @@ export async function createServer(options) {
110
139
  // provided one or explicitly opted out. Hooks into the primary project's
111
140
  // SQLite handle — when there's no primary, analytics endpoints will return
112
141
  // 409 until one is set (typically the next server restart with -p).
142
+ //
143
+ // The persisted runtime config (~/.specship/server-config.json) gates the
144
+ // start too: the Settings ingest toggle must survive a restart
145
+ // (REQ-DESKTOP-028.A2). CLI `--no-ingest` still wins over everything.
113
146
  let watcher = options.watcher ?? null;
114
147
  let ownedWatcher = false;
115
- if (!watcher && options.ingest !== false && primaryCg) {
148
+ let ingestEnabled = watcher != null
149
+ || (options.ingest !== false && readServerConfig().ingestEnabled !== false);
150
+ const startIngestWatcher = () => {
151
+ if (watcher)
152
+ return true;
153
+ if (!primaryCg)
154
+ return false;
116
155
  const cgAny = primaryCg;
117
156
  const dbHandle = cgAny.db?.getDb ? cgAny.db.getDb() : cgAny.queries?.db;
118
- if (dbHandle) {
119
- // Build a sync resolveGraph: for the primary project path return the
120
- // already-open SpecShip instance (which satisfies GraphLike).
121
- // Sessions from other project paths resolve to null — they'll be left
122
- // as 'unresolved' and retried on the next boot when that project is primary.
123
- // The stored project_path is the lossy-decoded slug (every '-' → '/'), so
124
- // an exact compare against the real primaryPath never matched and savings
125
- // stayed 0. primaryProjectMatcher accepts both the real path and its
126
- // mangled stored form. Sessions from OTHER projects still resolve to null
127
- // (left 'unresolved', retried when that project is primary).
128
- const primaryPath = options.projectRoot ?? null;
129
- const isPrimary = primaryPath ? primaryProjectMatcher(primaryPath) : () => false;
130
- const resolveGraph = (projectPath) => primaryPath && isPrimary(projectPath) ? primaryCg : null;
131
- watcher = startWatcher(dbHandle, { verbose, resolveGraph });
132
- ownedWatcher = true;
157
+ if (!dbHandle)
158
+ return false;
159
+ // Build a sync resolveGraph: for the primary project path return the
160
+ // already-open SpecShip instance (which satisfies GraphLike).
161
+ // Sessions from other project paths resolve to null — they'll be left
162
+ // as 'unresolved' and retried on the next boot when that project is primary.
163
+ // The stored project_path is the lossy-decoded slug (every '-' → '/'), so
164
+ // an exact compare against the real primaryPath never matched and savings
165
+ // stayed 0. primaryProjectMatcher accepts both the real path and its
166
+ // mangled stored form. Sessions from OTHER projects still resolve to null
167
+ // (left 'unresolved', retried when that project is primary).
168
+ const primaryPath = options.projectRoot ?? null;
169
+ const isPrimary = primaryPath ? primaryProjectMatcher(primaryPath) : () => false;
170
+ const resolveGraph = (projectPath) => primaryPath && isPrimary(projectPath) ? primaryCg : null;
171
+ watcher = startWatcher(dbHandle, { verbose, resolveGraph });
172
+ ownedWatcher = true;
173
+ if (verbose)
174
+ console.error('[specship-server] JSONL ingest watcher started');
175
+ // Backfill displaced_files / resolution for pre-upgrade rows (is_specship=1,
176
+ // resolution IS NULL). Idempotent — safe to run on every boot. Non-fatal:
177
+ // a failure here must never abort server startup.
178
+ try {
179
+ backfillDisplaced(dbHandle, resolveGraph);
133
180
  if (verbose)
134
- console.error('[specship-server] JSONL ingest watcher started');
135
- // Backfill displaced_files / resolution for pre-upgrade rows (is_specship=1,
136
- // resolution IS NULL). Idempotent — safe to run on every boot. Non-fatal:
137
- // a failure here must never abort server startup.
138
- try {
139
- backfillDisplaced(dbHandle, resolveGraph);
140
- if (verbose)
141
- console.error('[specship-server] specship-impact backfill complete');
142
- }
143
- catch (err) {
144
- console.error('[specship-server] specship-impact backfill failed (non-fatal):', err instanceof Error ? err.message : String(err));
145
- }
146
- // Re-cost prompts ingested while their model family was unpriced,
147
- // e.g. fable sessions stuck at $0 (REQ-DASHINT-001.A2). Idempotent.
148
- try {
149
- const recosted = recostUnpricedPrompts(dbHandle);
150
- if (verbose && recosted > 0)
151
- console.error(`[specship-server] re-costed ${recosted} unpriced prompts`);
152
- }
153
- catch (err) {
154
- console.error('[specship-server] pricing backfill failed (non-fatal):', err instanceof Error ? err.message : String(err));
155
- }
181
+ console.error('[specship-server] specship-impact backfill complete');
182
+ }
183
+ catch (err) {
184
+ console.error('[specship-server] specship-impact backfill failed (non-fatal):', err instanceof Error ? err.message : String(err));
185
+ }
186
+ // Re-cost prompts ingested while their model family was unpriced,
187
+ // e.g. fable sessions stuck at $0 (REQ-DASHINT-001.A2). Idempotent.
188
+ try {
189
+ const recosted = recostUnpricedPrompts(dbHandle);
190
+ if (verbose && recosted > 0)
191
+ console.error(`[specship-server] re-costed ${recosted} unpriced prompts`);
192
+ }
193
+ catch (err) {
194
+ console.error('[specship-server] pricing backfill failed (non-fatal):', err instanceof Error ? err.message : String(err));
195
+ }
196
+ return true;
197
+ };
198
+ if (!watcher && ingestEnabled) {
199
+ if (primaryCg) {
200
+ startIngestWatcher();
201
+ }
202
+ else if (verbose) {
203
+ console.error('[specship-server] no primary project — analytics will be empty until one is set');
156
204
  }
157
- }
158
- else if (!primaryCg && options.ingest !== false && verbose) {
159
- console.error('[specship-server] no primary project — analytics will be empty until one is set');
160
205
  }
161
206
  // Decorate the Fastify instance so route handlers can access shared state
162
207
  // without globals or DI containers.
163
208
  app.decorate('projects', registry);
164
209
  app.decorate('primaryCg', primaryCg);
165
210
  app.decorate('watcher', watcher);
211
+ // Runtime ingest control for GET/PUT /api/config (REQ-DESKTOP-028.A2).
212
+ // `enabled` is the configured intent (round-trips even when no primary
213
+ // project can host a watcher yet); `active` is whether one is running.
214
+ // start/stop keep `app.watcher` in sync so /api/refresh always sees the
215
+ // live handle.
216
+ app.decorate('ingestControl', {
217
+ enabled: () => ingestEnabled,
218
+ active: () => watcher != null,
219
+ start: () => {
220
+ ingestEnabled = true;
221
+ const started = startIngestWatcher();
222
+ app.watcher = watcher;
223
+ return started;
224
+ },
225
+ stop: () => {
226
+ ingestEnabled = false;
227
+ if (watcher) {
228
+ try {
229
+ watcher.stop();
230
+ }
231
+ catch { /* ignore */ }
232
+ }
233
+ watcher = null;
234
+ ownedWatcher = false;
235
+ app.watcher = null;
236
+ },
237
+ });
166
238
  // activeCg(req): resolve `?project=<slug>` → SpecShip instance, with the
167
239
  // primary as fallback. Returns null when nothing is selectable; route
168
240
  // handlers respond 409 in that case.
@@ -193,19 +265,17 @@ export async function createServer(options) {
193
265
  await registerMaintainabilityRoutes(app);
194
266
  await registerDomainRoutes(app);
195
267
  await registerChatRoutes(app);
196
- // SSR dashboard (DASH-LEAN-DOC / REQ-DASHLEAN-004): explicit page routes
197
- // rendered in-process from the /api handlers above (via app.inject), plus the
198
- // dashboard's static assets. Registered AFTER /api and BEFORE the SPA
199
- // fallback so the explicit page routes win.
200
- if (options.ssr) {
201
- const { registerSsrRoutes } = await import('./ssr/routes.js');
202
- await registerSsrRoutes(app);
203
- }
204
- // Optional: serve the built Angular UI from `webDir` and fall back to
205
- // index.html for client-side routes. Must register AFTER the /api/*
206
- // routes so they take precedence over the SPA wildcard.
207
- if (options.webDir) {
208
- const indexPath = path.join(options.webDir, 'index.html');
268
+ await registerMcpRoutes(app);
269
+ await registerConfigRoutes(app);
270
+ // Serve the built desktop SPA (the `ui/` module) from `webDir` and fall back
271
+ // to index.html for client-side routes. This is the dashboard's only surface
272
+ // (REQ-DESKTOP-033 — the server-rendered dashboard retired). Must register
273
+ // AFTER the /api/* routes so they take precedence over the SPA wildcard. When
274
+ // the caller passed no webDir at all, auto-detect the SPA shipped next to the
275
+ // server build; `null` explicitly opts out (headless / API only).
276
+ const webDir = options.webDir === undefined ? resolveDefaultWebDir() : options.webDir;
277
+ if (webDir) {
278
+ const indexPath = path.join(webDir, 'index.html');
209
279
  let indexBuffer = null;
210
280
  try {
211
281
  indexBuffer = await fs.readFile(indexPath);
@@ -217,7 +287,7 @@ export async function createServer(options) {
217
287
  }
218
288
  if (indexBuffer) {
219
289
  const cachedIndex = indexBuffer;
220
- const serveStatic = makeStaticHandler(options.webDir);
290
+ const serveStatic = makeStaticHandler(webDir);
221
291
  // A single 404 handler does both jobs:
222
292
  // 1. Try the requested URL as a real file under webDir → serve it
223
293
  // with the right content-type. Covers the SPA's chunk-*.js,
@@ -250,7 +320,7 @@ export async function createServer(options) {
250
320
  reply.code(200).type('text/html').send(cachedIndex);
251
321
  });
252
322
  if (verbose)
253
- console.error(`[specship-server] serving SPA from ${options.webDir}`);
323
+ console.error(`[specship-server] serving SPA from ${webDir}`);
254
324
  }
255
325
  }
256
326
  await app.listen({ host, port });
@@ -6,9 +6,9 @@
6
6
  * the `workflow_runs` table (which would mean a DB connection on the render
7
7
  * path). `clearActiveRun` removes the marker when no run is active.
8
8
  */
9
- import { ActiveRun } from './types';
9
+ import { ActiveRun, ActiveRunEta } from './types';
10
10
  /** Atomically record the active run. Best-effort; never throws. */
11
- export declare function writeActiveRun(projectRoot: string, specId: string | null, status: string): void;
11
+ export declare function writeActiveRun(projectRoot: string, specId: string | null, status: string, eta?: ActiveRunEta): void;
12
12
  /** Remove the active-run marker (e.g. once a run is merged/cancelled). */
13
13
  export declare function clearActiveRun(projectRoot: string): void;
14
14
  /** Read the active-run marker, or null when none. */
@@ -1 +1 @@
1
- {"version":3,"file":"active-run.d.ts","sourceRoot":"","sources":["../../src/statusline/active-run.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGpC,mEAAmE;AACnE,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAO/F;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAMxD;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAGnE"}
1
+ {"version":3,"file":"active-run.d.ts","sourceRoot":"","sources":["../../src/statusline/active-run.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGlD,mEAAmE;AACnE,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,MAAM,EAAE,MAAM,EACd,GAAG,CAAC,EAAE,YAAY,GACjB,IAAI,CAON;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAMxD;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAGnE"}
@@ -47,8 +47,8 @@ exports.readActiveRun = readActiveRun;
47
47
  const fs = __importStar(require("fs"));
48
48
  const paths_1 = require("./paths");
49
49
  /** Atomically record the active run. Best-effort; never throws. */
50
- function writeActiveRun(projectRoot, specId, status) {
51
- const data = { v: 1, specId, status, updatedAt: Date.now() };
50
+ function writeActiveRun(projectRoot, specId, status, eta) {
51
+ const data = { v: 1, specId, status, updatedAt: Date.now(), ...(eta ? { eta } : {}) };
52
52
  try {
53
53
  (0, paths_1.writeJsonAtomic)((0, paths_1.activeRunPath)(projectRoot), data);
54
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"active-run.js","sourceRoot":"","sources":["../../src/statusline/active-run.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOH,wCAOC;AAGD,wCAMC;AAGD,sCAGC;AA3BD,uCAAyB;AAEzB,mCAAuE;AAEvE,mEAAmE;AACnE,SAAgB,cAAc,CAAC,WAAmB,EAAE,MAAqB,EAAE,MAAc;IACvF,MAAM,IAAI,GAAc,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IACxE,IAAI,CAAC;QACH,IAAA,uBAAe,EAAC,IAAA,qBAAa,EAAC,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;AACH,CAAC;AAED,0EAA0E;AAC1E,SAAgB,cAAc,CAAC,WAAmB;IAChD,IAAI,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,IAAA,qBAAa,EAAC,WAAW,CAAC,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,oBAAoB;IACtB,CAAC;AACH,CAAC;AAED,qDAAqD;AACrD,SAAgB,aAAa,CAAC,WAAmB;IAC/C,MAAM,CAAC,GAAG,IAAA,oBAAY,EAAY,IAAA,qBAAa,EAAC,WAAW,CAAC,CAAC,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACnC,CAAC"}
1
+ {"version":3,"file":"active-run.js","sourceRoot":"","sources":["../../src/statusline/active-run.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOH,wCAYC;AAGD,wCAMC;AAGD,sCAGC;AAhCD,uCAAyB;AAEzB,mCAAuE;AAEvE,mEAAmE;AACnE,SAAgB,cAAc,CAC5B,WAAmB,EACnB,MAAqB,EACrB,MAAc,EACd,GAAkB;IAElB,MAAM,IAAI,GAAc,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACjG,IAAI,CAAC;QACH,IAAA,uBAAe,EAAC,IAAA,qBAAa,EAAC,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;AACH,CAAC;AAED,0EAA0E;AAC1E,SAAgB,cAAc,CAAC,WAAmB;IAChD,IAAI,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,IAAA,qBAAa,EAAC,WAAW,CAAC,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,oBAAoB;IACtB,CAAC;AACH,CAAC;AAED,qDAAqD;AACrD,SAAgB,aAAa,CAAC,WAAmB;IAC/C,MAAM,CAAC,GAAG,IAAA,oBAAY,EAAY,IAAA,qBAAa,EAAC,WAAW,CAAC,CAAC,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACnC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/statusline/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEjF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IACtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC;CAClB;AA+CD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CA6DxD"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/statusline/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEjF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IACtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC;CAClB;AA0ED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAoExD"}
@@ -18,6 +18,35 @@ function bar(pct) {
18
18
  const filled = Math.max(0, Math.min(cells, Math.round((pct / 100) * cells)));
19
19
  return `❮${'▰'.repeat(filled)}${'▱'.repeat(cells - filled)}❯`;
20
20
  }
21
+ /** Compact duration for the run ETA element: `4m`, `1h20m`, `<1m`. */
22
+ function fmtEtaDur(ms) {
23
+ const m = Math.round(ms / 60_000);
24
+ if (m < 1)
25
+ return '<1m';
26
+ if (m < 60)
27
+ return `${m}m`;
28
+ const h = Math.floor(m / 60);
29
+ const rest = m % 60;
30
+ return rest === 0 ? `${h}h` : `${h}h${rest}m`;
31
+ }
32
+ /**
33
+ * ETA suffix for the active-run element (REQ-STATUSLINE-011): a compact
34
+ * range for a running run, a waiting signal for a gated one, '' when the
35
+ * marker carries no estimate (older writer / no history).
36
+ */
37
+ function etaSuffix(run) {
38
+ const eta = run.eta;
39
+ if (!eta)
40
+ return '';
41
+ if (eta.kind === 'range') {
42
+ const low = fmtEtaDur(eta.lowMs);
43
+ const high = fmtEtaDur(eta.highMs);
44
+ return low === high ? ` ≈${low} left` : ` ≈${low}–${high} left`;
45
+ }
46
+ if (eta.kind === 'waiting')
47
+ return ' waiting on you';
48
+ return '';
49
+ }
21
50
  /**
22
51
  * Format a reset instant in the machine's local timezone: time-only when it
23
52
  * falls on the same local day as `now` (e.g. `(4pm)`), date + time otherwise
@@ -84,11 +113,15 @@ function renderSegment(input) {
84
113
  // Session call count — the honest usage signal. Zero placeholder when no marker.
85
114
  const calls = marker ? marker.calls : 0;
86
115
  parts.push(c(COLOR.calls, `${calls} ${calls === 1 ? 'call' : 'calls'}`));
87
- // Active workflow run, only when one exists.
116
+ // Active workflow run, only when one exists — with its remaining-time
117
+ // estimate when the marker carries one (REQ-STATUSLINE-011).
88
118
  if (run) {
89
119
  const label = run.specId ? `${run.specId}·${run.status}` : run.status;
90
- parts.push(c(COLOR.run, label));
120
+ parts.push(c(COLOR.run, `${label}${etaSuffix(run)}`));
91
121
  }
122
+ // Telemetry elements render on their own SECOND line (REQ-STATUSLINE-010):
123
+ // the SpecShip identity stays scannable while capacity bars get room.
124
+ const telemetry = [];
92
125
  // Context-usage element (REQ-STATUSLINE-009) — Claude's real context %, with
93
126
  // an escalating compaction warning past the threshold. Advisory only;
94
127
  // SpecShip cannot compact. Omitted when no real percentage is available.
@@ -96,7 +129,7 @@ function renderSegment(input) {
96
129
  const warn = context >= (ctxWarnPct ?? 80);
97
130
  const color = warn ? COLOR.pending : COLOR.calls; // amber when high, else gold
98
131
  const hint = warn ? ' ⚠ compact' : '';
99
- parts.push(c(color, `CTX ${bar(context)} ${Math.round(context)}%${hint}`));
132
+ telemetry.push(c(color, `CTX ${bar(context)} ${Math.round(context)}%${hint}`));
100
133
  }
101
134
  // Usage-limit sub-segment (REQ-STATUSLINE-008) — ONLY for windows with real
102
135
  // numbers; SpecShip never estimates. `now` formats reset times in local time.
@@ -105,11 +138,14 @@ function renderSegment(input) {
105
138
  if (!w)
106
139
  return;
107
140
  const reset = Number.isFinite(w.resetAt) ? ` ${formatReset(w.resetAt, now)}` : '';
108
- parts.push(c(COLOR.calls, `${label} ${bar(w.pctUsed)} ${Math.round(w.pctUsed)}%${reset}`));
141
+ telemetry.push(c(COLOR.calls, `${label} ${bar(w.pctUsed)} ${Math.round(w.pctUsed)}%${reset}`));
109
142
  };
110
143
  win('5h', usage.session);
111
144
  win('7d', usage.weekly);
112
145
  }
113
- return `${orn} ${brand}${sep}${parts.join(sep)} ${orn}`;
146
+ const line1 = `${orn} ${brand}${sep}${parts.join(sep)} ${orn}`;
147
+ if (telemetry.length === 0)
148
+ return line1;
149
+ return `${line1}\n${orn} ${telemetry.join(sep)} ${orn}`;
114
150
  }
115
151
  //# sourceMappingURL=render.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/statusline/render.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/statusline/render.ts"],"names":[],"mappings":"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"}
@@ -78,6 +78,19 @@ export interface UsageLimits {
78
78
  /** The weekly (7-day) window, or null when absent. */
79
79
  weekly: UsageWindow | null;
80
80
  }
81
+ /**
82
+ * Remaining-time estimate embedded in the run marker (REQ-STATUSLINE-011).
83
+ * Computed by the executor at marker-write time (WORKFLOW-ETA-DOC), so the
84
+ * render path never opens the DB. Absent when no estimate exists.
85
+ */
86
+ export type ActiveRunEta = {
87
+ kind: 'range';
88
+ lowMs: number;
89
+ highMs: number;
90
+ } | {
91
+ kind: 'waiting';
92
+ sinceMs?: number;
93
+ };
81
94
  /** The active (or most recent) workflow run for the project. */
82
95
  export interface ActiveRun {
83
96
  v: 1;
@@ -87,5 +100,7 @@ export interface ActiveRun {
87
100
  status: string;
88
101
  /** ms epoch of the last status change. */
89
102
  updatedAt: number;
103
+ /** Remaining-time estimate, when one exists (REQ-STATUSLINE-011). */
104
+ eta?: ActiveRunEta;
90
105
  }
91
106
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/statusline/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,CAAC,EAAE,CAAC,CAAC;IACL,yDAAyD;IACzD,WAAW,EAAE,OAAO,CAAC;IACrB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,yFAAyF;IACzF,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,+EAA+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,CAAC,EAAE,CAAC,CAAC;IACL,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,uEAAuE;IACvE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,8DAA8D;IAC9D,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,sDAAsD;IACtD,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;CAC5B;AAED,gEAAgE;AAChE,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,CAAC,CAAC;IACL,8DAA8D;IAC9D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,wFAAwF;IACxF,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/statusline/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,CAAC,EAAE,CAAC,CAAC;IACL,yDAAyD;IACzD,WAAW,EAAE,OAAO,CAAC;IACrB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,yFAAyF;IACzF,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,+EAA+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,CAAC,EAAE,CAAC,CAAC;IACL,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,uEAAuE;IACvE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,8DAA8D;IAC9D,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,sDAAsD;IACtD,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1C,gEAAgE;AAChE,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,CAAC,CAAC;IACL,8DAA8D;IAC9D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,wFAAwF;IACxF,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,GAAG,CAAC,EAAE,YAAY,CAAC;CACpB"}