instar 0.28.57 → 0.28.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -118,6 +118,7 @@ Instar solves the six dimensions of agent coherence:
118
118
  | **AutoUpdater** | Built-in update engine. Checks npm, auto-applies, self-restarts | [→](https://instar.sh/features/autoupdater/) |
119
119
  | **Build Pipeline** | `/build` skill with worktree isolation, 6-phase pipeline, quality gates, stop-hook enforcement | |
120
120
  | **Behavioral Hooks** | 9 automatic hooks: command guards, safety gates, identity grounding, topic context | [→](https://instar.sh/reference/hooks/) |
121
+ | **Initiative Tracker** | Persisted multi-phase long-running work tracker. Phases, blockers, links, digest alerts. HTTP API at `/initiatives/*` | |
121
122
  | **Default Jobs** | Health checks, reflection, evolution, relationship maintenance | [→](https://instar.sh/reference/default-jobs/) |
122
123
 
123
124
  > **Reference:** [CLI Commands](https://instar.sh/reference/cli/) · [API Endpoints](https://instar.sh/reference/api/) · [Configuration](https://instar.sh/reference/configuration/) · [File Structure](https://instar.sh/reference/file-structure/)
@@ -2415,6 +2415,7 @@
2415
2415
  <button class="tab" data-tab="systems" onclick="switchTab('systems')">Health</button>
2416
2416
  <button class="tab" data-tab="integrated-being" onclick="switchTab('integrated-being')">Integrated-Being</button>
2417
2417
  <button class="tab" data-tab="pr-pipeline" onclick="switchTab('pr-pipeline')">PR Pipeline</button>
2418
+ <button class="tab" data-tab="initiatives" onclick="switchTab('initiatives')">Initiatives <span class="tab-count" id="tabInitiativeCount">0</span></button>
2418
2419
  </nav>
2419
2420
  </div>
2420
2421
  <div class="vital-signs" id="vitalSigns">
@@ -2779,6 +2780,34 @@
2779
2780
  <div id="prPipelineList" style="display:flex;flex-direction:column;gap:12px"></div>
2780
2781
  </div>
2781
2782
 
2783
+ <!-- Initiatives Tab — multi-phase long-running work -->
2784
+ <div id="initiativesPanel" style="display:none;flex-direction:column;padding:20px;gap:16px;overflow-y:auto">
2785
+ <div style="display:flex;justify-content:space-between;align-items:center">
2786
+ <h2 style="margin:0">Initiatives</h2>
2787
+ <div style="display:flex;gap:8px;align-items:center">
2788
+ <select id="initiativesFilter" style="padding:6px 10px;background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:4px" onchange="loadInitiatives()">
2789
+ <option value="active">Active</option>
2790
+ <option value="">All</option>
2791
+ <option value="completed">Completed</option>
2792
+ <option value="archived">Archived</option>
2793
+ <option value="abandoned">Abandoned</option>
2794
+ </select>
2795
+ <button onclick="loadInitiatives()" style="padding:6px 12px">Refresh</button>
2796
+ </div>
2797
+ </div>
2798
+ <div style="font-size:12px;color:var(--text-dim);line-height:1.4">
2799
+ Multi-phase long-running work. Signals: <span style="color:#e27d3b">needs-user</span>,
2800
+ <span style="color:#d65f5f">next-check-due</span>,
2801
+ <span style="color:#4a9a4a">ready-to-advance</span>,
2802
+ <span style="color:#888">stale (&gt;7d)</span>.
2803
+ </div>
2804
+ <div id="initiativesDigest" style="display:none;padding:12px;border:1px solid var(--border);border-radius:6px;background:var(--bg-dim)"></div>
2805
+ <div id="initiativesEmpty" style="padding:40px;text-align:center;color:var(--text-dim);display:none">
2806
+ No initiatives to display. Create one via <code>POST /initiatives</code>.
2807
+ </div>
2808
+ <div id="initiativesList" style="display:flex;flex-direction:column;gap:12px"></div>
2809
+ </div>
2810
+
2782
2811
  <!-- Health Tab (was Systems) -->
2783
2812
  <div class="systems-container" id="systemsTab" style="display:none">
2784
2813
  <div class="systems-main">
@@ -3809,6 +3838,12 @@
3809
3838
  display: ['flex'],
3810
3839
  onActivate: () => { if (typeof loadPrPipeline === 'function') loadPrPipeline(); },
3811
3840
  },
3841
+ {
3842
+ id: 'initiatives',
3843
+ panels: ['initiativesPanel'],
3844
+ display: ['flex'],
3845
+ onActivate: () => { if (typeof loadInitiatives === 'function') loadInitiatives(); },
3846
+ },
3812
3847
  ];
3813
3848
 
3814
3849
  function switchTab(tabName) {
@@ -5699,6 +5734,176 @@
5699
5734
  }
5700
5735
  }
5701
5736
 
5737
+ // ── Initiatives Tab (INITIATIVE-TRACKER-SPEC v1) ─────────────
5738
+ //
5739
+ // Fetches /initiatives and /initiatives/digest on panel activation.
5740
+ // Read-only: no buttons here mutate the tracker. All content goes
5741
+ // through textContent; no innerHTML. Matches the PR Pipeline tab's
5742
+ // XSS-safe pattern.
5743
+ async function loadInitiatives() {
5744
+ const list = document.getElementById('initiativesList');
5745
+ const empty = document.getElementById('initiativesEmpty');
5746
+ const digestBox = document.getElementById('initiativesDigest');
5747
+ const filter = document.getElementById('initiativesFilter');
5748
+ const countBadge = document.getElementById('tabInitiativeCount');
5749
+
5750
+ while (list.firstChild) list.removeChild(list.firstChild);
5751
+ while (digestBox.firstChild) digestBox.removeChild(digestBox.firstChild);
5752
+ digestBox.style.display = 'none';
5753
+ empty.style.display = 'none';
5754
+
5755
+ let itemsRes = null;
5756
+ let digestRes = null;
5757
+ try {
5758
+ const statusQ = filter && filter.value ? `?status=${encodeURIComponent(filter.value)}` : '';
5759
+ const [a, b] = await Promise.all([
5760
+ apiFetch('/initiatives' + statusQ).catch(() => null),
5761
+ apiFetch('/initiatives/digest').catch(() => null),
5762
+ ]);
5763
+ itemsRes = a;
5764
+ digestRes = b;
5765
+ } catch { /* handled by null check below */ }
5766
+
5767
+ if (!itemsRes) {
5768
+ empty.style.display = 'block';
5769
+ empty.textContent = 'Initiative tracker unavailable.';
5770
+ if (countBadge) countBadge.textContent = '0';
5771
+ return;
5772
+ }
5773
+
5774
+ const items = Array.isArray(itemsRes.items) ? itemsRes.items : [];
5775
+ if (countBadge) countBadge.textContent = String(items.length);
5776
+
5777
+ // Digest summary (actionable signals)
5778
+ if (digestRes && Array.isArray(digestRes.items) && digestRes.items.length > 0) {
5779
+ const title = document.createElement('div');
5780
+ title.style.fontWeight = '600';
5781
+ title.style.marginBottom = '6px';
5782
+ title.textContent = `${digestRes.items.length} signal${digestRes.items.length === 1 ? '' : 's'}`;
5783
+ digestBox.appendChild(title);
5784
+ for (const d of digestRes.items) {
5785
+ const row = document.createElement('div');
5786
+ row.style.fontSize = '13px';
5787
+ row.style.padding = '3px 0';
5788
+ const colorMap = {
5789
+ 'needs-user': '#e27d3b',
5790
+ 'next-check-due': '#d65f5f',
5791
+ 'ready-to-advance': '#4a9a4a',
5792
+ 'stale': '#888',
5793
+ };
5794
+ const tag = document.createElement('span');
5795
+ tag.style.color = colorMap[d.reason] || 'var(--text-dim)';
5796
+ tag.style.marginRight = '6px';
5797
+ tag.textContent = `[${d.reason}]`;
5798
+ const label = document.createElement('span');
5799
+ label.textContent = `${d.title} — ${d.detail}`;
5800
+ row.appendChild(tag);
5801
+ row.appendChild(label);
5802
+ digestBox.appendChild(row);
5803
+ }
5804
+ digestBox.style.display = 'block';
5805
+ }
5806
+
5807
+ if (items.length === 0) {
5808
+ empty.style.display = 'block';
5809
+ empty.textContent = 'No initiatives to display. Create one via POST /initiatives.';
5810
+ return;
5811
+ }
5812
+
5813
+ for (const ini of items) {
5814
+ const card = document.createElement('div');
5815
+ card.style.background = 'var(--panel)';
5816
+ card.style.padding = '12px';
5817
+ card.style.borderRadius = '6px';
5818
+ card.style.border = '1px solid var(--border)';
5819
+
5820
+ const header = document.createElement('div');
5821
+ header.style.display = 'flex';
5822
+ header.style.justifyContent = 'space-between';
5823
+ header.style.alignItems = 'center';
5824
+ header.style.marginBottom = '6px';
5825
+
5826
+ const titleEl = document.createElement('div');
5827
+ titleEl.style.fontWeight = '600';
5828
+ titleEl.textContent = ini.title || ini.id || '(untitled)';
5829
+ header.appendChild(titleEl);
5830
+
5831
+ const status = document.createElement('span');
5832
+ status.style.fontSize = '11px';
5833
+ status.style.padding = '2px 8px';
5834
+ status.style.borderRadius = '999px';
5835
+ const statusColors = {
5836
+ active: 'var(--accent)',
5837
+ completed: '#4a9a4a',
5838
+ archived: 'var(--text-dim)',
5839
+ abandoned: '#d65f5f',
5840
+ };
5841
+ status.style.background = statusColors[ini.status] || 'var(--text-dim)';
5842
+ status.style.color = '#fff';
5843
+ status.textContent = ini.status || 'unknown';
5844
+ header.appendChild(status);
5845
+ card.appendChild(header);
5846
+
5847
+ if (ini.description) {
5848
+ const desc = document.createElement('div');
5849
+ desc.style.fontSize = '13px';
5850
+ desc.style.color = 'var(--text-dim)';
5851
+ desc.style.marginBottom = '8px';
5852
+ desc.textContent = ini.description;
5853
+ card.appendChild(desc);
5854
+ }
5855
+
5856
+ // Phase pills
5857
+ if (Array.isArray(ini.phases) && ini.phases.length > 0) {
5858
+ const phaseRow = document.createElement('div');
5859
+ phaseRow.style.display = 'flex';
5860
+ phaseRow.style.gap = '6px';
5861
+ phaseRow.style.flexWrap = 'wrap';
5862
+ phaseRow.style.marginBottom = '8px';
5863
+ const phaseColors = {
5864
+ pending: 'var(--text-dim)',
5865
+ 'in-progress': 'var(--accent)',
5866
+ done: '#4a9a4a',
5867
+ blocked: '#d65f5f',
5868
+ };
5869
+ for (const p of ini.phases) {
5870
+ const pill = document.createElement('span');
5871
+ pill.style.fontSize = '11px';
5872
+ pill.style.padding = '2px 8px';
5873
+ pill.style.borderRadius = '4px';
5874
+ pill.style.border = `1px solid ${phaseColors[p.status] || 'var(--border)'}`;
5875
+ pill.style.color = phaseColors[p.status] || 'var(--text)';
5876
+ pill.textContent = `${p.name} · ${p.status}`;
5877
+ phaseRow.appendChild(pill);
5878
+ }
5879
+ card.appendChild(phaseRow);
5880
+ }
5881
+
5882
+ // Meta row
5883
+ const meta = document.createElement('div');
5884
+ meta.style.fontSize = '11px';
5885
+ meta.style.color = 'var(--text-dim)';
5886
+ const lastTouched = ini.lastTouchedAt ? ini.lastTouchedAt.slice(0, 10) : '';
5887
+ const needsUser = ini.needsUser ? ' · needs you' : '';
5888
+ const blockerCount = Array.isArray(ini.blockers) && ini.blockers.length > 0
5889
+ ? ` · ${ini.blockers.length} blocker${ini.blockers.length === 1 ? '' : 's'}`
5890
+ : '';
5891
+ meta.textContent = `Last touched: ${lastTouched}${needsUser}${blockerCount}`;
5892
+ card.appendChild(meta);
5893
+
5894
+ if (ini.needsUser && ini.needsUserReason) {
5895
+ const reason = document.createElement('div');
5896
+ reason.style.fontSize = '12px';
5897
+ reason.style.marginTop = '4px';
5898
+ reason.style.color = '#e27d3b';
5899
+ reason.textContent = `→ ${ini.needsUserReason}`;
5900
+ card.appendChild(reason);
5901
+ }
5902
+
5903
+ list.appendChild(card);
5904
+ }
5905
+ }
5906
+
5702
5907
  // ── Integrated-Being Tab (v1) ────────────────────────────────
5703
5908
  let integratedBeingPollTimer = null;
5704
5909
 
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA2PH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA81CD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA86ItE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA2PH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA81CD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAi7ItE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
@@ -5355,7 +5355,9 @@ export async function startServer(options) {
5355
5355
  console.log(pc.green(` Parallel-dev isolation: ${parallelDevConfig.phase} (WorktreeManager wired)`));
5356
5356
  }
5357
5357
  }
