instar 0.28.78 → 0.28.79

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 (65) hide show
  1. package/dashboard/index.html +170 -7
  2. package/dist/commands/init.d.ts.map +1 -1
  3. package/dist/commands/init.js +6 -4
  4. package/dist/commands/init.js.map +1 -1
  5. package/dist/commands/playbook.d.ts.map +1 -1
  6. package/dist/commands/playbook.js +2 -1
  7. package/dist/commands/playbook.js.map +1 -1
  8. package/dist/commands/server.d.ts.map +1 -1
  9. package/dist/commands/server.js +91 -8
  10. package/dist/commands/server.js.map +1 -1
  11. package/dist/commands/setup.d.ts.map +1 -1
  12. package/dist/commands/setup.js +5 -3
  13. package/dist/commands/setup.js.map +1 -1
  14. package/dist/core/Config.d.ts.map +1 -1
  15. package/dist/core/Config.js +2 -1
  16. package/dist/core/Config.js.map +1 -1
  17. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  18. package/dist/core/PostUpdateMigrator.js +4 -5
  19. package/dist/core/PostUpdateMigrator.js.map +1 -1
  20. package/dist/core/SessionManager.d.ts +38 -0
  21. package/dist/core/SessionManager.d.ts.map +1 -1
  22. package/dist/core/SessionManager.js +157 -23
  23. package/dist/core/SessionManager.js.map +1 -1
  24. package/dist/core/UpdateChecker.d.ts.map +1 -1
  25. package/dist/core/UpdateChecker.js +3 -1
  26. package/dist/core/UpdateChecker.js.map +1 -1
  27. package/dist/core/UpgradeGuideProcessor.d.ts.map +1 -1
  28. package/dist/core/UpgradeGuideProcessor.js +3 -1
  29. package/dist/core/UpgradeGuideProcessor.js.map +1 -1
  30. package/dist/core/types.d.ts +18 -0
  31. package/dist/core/types.d.ts.map +1 -1
  32. package/dist/core/types.js.map +1 -1
  33. package/dist/lifeline/ServerSupervisor.d.ts.map +1 -1
  34. package/dist/lifeline/ServerSupervisor.js +3 -1
  35. package/dist/lifeline/ServerSupervisor.js.map +1 -1
  36. package/dist/memory/SemanticMemory.d.ts +9 -0
  37. package/dist/memory/SemanticMemory.d.ts.map +1 -1
  38. package/dist/memory/SemanticMemory.js +131 -0
  39. package/dist/memory/SemanticMemory.js.map +1 -1
  40. package/dist/scheduler/JobRunHistory.d.ts +6 -0
  41. package/dist/scheduler/JobRunHistory.d.ts.map +1 -1
  42. package/dist/scheduler/JobRunHistory.js +11 -0
  43. package/dist/scheduler/JobRunHistory.js.map +1 -1
  44. package/dist/scheduler/JobScheduler.d.ts +23 -0
  45. package/dist/scheduler/JobScheduler.d.ts.map +1 -1
  46. package/dist/scheduler/JobScheduler.js +84 -0
  47. package/dist/scheduler/JobScheduler.js.map +1 -1
  48. package/dist/server/routes.d.ts.map +1 -1
  49. package/dist/server/routes.js +56 -0
  50. package/dist/server/routes.js.map +1 -1
  51. package/dist/threadline/ThreadlineBootstrap.d.ts.map +1 -1
  52. package/dist/threadline/ThreadlineBootstrap.js +3 -2
  53. package/dist/threadline/ThreadlineBootstrap.js.map +1 -1
  54. package/dist/threadline/relay/ConnectionManager.d.ts.map +1 -1
  55. package/dist/threadline/relay/ConnectionManager.js +34 -7
  56. package/dist/threadline/relay/ConnectionManager.js.map +1 -1
  57. package/package.json +1 -1
  58. package/scripts/pre-push-gate.js +26 -0
  59. package/src/data/builtin-manifest.json +64 -64
  60. package/upgrades/0.28.79.md +67 -0
  61. package/upgrades/side-effects/0.28.79.md +310 -0
  62. package/upgrades/side-effects/assembler-context-endpoint.md +67 -0
  63. package/upgrades/side-effects/post-update-migrator-path-fix.md +52 -0
  64. package/upgrades/side-effects/semantic-memory-corruption-recovery.md +98 -0
  65. package/upgrades/side-effects/url-pathname-path-encoding-fix.md +45 -0
@@ -52,6 +52,12 @@
52
52
  padding: 12px 20px;
53
53
  border-bottom: 1px solid var(--border);
54
54
  background: var(--bg-panel);
55
+ position: relative;
56
+ }
57
+
58
+ /* Hamburger toggle — visible only on mobile, sits in the header row */
59
+ .nav-toggle {
60
+ display: none;
55
61
  }
