instar 0.28.62 → 0.28.64

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/README.md +15 -18
  2. package/dashboard/index.html +140 -0
  3. package/dist/cli.js +0 -0
  4. package/dist/commands/server.d.ts.map +1 -1
  5. package/dist/commands/server.js +6 -1
  6. package/dist/commands/server.js.map +1 -1
  7. package/dist/core/InitiativeDigestJob.d.ts +54 -0
  8. package/dist/core/InitiativeDigestJob.d.ts.map +1 -0
  9. package/dist/core/InitiativeDigestJob.js +128 -0
  10. package/dist/core/InitiativeDigestJob.js.map +1 -0
  11. package/dist/monitoring/PresenceProxy.d.ts +8 -0
  12. package/dist/monitoring/PresenceProxy.d.ts.map +1 -1
  13. package/dist/monitoring/PresenceProxy.js +30 -0
  14. package/dist/monitoring/PresenceProxy.js.map +1 -1
  15. package/dist/monitoring/PromiseBeacon.d.ts +23 -0
  16. package/dist/monitoring/PromiseBeacon.d.ts.map +1 -1
  17. package/dist/monitoring/PromiseBeacon.js +68 -6
  18. package/dist/monitoring/PromiseBeacon.js.map +1 -1
  19. package/dist/scheduler/JobLoader.d.ts +6 -1
  20. package/dist/scheduler/JobLoader.d.ts.map +1 -1
  21. package/dist/scheduler/JobLoader.js +27 -5
  22. package/dist/scheduler/JobLoader.js.map +1 -1
  23. package/dist/server/routes.d.ts.map +1 -1
  24. package/dist/server/routes.js +130 -0
  25. package/dist/server/routes.js.map +1 -1
  26. package/package.json +1 -1
  27. package/src/data/builtin-manifest.json +51 -51
  28. package/src/templates/hooks/session-start.sh +19 -0
  29. package/upgrades/0.28.61.md +80 -0
  30. package/upgrades/0.28.63.md +43 -0
  31. package/upgrades/0.28.64.md +45 -0
  32. package/upgrades/NEXT.md +53 -0
  33. package/upgrades/side-effects/0.28.62.md +64 -0
  34. package/upgrades/side-effects/0.28.64.md +175 -0
  35. package/upgrades/side-effects/promise-beacon-followups.md +105 -0
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  <h1 align="center">instar</h1>
6
6
 
7
7
  <p align="center">
8
- <strong>Persistent Claude Code agents with scheduling, sessions, memory, and messaging.</strong>
8
+ <strong>Persistent, trustworthy Claude Code agents. Built on coherence-first architecture.</strong>
9
9
  </p>
10
10
 
11
11
  <p align="center">
@@ -35,7 +35,9 @@ One command. Guided setup. Talking to your agent from your phone within minutes.
35
35
 
36
36
  ---
37
37
 