5358
- const server = new AgentServer({ config, sessionManager, state, scheduler, telegram, relationships, feedback, feedbackAnomalyDetector, dispatches, updateChecker, autoUpdater, autoDispatcher, quotaTracker, quotaManager, publisher, viewer, tunnel, evolution, watchdog, topicMemory, triageNurse, projectMapper, coherenceGate: scopeVerifier, contextHierarchy, canonicalState, operationGate, sentinel, adaptiveTrust, memoryMonitor, orphanReaper, coherenceMonitor, commitmentTracker, semanticMemory, activitySentinel, messageRouter, summarySentinel, spawnManager, systemReviewer, capabilityMapper, selfKnowledgeTree, coverageAuditor, topicResumeMap: _topicResumeMap ?? undefined, autonomyManager, trustElevationTracker, autonomousEvolution, coordinator: coordinator.enabled ? coordinator : undefined, localSigningKeyPem, whatsapp: whatsappAdapter, slack: slackAdapter, imessage: imessageAdapter, whatsappBusinessBackend, messageBridge, hookEventReceiver, worktreeMonitor, subagentTracker, instructionsVerifier, handshakeManager: threadlineHandshake, threadlineRouter, threadlineRelayClient, threadlineReplyWaiters, listenerManager: listenerManager ?? undefined, responseReviewGate, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos });
5358
+ const { InitiativeTracker } = await import('../core/InitiativeTracker.js');
5359
+ const initiativeTracker = new InitiativeTracker(config.stateDir);
5360
+ const server = new AgentServer({ config, sessionManager, state, scheduler, telegram, relationships, feedback, feedbackAnomalyDetector, dispatches, updateChecker, autoUpdater, autoDispatcher, quotaTracker, quotaManager, publisher, viewer, tunnel, evolution, watchdog, topicMemory, triageNurse, projectMapper, coherenceGate: scopeVerifier, contextHierarchy, canonicalState, operationGate, sentinel, adaptiveTrust, memoryMonitor, orphanReaper, coherenceMonitor, commitmentTracker, semanticMemory, activitySentinel, messageRouter, summarySentinel, spawnManager, systemReviewer, capabilityMapper, selfKnowledgeTree, coverageAuditor, topicResumeMap: _topicResumeMap ?? undefined, autonomyManager, trustElevationTracker, autonomousEvolution, coordinator: coordinator.enabled ? coordinator : undefined, localSigningKeyPem, whatsapp: whatsappAdapter, slack: slackAdapter, imessage: imessageAdapter, whatsappBusinessBackend, messageBridge, hookEventReceiver, worktreeMonitor, subagentTracker, instructionsVerifier, handshakeManager: threadlineHandshake, threadlineRouter, threadlineRelayClient, threadlineReplyWaiters, listenerManager: listenerManager ?? undefined, responseReviewGate, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos, initiativeTracker });
5359
5361
  await server.start();
5360
5362
  // Connect DegradationReporter downstream systems now that everything is initialized.
5361
5363
  // Any degradation events queued during startup will drain to feedback + telegram.