56
62
 
57
63
  .header-left {
@@ -2206,9 +2212,26 @@
2206
2212
  font-size: 14px;
2207
2213
  }
2208
2214
 
2215
+ /* Compact terminal action row — only essential keys inline,
2216
+ rest collapse into an overflow scroll strip */
2209
2217
  .terminal-actions {
2210
2218
  gap: 4px;
2211
- flex-wrap: wrap;
2219
+ flex-wrap: nowrap;
2220
+ overflow-x: auto;
2221
+ -webkit-overflow-scrolling: touch;
2222
+ scrollbar-width: none;
2223
+ }
2224
+ .terminal-actions::-webkit-scrollbar { display: none; }
2225
+
2226
+ .terminal-actions .action-btn {
2227
+ flex-shrink: 0;
2228
+ min-height: 36px; /* slightly smaller than 44 since these are arrow keys */
2229
+ }
2230
+
2231
+ /* The arrow-key cluster compresses tighter to leave room */
2232
+ .terminal-actions .action-btn.action-arrow {
2233
+ padding: 6px 10px;
2234
+ min-width: 36px;
2212
2235
  }
2213
2236
 
2214
2237
  .terminal-header {
@@ -2285,14 +2308,62 @@
2285
2308
  padding: 12px 14px;
2286
2309
  }
2287
2310
 
2288
- /* Tab bar compact */
2289
- .tab-bar {
2311
+ /* Hamburger toggle visible in header row on mobile */
2312
+ .nav-toggle {
2313
+ display: flex;
2314
+ align-items: center;
2315
+ gap: 8px;
2290
2316
  margin-left: 12px;
2317
+ padding: 8px 12px;
2318
+ min-height: 40px;
2319
+ background: var(--bg);
2320
+ border: 1px solid var(--border);
2321
+ border-radius: 6px;
2322
+ color: var(--text);
2323
+ font-size: 14px;
2324
+ font-weight: 500;
2325
+ cursor: pointer;
2326
+ }
2327
+ .nav-toggle:hover { background: var(--bg-hover); }
2328
+ .nav-toggle[aria-expanded="true"] { background: var(--bg-active); border-color: var(--accent); }
2329
+
2330
+ /* On mobile the tab-bar becomes a vertical dropdown panel,
2331
+ hidden by default and toggled via the .nav-open class on .app */
2332
+ .tab-bar {
2333
+ position: absolute;
2334
+ top: 100%; /* below the header row */
2335
+ left: 0;
2336
+ right: 0;
2337
+ flex-direction: column;
2338
+ margin-left: 0;
2339
+ padding: 8px;
2340
+ gap: 4px;
2341
+ background: var(--bg-panel);
2342
+ border-bottom: 1px solid var(--border);
2343
+ box-shadow: 0 4px 12px rgba(0,0,0,0.4);
2344
+ z-index: 100;
2345
+ overflow-x: visible;
2346
+ max-height: calc(100vh - 60px);
2347
+ overflow-y: auto;
2348
+ display: none;
2349
+ }
2350
+ .app.nav-open .tab-bar {
2351
+ display: flex;
2291
2352
  }
2292
2353
 
2293
2354
  .tab-bar .tab {
2294
- padding: 5px 12px;
2295
- font-size: 12px;
2355
+ width: 100%;
2356
+ text-align: left;
2357
+ border-radius: 6px;
2358
+ padding: 12px 14px;
2359
+ font-size: 15px;
2360
+ min-height: 44px;
2361
+ border-bottom: 1px solid var(--border);
2362
+ margin-bottom: 0;
2363
+ }
2364
+ .tab-bar .tab.active {
2365
+ background: var(--bg-active);
2366
+ border-color: var(--accent);
2296
2367
  }
2297
2368
 
2298
2369
  /* File viewer mobile */
@@ -2385,6 +2456,41 @@
2385
2456
  .jobs-detail-content {
2386
2457
  padding: 14px;
2387
2458
  }
2459
+
2460
+ /* Filter chips and sort select were below 32px — bump to comfortable tap size */
2461
+ .jobs-filter-chip {
2462
+ padding: 8px 12px;
2463
+ font-size: 12px;
2464
+ min-height: 36px;
2465
+ }
2466
+ .jobs-sort {
2467
+ font-size: 13px;
2468
+ padding: 6px 8px;
2469
+ min-height: 36px;
2470
+ }
2471
+
2472
+ /* Modal — explicit mobile rule instead of relying on max-width: 90vw fallback */
2473
+ .modal-dialog, .modal-content {
2474
+ width: calc(100vw - 24px);
2475
+ max-width: 100%;
2476
+ margin: 12px;
2477
+ }
2478
+ }
2479
+
2480
+ @media (max-width: 480px) {
2481
+ /* Even tighter — phone-only refinements */
2482
+ .header h1 { font-size: 14px; }
2483
+ .nav-toggle { padding: 6px 10px; font-size: 13px; }
2484
+
2485
+ /* Terminal action row — drop arrow keys to icon-only at very narrow widths */
2486
+ .terminal-actions .action-btn.action-arrow {
2487
+ padding: 6px 8px;
2488
+ min-width: 30px;
2489
+ }
2490
+
2491
+ /* Jobs summary cards stack tighter */
2492
+ .jobs-summary-card { padding: 4px 2px; min-width: 40px; }
2493
+ .jobs-summary-val { font-size: 14px; }
2388
2494
  }