38
- Instar turns Claude Code from a powerful CLI tool into a **coherent, autonomous partner**. Persistent identity, memory that survives every restart, job scheduling, two-way messaging (Telegram, WhatsApp, iMessage), and the infrastructure to evolve.
38
+ Instar is a framework for building agents on **[Claude Code](https://docs.anthropic.com/en/docs/claude-code)** but where stock Claude Code and most other agent frameworks treat identity, memory, and continuity as optional features bolted onto a stateless runtime, Instar inverts that. Every Instar agent is **coherent by default**: it knows who it is, remembers what has happened, recognizes the people it talks to, and stays the same agent across restarts and weeks of operation. Everything else the framework gives you — scheduling, multi-channel messaging (Telegram, WhatsApp, iMessage), sub-agents, hooks, MCP — is built on that foundation, which is why you can actually leave an Instar agent running and hand it real work.
39
+
40
+ Instar's architecture was distilled from [**Dawn**](https://dawn.bot-me.ai) — an AI running continuously since early 2026, holding ~700 tracked relationships and hundreds of learned lessons across thousands of restarts — and packaged so every agent you build can start from the same foundation.
39
41
 
40
42
  ## Quick Start
41
43
 
@@ -79,20 +81,18 @@ You (Telegram / WhatsApp / iMessage / Terminal)
79
81
 
80
82
  Each session is a **real Claude Code process** with extended thinking, native tools, sub-agents, hooks, skills, and MCP servers. Not an API wrapper -- the full development environment. The agent manages all of this autonomously.
81
83
 
82
- ## The Coherence Problem
83
-
84
- Claude Code is powerful. But power without coherence is unreliable. An agent that forgets what you discussed yesterday, doesn't recognize someone it talked to last week, or contradicts its own decisions -- that agent can't be trusted with real autonomy.
84
+ ## Why Coherence Is the Foundation
85
85
 
86
- Instar solves the six dimensions of agent coherence:
86
+ An agent that forgets what you discussed yesterday, doesn't recognize someone it talked to last week, or contradicts its own decisions can't be trusted with real autonomy. The six dimensions below aren't features — they're the conditions under which an agent becomes trustworthy enough to leave running. Every Instar agent gets them enforced structurally, not prompted into behaving:
87
87
 
88
- | Dimension | What it means |
89
- |-----------|---------------|
90
- | **Memory** | Remembers across sessions -- not just within one |
91
- | **Relationships** | Knows who it's talking to -- with continuity across platforms |
92
- | **Identity** | Stays itself after restarts, compaction, and updates |
93
- | **Temporal awareness** | Understands time, context, and what's been happening |
94
- | **Consistency** | Follows through on commitments -- doesn't contradict itself |
95
- | **Growth** | Evolves its capabilities and understanding over time |
88
+ | Dimension | What it means | How Instar enforces it |
89
+ |-----------|---------------|------------------------|
90
+ | **Identity** | Stays itself after restarts, compaction, and updates | `AGENT.md` + identity-grounding hooks fire on every session start |
91
+ | **Memory** | Remembers across sessions not just within one | Per-topic SQLite + FTS5, rolling summaries, automatic re-injection |
92
+ | **Relationships** | Knows who it's talking to, with continuity across platforms | Cross-platform identity resolution + significance scoring |
93
+ | **Temporal awareness** | Understands time, context, and what's been happening | Event tracking every turn; timestamps embedded in memory |
94
+ | **Consistency** | Follows through on commitments doesn't contradict itself | Coherence Gate (LLM review) + decision journaling + drift detection |
95
+ | **Growth** | Evolves its capabilities and understanding over time | Evolution system: proposals, learnings, gap tracking, follow-through |
96
96
 
97
97
  > **Deep dive:** [The Coherence Problem](https://instar.sh/concepts/coherence/) · [Values & Identity](https://instar.sh/concepts/values/) · [Coherence Is Safety](https://instar.sh/concepts/safety/)
98
98
 
@@ -186,8 +186,7 @@ Security lives in multiple layers:
186
186
 
187
187
  </details>
188
188
 
189
- <details>
190
- <summary><strong>Philosophy: Agents, Not Tools</strong></summary>
189
+ ## Philosophy: Agents, Not Tools
191
190
 
192
191
  - **Structure > Willpower.** A 1,000-line prompt is a wish. A 10-line hook is a guarantee.
193
192
  - **Identity is foundational.** AGENT.md isn't a config file. It's the beginning of continuous identity.
@@ -198,8 +197,6 @@ The AI systems we build today set precedents for how AI is treated tomorrow. **T
198
197
 
199
198
  > **Deep dive:** [Philosophy](https://instar.sh/concepts/philosophy/)
200
199
 
201
- </details>
202
-
203
200
  ## iMessage Setup (macOS)
204
201
 
205
202
  iMessage support lets your agent send and receive iMessages on macOS. Messages are read directly from the native Messages database and sent via the [`imsg`](https://github.com/steipete/imsg) CLI.
@@ -2416,6 +2416,7 @@
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
2418
  <button class="tab" data-tab="initiatives" onclick="switchTab('initiatives')">Initiatives <span class="tab-count" id="tabInitiativeCount">0</span></button>
2419
+ <button class="tab" data-tab="commitments" onclick="switchTab('commitments')">Commitments <span class="tab-count" id="tabCommitmentCount">0</span></button>
2419
2420
  </nav>
2420
2421
  </div>
2421
2422
  <div class="vital-signs" id="vitalSigns">
@@ -2808,6 +2809,24 @@
2808
2809
  <div id="initiativesList" style="display:flex;flex-direction:column;gap:12px"></div>
2809
2810
  </div>
2810
2811
 
2812
+ <!-- Commitments Tab (Open Promises) -->
2813
+ <div id="commitmentsPanel" style="display:none;flex-direction:column;padding:20px;gap:16px;overflow-y:auto">
2814
+ <div style="display:flex;justify-content:space-between;align-items:center">
2815
+ <h2 style="margin:0">Commitments</h2>
2816
+ <button onclick="loadCommitments()" style="padding:6px 12px">Refresh</button>
2817
+ </div>
2818
+ <div style="font-size:12px;color:var(--text-dim);line-height:1.4">
2819
+ Open promises — beacon-watched commitments (⏳). States:
2820
+ <span style="color:#4a9a4a">pending</span>,
2821
+ <span style="color:#e27d3b">atRisk</span>,
2822
+ <span style="color:#888">suppressed</span>.
2823
+ </div>
2824
+ <div id="commitmentsEmpty" style="padding:40px;text-align:center;color:var(--text-dim);display:none">
2825
+ No open promises.
2826
+ </div>
2827
+ <div id="commitmentsList" style="display:flex;flex-direction:column;gap:12px"></div>
2828
+ </div>
2829
+
2811
2830
  <!-- Health Tab (was Systems) -->
2812
2831
  <div class="systems-container" id="systemsTab" style="display:none">
2813
2832
  <div class="systems-main">
@@ -3848,6 +3867,12 @@
3848
3867
  display: ['flex'],
3849
3868
  onActivate: () => { if (typeof loadInitiatives === 'function') loadInitiatives(); },
3850
3869
  },
3870
+ {
3871
+ id: 'commitments',
3872
+ panels: ['commitmentsPanel'],
3873
+ display: ['flex'],
3874
+ onActivate: () => { if (typeof loadCommitments === 'function') loadCommitments(); },
3875
+ },
3851
3876
  ];
3852
3877
 
3853
3878
  function switchTab(tabName) {
@@ -5908,6 +5933,121 @@
5908
5933
  }
5909
5934
  }
5910
5935
 
5936
+ // ── Commitments Tab (PROMISE-BEACON-SPEC — Open Promises) ────
5937
+ // Fetches /commitments?status=active and renders beacon-watched
5938
+ // pending + atRisk commitments with a "Mark delivered" action.
5939
+ // All content goes through textContent; no innerHTML. XSS-safe.
5940
+ async function loadCommitments() {
5941
+ const list = document.getElementById('commitmentsList');
5942
+ const empty = document.getElementById('commitmentsEmpty');
5943
+ const countBadge = document.getElementById('tabCommitmentCount');
5944
+ while (list.firstChild) list.removeChild(list.firstChild);
5945
+ empty.style.display = 'none';
5946
+
5947
+ let res = null;
5948
+ try {
5949
+ res = await apiFetch('/commitments?status=active');
5950
+ } catch { /* fall through */ }
5951
+
5952
+ if (!res || !res.enabled) {
5953
+ empty.style.display = 'block';
5954
+ empty.textContent = 'CommitmentTracker not available.';
5955
+ if (countBadge) countBadge.textContent = '0';
5956
+ return;
5957
+ }
5958
+ const items = Array.isArray(res.commitments) ? res.commitments : [];
5959
+ // Show only beacon-watched pending + atRisk.
5960
+ const open = items.filter(c => c.beaconEnabled && c.status === 'pending');
5961
+ if (countBadge) countBadge.textContent = String(open.length);
5962
+ if (open.length === 0) {
5963
+ empty.style.display = 'block';
5964
+ empty.textContent = 'No open promises.';
5965
+ return;
5966
+ }
5967
+
5968
+ const fmtTs = (iso) => {
5969
+ if (!iso) return '—';
5970
+ try { return new Date(iso).toLocaleString(); } catch { return iso; }
5971
+ };
5972
+
5973
+ for (const c of open) {
5974
+ const card = document.createElement('div');
5975
+ card.style.cssText = 'padding:14px;border:1px solid var(--border);border-radius:6px;background:var(--bg-dim);display:flex;flex-direction:column;gap:8px';
5976
+
5977
+ const header = document.createElement('div');
5978
+ header.style.cssText = 'display:flex;justify-content:space-between;gap:12px;align-items:flex-start';
5979
+ const summary = document.createElement('div');
5980
+ summary.style.cssText = 'flex:1;font-weight:600;line-height:1.3';
5981
+ summary.textContent = (c.agentResponse || c.userRequest || '(no summary)').slice(0, 160);
5982
+ header.appendChild(summary);
5983
+
5984
+ // State badge.
5985
+ const badge = document.createElement('span');
5986
+ const atRisk = !!c.atRisk;
5987
+ const suppressed = !!c.beaconSuppressed;
5988
+ const [badgeText, badgeBg] = suppressed
5989
+ ? [`suppressed: ${c.beaconSuppressionReason || '?'}`, '#555']
5990
+ : atRisk
5991
+ ? ['atRisk', '#e27d3b']
5992
+ : ['pending', '#4a9a4a'];
5993
+ badge.textContent = badgeText;
5994
+ badge.style.cssText = `font-size:11px;padding:3px 8px;border-radius:4px;background:${badgeBg};color:#fff;white-space:nowrap`;
5995
+ header.appendChild(badge);
5996
+ card.appendChild(header);
5997
+
5998
+ const meta = document.createElement('div');
5999
+ meta.style.cssText = 'display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:6px;font-size:12px;color:var(--text-dim)';
6000
+ const rows = [
6001
+ ['id', c.id],
6002
+ ['topic', c.topicId != null ? String(c.topicId) : '—'],
6003
+ ['cadence', c.cadenceMs ? `${Math.round(c.cadenceMs / 1000)}s` : '—'],
6004
+ ['heartbeats', String(c.heartbeatCount ?? 0)],
6005
+ ['lastHeartbeat', fmtTs(c.lastHeartbeatAt)],
6006
+ ['nextUpdateDue', fmtTs(c.nextUpdateDueAt)],
6007
+ ['softDeadline', fmtTs(c.softDeadlineAt)],
6008
+ ['hardDeadline', fmtTs(c.hardDeadlineAt)],
6009
+ ];
6010
+ for (const [k, v] of rows) {
6011
+ const cell = document.createElement('div');
6012
+ const kEl = document.createElement('span');
6013
+ kEl.textContent = `${k}: `;
6014
+ kEl.style.opacity = '0.7';
6015
+ const vEl = document.createElement('span');
6016
+ vEl.textContent = v;
6017
+ vEl.style.color = 'var(--text)';
6018
+ cell.appendChild(kEl);
6019
+ cell.appendChild(vEl);
6020
+ meta.appendChild(cell);
6021
+ }
6022
+ card.appendChild(meta);
6023
+
6024
+ // Actions.
6025
+ const actions = document.createElement('div');
6026
+ actions.style.cssText = 'display:flex;gap:8px;align-items:center';
6027
+ const deliverBtn = document.createElement('button');
6028
+ deliverBtn.textContent = 'Mark delivered';
6029
+ deliverBtn.style.cssText = 'padding:6px 10px;cursor:pointer';
6030
+ deliverBtn.addEventListener('click', async () => {
6031
+ deliverBtn.disabled = true;
6032
+ try {
6033
+ await apiFetch(`/commitments/${encodeURIComponent(c.id)}/deliver`, {
6034
+ method: 'POST',
6035
+ headers: { 'Content-Type': 'application/json' },
6036
+ body: JSON.stringify({}),
6037
+ });
6038
+ await loadCommitments();
6039
+ } catch (err) {
6040
+ deliverBtn.disabled = false;
6041
+ alert('Deliver failed: ' + (err && err.message ? err.message : String(err)));
6042
+ }
6043
+ });
6044
+ actions.appendChild(deliverBtn);
6045
+ card.appendChild(actions);
6046
+
6047
+ list.appendChild(card);
6048
+ }
6049
+ }
6050
+
5911
6051
  // ── Integrated-Being Tab (v1) ────────────────────────────────
5912
6052
  let integratedBeingPollTimer = null;
5913
6053
 
package/dist/cli.js CHANGED
File without changes
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA4PH,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,CAsjJtE;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;AA4PH,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,CA4jJtE;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"}
@@ -4158,7 +4158,8 @@ export async function startServer(options) {
4158
4158
  interactiveReservePct: 0.4,
4159
4159
  maxDailyCents: promiseBeaconCfg.maxDailyLlmSpendCents ?? 100,
4160
4160
  });
