instar 1.3.524 → 1.3.526

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 (64) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +77 -5
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  5. package/dist/config/ConfigDefaults.js +23 -0
  6. package/dist/config/ConfigDefaults.js.map +1 -1
  7. package/dist/core/ConflictStore.d.ts +150 -0
  8. package/dist/core/ConflictStore.d.ts.map +1 -0
  9. package/dist/core/ConflictStore.js +247 -0
  10. package/dist/core/ConflictStore.js.map +1 -0
  11. package/dist/core/PostUpdateMigrator.d.ts +1 -0
  12. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  13. package/dist/core/PostUpdateMigrator.js +116 -0
  14. package/dist/core/PostUpdateMigrator.js.map +1 -1
  15. package/dist/core/ReplicatedStoreReader.d.ts +83 -0
  16. package/dist/core/ReplicatedStoreReader.d.ts.map +1 -0
  17. package/dist/core/ReplicatedStoreReader.js +100 -0
  18. package/dist/core/ReplicatedStoreReader.js.map +1 -0
  19. package/dist/core/ReplicationBudget.d.ts +183 -0
  20. package/dist/core/ReplicationBudget.d.ts.map +1 -0
  21. package/dist/core/ReplicationBudget.js +253 -0
  22. package/dist/core/ReplicationBudget.js.map +1 -0
  23. package/dist/core/RollbackUnmerge.d.ts +134 -0
  24. package/dist/core/RollbackUnmerge.d.ts.map +1 -0
  25. package/dist/core/RollbackUnmerge.js +286 -0
  26. package/dist/core/RollbackUnmerge.js.map +1 -0
  27. package/dist/core/UnionReader.d.ts +161 -0
  28. package/dist/core/UnionReader.d.ts.map +1 -0
  29. package/dist/core/UnionReader.js +0 -0
  30. package/dist/core/UnionReader.js.map +1 -0
  31. package/dist/monitoring/ActiveWorkSilenceSentinel.d.ts +56 -2
  32. package/dist/monitoring/ActiveWorkSilenceSentinel.d.ts.map +1 -1
  33. package/dist/monitoring/ActiveWorkSilenceSentinel.js +174 -10
  34. package/dist/monitoring/ActiveWorkSilenceSentinel.js.map +1 -1
  35. package/dist/monitoring/PromiseBeacon.d.ts +48 -0
  36. package/dist/monitoring/PromiseBeacon.d.ts.map +1 -1
  37. package/dist/monitoring/PromiseBeacon.js +186 -41
  38. package/dist/monitoring/PromiseBeacon.js.map +1 -1
  39. package/dist/monitoring/SubagentTracker.d.ts +9 -0
  40. package/dist/monitoring/SubagentTracker.d.ts.map +1 -1
  41. package/dist/monitoring/SubagentTracker.js +11 -0
  42. package/dist/monitoring/SubagentTracker.js.map +1 -1
  43. package/dist/monitoring/sentinelWiring.d.ts +20 -1
  44. package/dist/monitoring/sentinelWiring.d.ts.map +1 -1
  45. package/dist/monitoring/sentinelWiring.js +26 -0
  46. package/dist/monitoring/sentinelWiring.js.map +1 -1
  47. package/dist/scaffold/templates.d.ts.map +1 -1
  48. package/dist/scaffold/templates.js +13 -0
  49. package/dist/scaffold/templates.js.map +1 -1
  50. package/dist/server/AgentServer.d.ts +7 -0
  51. package/dist/server/AgentServer.d.ts.map +1 -1
  52. package/dist/server/AgentServer.js +3 -0
  53. package/dist/server/AgentServer.js.map +1 -1
  54. package/dist/server/routes.d.ts +10 -0
  55. package/dist/server/routes.d.ts.map +1 -1
  56. package/dist/server/routes.js +67 -0
  57. package/dist/server/routes.js.map +1 -1
  58. package/package.json +1 -1
  59. package/src/data/builtin-manifest.json +64 -64
  60. package/src/scaffold/templates.ts +13 -0
  61. package/upgrades/1.3.525.md +32 -0
  62. package/upgrades/1.3.526.md +83 -0
  63. package/upgrades/side-effects/hlc-step4-5-union-rollback-bounds.md +148 -0
  64. package/upgrades/side-effects/honest-progress-messaging.md +150 -0