2389
2495
  </style>
2390
2496
  </head>
@@ -2406,7 +2512,8 @@
2406
2512
  <div class="header-left">
2407
2513
  <img class="logo" src="/dashboard/logo.png" alt="Instar">
2408
2514
  <h1>Instar Dashboard</h1>
2409
- <nav class="tab-bar">
2515
+ <button class="nav-toggle" id="navToggle" aria-label="Open navigation menu" aria-expanded="false" onclick="toggleNavMenu()">&#9776; <span id="navToggleLabel">Sessions</span></button>
2516
+ <nav class="tab-bar" id="tabBar">
2410
2517
  <button class="tab active" data-tab="sessions" onclick="switchTab('sessions')">Sessions <span class="tab-count" id="tabSessionCount">0</span></button>
2411
2518
  <button class="tab" data-tab="files" onclick="switchTab('files')">Files</button>
2412
2519
  <button class="tab" data-tab="dropzone" onclick="switchTab('dropzone')">Send Content</button>
@@ -3470,7 +3577,7 @@
3470
3577
  brightCyan: '#99f6e4',
3471
3578
  brightWhite: '#eee',
3472
3579
  },
3473
- fontSize: window.innerWidth <= 768 ? 11 : 13,
3580
+ fontSize: window.innerWidth <= 480 ? 10 : window.innerWidth <= 768 ? 11 : 13,
3474
3581
  fontFamily: "'SF Mono', 'Fira Code', 'JetBrains Mono', 'Cascadia Code', monospace",
3475
3582
  cursorBlink: false,
3476
3583
  cursorStyle: 'underline',
@@ -3488,6 +3595,12 @@
3488
3595
  });
3489
3596
  resizeObserver.observe(container);
3490
3597
 
3598
+ // Refit on window resize / orientation change — phone rotation may not
3599
+ // trigger ResizeObserver if the parent grid keeps its size.
3600
+ window.addEventListener('resize', () => {
3601
+ try { fitAddon.fit(); } catch {}
3602
+ });
3603
+
3491
3604
  // Initial fit after a tick (container needs to be visible)
3492
3605
  requestAnimationFrame(() => {
3493
3606
  try { fitAddon.fit(); } catch {}
@@ -4052,6 +4165,51 @@
4052
4165
  },
4053
4166
  ];
4054
4167
 
4168
+ function toggleNavMenu() {
4169
+ const app = document.querySelector('.app');
4170
+ const toggle = document.getElementById('navToggle');
4171
+ const open = app.classList.toggle('nav-open');
4172
+ toggle.setAttribute('aria-expanded', open ? 'true' : 'false');
4173
+ }
4174
+
4175
+ function updateNavToggleLabel(tabName) {
4176
+ // Read the tab name from the actual button so we don't drift when
4177
+ // tabs get renamed in the registry. Strip the trailing count badge
4178
+ // ("Jobs 3" → "Jobs") by ignoring child element text.
4179
+ const labelEl = document.getElementById('navToggleLabel');
4180
+ if (!labelEl) return;
4181
+ const tabBtn = document.querySelector(`.tab-bar .tab[data-tab="${tabName}"]`);
4182
+ let text = tabName;
4183
+ if (tabBtn) {
4184
+ // Clone the button, strip count badges, then read trimmed text.
4185
+ const clone = tabBtn.cloneNode(true);
4186
+ clone.querySelectorAll('.tab-count').forEach(el => el.remove());
4187
+ text = clone.textContent.trim() || tabName;
4188
+ }
4189
+ labelEl.textContent = text;
4190
+ }
4191
+
4192
+ function closeNavMenu() {
4193
+ const app = document.querySelector('.app');
4194
+ if (!app || !app.classList.contains('nav-open')) return;
4195
+ app.classList.remove('nav-open');
4196
+ const toggle = document.getElementById('navToggle');
4197
+ if (toggle) toggle.setAttribute('aria-expanded', 'false');
4198
+ }
4199
+
4200
+ // Close the mobile menu on Escape or on tap outside the tab bar.
4201
+ document.addEventListener('keydown', (e) => {
4202
+ if (e.key === 'Escape') closeNavMenu();
4203
+ });
4204
+ document.addEventListener('click', (e) => {
4205
+ const app = document.querySelector('.app');
4206
+ if (!app || !app.classList.contains('nav-open')) return;
4207
+ const tabBar = document.querySelector('.tab-bar');
4208
+ const toggle = document.getElementById('navToggle');
4209
+ if (tabBar?.contains(e.target) || toggle?.contains(e.target)) return;
4210
+ closeNavMenu();
4211
+ });
4212
+
4055
4213
  function switchTab(tabName) {
4056
4214
  if (tabName === currentTab) return;
4057
4215
 
@@ -4066,6 +4224,11 @@
4066
4224
  btn.classList.toggle('active', btn.dataset.tab === tabName);
4067
4225
  });