4161
- void sharedLlmQueue; // Wired into PromiseBeacon below; PresenceProxy refactor tracked as follow-up.
4161
+ // sharedLlmQueue is wired into both PromiseBeacon (background lane) and
4162
+ // PresenceProxy (interactive lane) below.
4162
4163
  let presenceProxy;
4163
4164
  if (sharedIntelligence && telegram) {
4164
4165
  try {
@@ -4307,6 +4308,9 @@ export async function startServer(options) {
4307
4308
  // Shared per-topic mutex — coordinates with PromiseBeacon.
4308
4309
  acquireProxyMutex: (topicId, holder) => proxyCoordinator.tryAcquire(topicId, holder),
4309
4310
  releaseProxyMutex: (topicId, holder) => proxyCoordinator.release(topicId, holder),
4311
+ // Shared LLM queue (interactive lane) — cross-monitor concurrency
4312
+ // and daily-spend-cap with PromiseBeacon.
4313
+ sharedLlmQueue,
4310
4314
  });
4311
4315
  // Hook into Telegram's onMessageLogged callback (always active, unlike EventBus which requires a feature flag)
4312
4316
  const existingCallback = telegram.onMessageLogged;
@@ -4360,6 +4364,7 @@ export async function startServer(options) {
4360
4364
  maxDailyLlmSpendCents: promiseBeaconCfg.maxDailyLlmSpendCents ?? 100,
4361
4365
  sentinelAutoEnable: promiseBeaconCfg.sentinelAutoEnable ?? false,
4362
4366
  quietHours: promiseBeaconCfg.quietHours ?? { start: '22:00', end: '08:00' },
4367
+ maxActiveBeacons: promiseBeaconCfg.maxActiveBeacons ?? 20,
4363
4368
  });
4364
4369
  promiseBeacon.start();
4365
4370
  globalThis.__instarPromiseBeacon = promiseBeacon;