@@ -261,6 +261,7 @@ export class PostUpdateMigrator {
261
261
  this.migrateCommitmentOwnerBackfill(result);
262
262
  this.migrateMultiMachinePostureReviewDimension(result);
263
263
  this.migrateConformanceGateAutoInvoke(result);
264
+ this.migrateHonestProgressMessagingDefaults(result);
264
265
  return result;
265
266
  }
266
267
  // ── Standards-Conformance Gate auto-invocation (2026-06-12, topic 13481) ──
@@ -530,6 +531,81 @@ export class PostUpdateMigrator {
530
531
  result.skipped.push('cartographer-dev-gate: no default-shaped false to strip (marker set)');
531
532
  }
532
533
  }
534
+ // ── HONEST-PROGRESS-MESSAGING D (Config surface + migration parity) ──
535
+ //
536
+ // The honest-messaging behavior reaches every agent via the monitors' code
537
+ // defaults already; this migration SURFACES the operator-tunable / rollback
538
+ // keys into a deployed agent's config.json so they are visible and settable,
539
+ // and logs which keys it backfilled (audit). Existence-checked + idempotent: a
540
+ // key the operator has explicitly set — including the rollback
541
+ // `suppressUnchangedHeartbeats: false` — is NEVER overwritten. Writes to the
542
+ // paths the runtime ACTUALLY reads: `monitoring.activeWorkSilenceSentinel.*`
543
+ // and TOP-LEVEL `promiseBeacon.*` (server.ts reads `config.promiseBeacon`, not
544
+ // `monitoring.promiseBeacon` — the spec prose's path was corrected against the
545
+ // real read site during the build).
546
+ migrateHonestProgressMessagingDefaults(result) {
547
+ const configPath = path.join(this.config.stateDir, 'config.json');
548
+ if (!fs.existsSync(configPath)) {
549
+ result.skipped.push('honest-progress-messaging-defaults: config.json not found');
550
+ return;
551
+ }
552
+ let config;
553
+ try {
554
+ config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
555
+ }
556
+ catch (err) {
557
+ result.errors.push(`honest-progress-messaging-defaults: config.json read failed: ${err instanceof Error ? err.message : String(err)}`);
558
+ return;
559
+ }
560
+ const migrations = (config._instar_migrations ?? []);
561
+ const marker = 'honest-progress-messaging-defaults';
562
+ if (migrations.some(m => m.startsWith(marker))) {
563
+ result.skipped.push('honest-progress-messaging-defaults: already migrated');
564
+ return;
565
+ }
566
+ // Ensure a nested object exists without clobbering operator settings.
567
+ const ensureObj = (parent, key) => {
568
+ const cur = parent[key];
569
+ if (cur && typeof cur === 'object' && !Array.isArray(cur))
570
+ return cur;
571
+ const fresh = {};
572
+ parent[key] = fresh;
573
+ return fresh;
574
+ };
575
+ // Set a key ONLY if absent (existence-checked) — operator overrides survive.
576
+ const backfilled = [];
577
+ const setIfAbsent = (obj, key, value, label) => {
578
+ if (!(key in obj)) {
579
+ obj[key] = value;
580
+ backfilled.push(label);
581
+ }
582
+ };
583
+ const monitoring = ensureObj(config, 'monitoring');
584
+ const silence = ensureObj(monitoring, 'activeWorkSilenceSentinel');
585
+ setIfAbsent(silence, 'silenceThresholdMs', 1_800_000, 'monitoring.activeWorkSilenceSentinel.silenceThresholdMs');
586
+ setIfAbsent(silence, 'activeWorkMaxFrozenIndicatorMs', 5_400_000, 'monitoring.activeWorkSilenceSentinel.activeWorkMaxFrozenIndicatorMs');
587
+ const beacon = ensureObj(config, 'promiseBeacon');
588
+ setIfAbsent(beacon, 'suppressUnchangedHeartbeats', true, 'promiseBeacon.suppressUnchangedHeartbeats');
589
+ setIfAbsent(beacon, 'beaconLivenessIntervalMs', 3_600_000, 'promiseBeacon.beaconLivenessIntervalMs');
590
+ setIfAbsent(beacon, 'turnFinishedCloseoutChecks', 3, 'promiseBeacon.turnFinishedCloseoutChecks');
591
+ // Record the marker even when nothing was backfilled, so it runs exactly once.
592
+ const now = new Date().toISOString();
593
+ migrations.push(`${marker}-${now}`);
594
+ config._instar_migrations = migrations;
595
+ try {
596
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
597
+ }
598
+ catch (err) {
599
+ result.errors.push(`honest-progress-messaging-defaults: config.json write failed: ${err instanceof Error ? err.message : String(err)}`);
600
+ return;
601
+ }
602
+ if (backfilled.length > 0) {
603
+ result.upgraded.push(`honest-progress-messaging-defaults: backfilled ${backfilled.join(', ')} (existence-checked — operator overrides preserved)`);
604
+ }
605
+ else {
606
+ result.skipped.push('honest-progress-messaging-defaults: all keys already present (marker set)');
607
+ }
608
+ }
533
609
  /**
534
610
  * Seed the interactive first-launch onboarding flags into every EXISTING
535
611
  * claude-code subscription-pool config home (2026-06-09 incident, topic
@@ -4244,6 +4320,26 @@ A secret you give me on one machine — a Telegram token, an API key, a GitHub P
4244
4320
  patched = true;
4245
4321
  result.upgraded.push('CLAUDE.md: added secret-sync push-opt-in safety line');
4246
4322
  }
4323
+ // One Memory (replicated stores) — multi-machine-replicated-store-foundation
4324
+ // §7. Deployed agents don't know certain stores now replicate with a no-clobber
4325
+ // union + operator-resolved conflicts + origin-tagged rollback, nor the three
4326
+ // /state/* routes. Append the section so an agent can answer "why do I have two
4327
+ // versions of preference X?" / "roll back machine Y's data". Idempotent via the
4328
+ // unique `/state/resolve-conflict` marker.
4329
+ if (!content.includes('/state/resolve-conflict') && !content.includes('One Memory (replicated stores)')) {
4330
+ const oneMemory = `
4331
+ ### One Memory (replicated stores)
4332
+
4333
+ When enabled, certain stores (preferences, relationships) replicate across my machines so I have ONE memory, not one-per-machine. A read returns the UNION of every machine's copy, merged by a no-clobber rule: a normal sequential edit history resolves to the latest writer; but two machines that edited the SAME thing DURING A PARTITION (a genuine concurrent divergence) are NEVER silently overwritten. For a high-impact store (preferences, relationships) BOTH versions are preserved and the conflict is flagged for you to resolve; for a low-impact store the latest wins but the overwrite is flagged, never silent. A replicated record never clobbers a divergent local one — reach is not authority. Ships DARK behind \`multiMachine.stateSync.<store>\` (default false); a single-machine agent is a strict no-op.
4334
+ - See open conflicts: \`curl -H "Authorization: Bearer $AUTH" http://localhost:4042/state/conflicts\` → the unresolved divergences awaiting your call (each with a stable \`conflictId\` + the preserved versions).
4335
+ - Resolve one (YOUR authority — the foundation never picks a winner): \`curl -X POST -H "Authorization: Bearer $AUTH" http://localhost:4042/state/resolve-conflict -H 'Content-Type: application/json' -d '{"conflictId":"<id>","winnerOrigin":"<machine id>"}'\` (or supply a \`mergedVersion\` object). The chosen/merged record then replicates as normal.
4336
+ - Roll back a machine's data (un-merge): disabling \`multiMachine.stateSync.<store>\` for a peer atomically DROPS that origin's contribution — the union recomputes live, a key that was winning from the dropped machine reverts to the latest among the REMAINING machines (or to "no record"), any conflict that only existed because of it auto-resolves, and the dropped streams are quarantined-aside (reversible, auditable, never a destructive delete). View what's currently un-merged: \`curl -H "Authorization: Bearer $AUTH" http://localhost:4042/state/quarantine\`.
4337
+ - **When to use** (PROACTIVE — these are the triggers): the user asks "why do I have two versions of preference X?" → read open conflicts and present them for resolution. The user says "roll back machine Y's data / forget what the other machine learned" → un-merge that origin. Spec: \`docs/specs/multi-machine-replicated-store-foundation.md\` §7.
4338
+ `;
4339
+ content += '\n' + oneMemory;
4340
+ patched = true;
4341
+ result.upgraded.push('CLAUDE.md: added One Memory (replicated stores) section');
4342
+ }
4247
4343
  // ContextWedgeSentinel — the 4th silently-stopped sentinel. Tells the agent
4248
4344
  // about the transcript fast-fail wedges (thinking-block 400 + AUP-rejection
4249
4345
  // loop) + that auto-recovery is opt-in. Without it, an agent asked "why did
@@ -5530,6 +5626,16 @@ Create worktrees for collaborator repos with \`instar worktree create <branch>\`
5530
5626
  patched = true;
5531
5627
  result.upgraded.push('CLAUDE.md: added Threadline Single-Negotiator section');
5532
5628
  }
5629
+ // HONEST-PROGRESS-MESSAGING C (docs alignment) — the silent-freeze watchdog +
5630
+ // promise beacon are now honest (corroborate before claiming a freeze; silent
5631
+ // unless there's something true to say). Existing agents learn what they are,
5632
+ // their defaults, and how to tune/disable via this appended subsection (Agent
5633
+ // Awareness Standard). Content-sniff marker keeps it idempotent.
5634
+ if (!content.includes('Honest progress messaging (silent-freeze watchdog + promise beacon)')) {
5635
+ content += `\n### Honest progress messaging (silent-freeze watchdog + promise beacon)\n\nTwo background notifiers used to post frequent, falsely-confident noise because they judged "work" by whether the terminal *screen* repainted — a busy long task looks identical to a frozen one. Both are now honest. They are SIGNALS, never gates: they only decide whether to notify you, and every error path fails toward silence.\n- **Silent-freeze watchdog** (ActiveWorkSilenceSentinel): before claiming a session is stuck, it re-captures the LIVE frame and corroborates — if the frame still shows an active-work indicator (spinner / "esc to interrupt"), a sub-agent is live, or it's a clean idle prompt, it stays SILENT. It speaks only when genuinely wedged, and even then hedges ("…hasn't changed in N min and a nudge didn't wake it — it may be stuck, or on a long task I can't see into. Want me to check?"). Threshold raised 15m→30m; a 90m frozen-indicator backstop still surfaces a real mid-tool hang. Tune/disable: \`monitoring.activeWorkSilenceSentinel.enabled\` (off), \`.silenceThresholdMs\` (default 30m), \`.activeWorkMaxFrozenIndicatorMs\` (default 90m).\n- **Promise beacon** (the ⏳ heartbeats): the zero-information "still on it, no new output" filler is suppressed by default — it speaks only on genuine new progress, deadline pressure, a sparse once-per-60m liveness line, or a one-shot turn-finished close-out. Base cadence relaxed 10m→20m. Tune/disable: \`promiseBeacon.suppressUnchangedHeartbeats: false\` (restore the legacy every-tick heartbeat — the rollback lever), \`promiseBeacon.beaconLivenessIntervalMs\` (default 60m), \`promiseBeacon.turnFinishedCloseoutChecks\` (default 3).\n- **Doc correction:** the trio's escalations are NOT gated by \`monitoring.sentinelTelegramEscalation\` (that gate governs a different path); they route through the tone-gated \`/attention\` surface and are controlled by each sentinel's own \`enabled\` flag (both default true). Effectiveness is measurable in \`logs/sentinel-events.jsonl\` and the per-feature LLM-metrics surface (feature keys \`active-work-silence\`, \`promise-beacon\`). Spec: \`docs/specs/HONEST-PROGRESS-MESSAGING-SPEC.md\`.\n`;
5636
+ patched = true;
5637
+ result.upgraded.push('CLAUDE.md: added Honest progress messaging section');
5638
+ }
5533
5639
  if (patched) {
5534
5640
  try {
5535
5641
  fs.writeFileSync(claudeMdPath, content);
@@ -5702,6 +5808,16 @@ Create worktrees for collaborator repos with \`instar worktree create <branch>\`
5702
5808
  // Metrics precedent; each CLAUDE.md contains exactly one, so the other no-ops.
5703
5809
  '**Links that survive machine boundaries (WS4.4',
5704
5810
  '### Links that survive machine boundaries (WS4.4',
5811
+ // One Memory (replicated stores) — multi-machine-replicated-store-foundation
5812
+ // §7: framework-agnostic — a Codex/Gemini agent on a multi-machine pool must
5813
+ // know stores replicate with a no-clobber union + operator-resolved conflicts
5814
+ // (/state/conflicts, /state/resolve-conflict) + origin-tagged rollback
5815
+ // (/state/quarantine), so it answers "why two versions of preference X?" /
5816
+ // "roll back machine Y's data" instead of improvising a clobber. Two tail-
5817
+ // truncated variants cover both deployed forms (templates' bold block +
5818
+ // migrateClaudeMd's H3); each CLAUDE.md contains exactly one, so the other no-ops.
5819
+ '**One Memory (replicated stores)',
5820
+ '### One Memory (replicated stores)',
5705
5821
  ];
5706
5822
  for (const shadowName of ['AGENTS.md', 'GEMINI.md']) {
5707
5823
  const shadowPath = path.join(this.config.projectDir, shadowName);