4068
4226
 
4227
+ updateNavToggleLabel(tabName);
4228
+ document.querySelector('.app').classList.remove('nav-open');
4229
+ const navToggle = document.getElementById('navToggle');
4230
+ if (navToggle) navToggle.setAttribute('aria-expanded', 'false');
4231
+
4069
4232
  // Hide all panels
4070
4233
  for (const tab of TAB_REGISTRY) {
4071
4234
  for (const panelId of tab.panels) {
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAgDH,UAAU,WAAW;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yFAAyF;IACzF,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBrE;AAkzCD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAkqC1E;AA0mBD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAuBlF"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAmDH,UAAU,WAAW;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yFAAyF;IACzF,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBrE;AAkzCD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAkqC1E;AA0mBD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAuBlF"}
@@ -29,6 +29,8 @@
29
29
  import fs from 'node:fs';
30
30
  import os from 'node:os';
31
31
  import path from 'node:path';
32
+ import { fileURLToPath } from 'node:url';
33
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
32
34
  import pc from 'picocolors';
33
35
  import { randomUUID } from 'node:crypto';
34
36
  import { execFileSync, execSync } from 'node:child_process';
@@ -2534,7 +2536,7 @@ function installBuildSkill(skillsDir) {
2534
2536
  if (fs.existsSync(skillFile) || fs.existsSync(path.join(buildDir, 'skill.md')))
2535
2537
  return;
2536
2538
  // Try to copy from bundled .claude/skills/build/ first
2537
- const modDir = path.dirname(new URL(import.meta.url).pathname);
2539
+ const modDir = __dirname;
2538
2540
  const bundledSkill = path.join(modDir, '..', '..', '.claude', 'skills', 'build', 'SKILL.md');
2539
2541
  if (fs.existsSync(bundledSkill)) {
2540
2542
  fs.mkdirSync(buildDir, { recursive: true });
@@ -2573,7 +2575,7 @@ function installAutonomousSkill(skillsDir) {
2573
2575
  const hooksDir = path.join(autonomousDir, 'hooks');
2574
2576
  const scriptsDir = path.join(autonomousDir, 'scripts');
2575
2577
  // Copy from instar's bundled skill files if they exist
2576
- const modDir = path.dirname(new URL(import.meta.url).pathname);
2578
+ const modDir = __dirname;
2577
2579
  const bundledDir = path.join(path.dirname(path.dirname(modDir)), '.claude', 'skills', 'autonomous');
2578
2580
  if (fs.existsSync(bundledDir)) {
2579
2581
  // Copy from bundled source
@@ -3304,7 +3306,7 @@ function refreshScripts(projectDir, stateDir) {
3304
3306
  * PostUpdateMigrator.getTelegramReplyScript() uses the same loading pattern.
3305
3307
  */
3306
3308
  function loadRelayTemplate(filename, port) {
3307
- const modDir = path.dirname(new URL(import.meta.url).pathname);
3309
+ const modDir = __dirname;
3308
3310
  const candidates = [
3309
3311
  // dev: src/commands → ../templates/scripts
3310
3312
  path.resolve(modDir, '..', 'templates', 'scripts', filename),
@@ -4010,7 +4012,7 @@ function installSerendipityCapture(projectDir) {
4010
4012
  // Resolve template from package directory
4011
4013
  // In dev: src/commands/ → ../../src/templates/scripts/serendipity-capture.sh
4012
4014
  // In dist: dist/commands/ → ../templates/scripts/serendipity-capture.sh
4013
- const modDir = path.dirname(new URL(import.meta.url).pathname);
4015
+ const modDir = __dirname;
4014
4016
  const candidates = [
4015
4017
  path.resolve(modDir, '..', 'templates', 'scripts', 'serendipity-capture.sh'),
4016
4018
  path.resolve(modDir, '..', '..', 'src', 'templates', 'scripts', 'serendipity-capture.sh'),