instar 1.3.890 → 1.3.892

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 (71) hide show
  1. package/dashboard/index.html +35 -2
  2. package/dashboard/preferences-learning.js +2 -2
  3. package/dist/commands/server.d.ts.map +1 -1
  4. package/dist/commands/server.js +100 -2
  5. package/dist/commands/server.js.map +1 -1
  6. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  7. package/dist/config/ConfigDefaults.js +12 -1
  8. package/dist/config/ConfigDefaults.js.map +1 -1
  9. package/dist/core/BackupManager.d.ts.map +1 -1
  10. package/dist/core/BackupManager.js +1 -5
  11. package/dist/core/BackupManager.js.map +1 -1
  12. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  13. package/dist/core/PostUpdateMigrator.js +33 -7
  14. package/dist/core/PostUpdateMigrator.js.map +1 -1
  15. package/dist/core/devGatedFeatures.d.ts.map +1 -1
  16. package/dist/core/devGatedFeatures.js +8 -2
  17. package/dist/core/devGatedFeatures.js.map +1 -1
  18. package/dist/core/types.d.ts +13 -0
  19. package/dist/core/types.d.ts.map +1 -1
  20. package/dist/core/types.js.map +1 -1
  21. package/dist/monitoring/AutonomousThroughputFloor.d.ts +118 -0
  22. package/dist/monitoring/AutonomousThroughputFloor.d.ts.map +1 -0
  23. package/dist/monitoring/AutonomousThroughputFloor.js +147 -0
  24. package/dist/monitoring/AutonomousThroughputFloor.js.map +1 -0
  25. package/dist/monitoring/ClaimClauseArbiter.d.ts +11 -2
  26. package/dist/monitoring/ClaimClauseArbiter.d.ts.map +1 -1
  27. package/dist/monitoring/ClaimClauseArbiter.js +55 -9
  28. package/dist/monitoring/ClaimClauseArbiter.js.map +1 -1
  29. package/dist/monitoring/ClaimObservation.d.ts +181 -0
  30. package/dist/monitoring/ClaimObservation.d.ts.map +1 -0
  31. package/dist/monitoring/ClaimObservation.js +575 -0
  32. package/dist/monitoring/ClaimObservation.js.map +1 -0
  33. package/dist/monitoring/ClaimObservationAdmissionQueue.d.ts +38 -0
  34. package/dist/monitoring/ClaimObservationAdmissionQueue.d.ts.map +1 -0
  35. package/dist/monitoring/ClaimObservationAdmissionQueue.js +90 -0
  36. package/dist/monitoring/ClaimObservationAdmissionQueue.js.map +1 -0
  37. package/dist/monitoring/CompletionClaimVerifier.d.ts +45 -4
  38. package/dist/monitoring/CompletionClaimVerifier.d.ts.map +1 -1
  39. package/dist/monitoring/CompletionClaimVerifier.js +74 -29
  40. package/dist/monitoring/CompletionClaimVerifier.js.map +1 -1
  41. package/dist/monitoring/LlmQueue.d.ts +31 -0
  42. package/dist/monitoring/LlmQueue.d.ts.map +1 -1
  43. package/dist/monitoring/LlmQueue.js +41 -0
  44. package/dist/monitoring/LlmQueue.js.map +1 -1
  45. package/dist/monitoring/TurnEvidence.d.ts.map +1 -1
  46. package/dist/monitoring/TurnEvidence.js +12 -4
  47. package/dist/monitoring/TurnEvidence.js.map +1 -1
  48. package/dist/scaffold/templates.d.ts.map +1 -1
  49. package/dist/scaffold/templates.js +5 -1
  50. package/dist/scaffold/templates.js.map +1 -1
  51. package/dist/server/AgentServer.d.ts +3 -0
  52. package/dist/server/AgentServer.d.ts.map +1 -1
  53. package/dist/server/AgentServer.js +83 -2
  54. package/dist/server/AgentServer.js.map +1 -1
  55. package/dist/server/CapabilityIndex.js +1 -1
  56. package/dist/server/CapabilityIndex.js.map +1 -1
  57. package/dist/server/fileRoutes.d.ts.map +1 -1
  58. package/dist/server/fileRoutes.js +2 -0
  59. package/dist/server/fileRoutes.js.map +1 -1
  60. package/dist/server/routes.d.ts +2 -0
  61. package/dist/server/routes.d.ts.map +1 -1
  62. package/dist/server/routes.js +93 -21
  63. package/dist/server/routes.js.map +1 -1
  64. package/package.json +1 -1
  65. package/src/data/builtin-manifest.json +65 -65
  66. package/src/data/state-coherence-registry.json +18 -0
  67. package/src/scaffold/templates.ts +5 -1
  68. package/upgrades/1.3.891.md +30 -0
  69. package/upgrades/1.3.892.md +20 -0
  70. package/upgrades/side-effects/autonomous-throughput-floor.md +36 -0
  71. package/upgrades/side-effects/claim-verification-sentinel.md +93 -0
@@ -4235,6 +4235,13 @@ export function createRoutes(ctx) {
4235
4235
  }
4236
4236
  res.json(ctx.autonomousLivenessReconciler.status());
4237
4237
  });
4238
+ router.get('/autonomous/throughput-floor', (_req, res) => {
4239
+ if (!ctx.autonomousThroughputFloor) {
4240
+ res.status(503).json({ error: 'autonomous-throughput-floor not available on this agent' });
4241
+ return;
4242
+ }
4243
+ res.json(ctx.autonomousThroughputFloor.status());
4244
+ });
4238
4245
  // ── Standby-Write Reconciliation (docs/specs/standby-write-reconciliation.md §6) ──
4239
4246
  // The observability surface: mode, per-domain admitted/refused/would-verdict
4240
4247
  // counters, recent typed refusals (minus hints), the ownership-index stats,
@@ -7557,8 +7564,8 @@ export function createRoutes(ctx) {
7557
7564
  }
7558
7565
  : summary.totals;
7559
7566
  const classReview = ctx.classReviewStore?.health() ?? null;
7560
- const completionClaim = ctx.completionClaimVerifier?.stats?.() ?? null;
7561
- res.json({ ...summary, totals, features, classReview, completionClaim });
7567
+ const claimVerificationServerAdmittedOnly = ctx.completionClaimVerifier?.stats?.() ?? null;
7568
+ res.json({ ...summary, totals, features, classReview, claimVerificationServerAdmittedOnly });
7562
7569
  });
7563
7570
  // ── GrowthMilestoneAnalyst (the proactive growth & milestone analyst) ──────
7564
7571
  // Read-only observability over the maturity/initiative/spec/correction
@@ -20527,24 +20534,70 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
20527
20534
  res.status(400).json({ error: 'message is required' });
20528
20535
  return;
20529
20536
  }
20537
+ if (Buffer.byteLength(message, 'utf8') > 32_768) {
20538
+ res.status(413).json({ error: 'claim observation input bound exceeded' });
20539
+ return;
20540
+ }
20541
+ const forbiddenAuthorityFields = ['agentId', 'sessionId', 'projectDir', 'repository', 'machineId', 'ownershipEpoch'];
20542
+ if (forbiddenAuthorityFields.some((field) => field in (req.body ?? {}))) {
20543
+ res.status(400).json({ error: 'authority context is derived server-side' });
20544
+ return;
20545
+ }
20530
20546
  if ('transcriptPath' in (req.body ?? {}) || 'transcript_path' in (req.body ?? {})) {
20531
20547
  res.status(400).json({ error: 'transcript paths are not accepted; send structural TurnEvidence' });
20532
20548
  return;
20533
20549
  }
20534
- const evidence = validateTurnEvidence(req.body?.evidence);
20550
+ const hasV1Envelope = 'hookSchemaVersion' in (req.body ?? {}) || 'messageAttemptId' in (req.body ?? {}) || 'turnEvidence' in (req.body ?? {});
20551
+ const messageAttemptId = typeof req.body?.messageAttemptId === 'string' ? req.body.messageAttemptId : undefined;
20552
+ if (hasV1Envelope && (req.body?.hookSchemaVersion !== 1 || !messageAttemptId
20553
+ || !/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(messageAttemptId))) {
20554
+ res.status(400).json({ error: 'valid hookSchemaVersion and UUIDv7 messageAttemptId are required' });
20555
+ return;
20556
+ }
20557
+ const evidence = validateTurnEvidence(hasV1Envelope ? req.body?.turnEvidence : req.body?.evidence);
20535
20558
  if (!evidence) {
20536
20559
  res.status(400).json({ error: 'valid structural evidence is required' });
20537
20560
  return;
20538
20561
  }
20539
- const topicId = typeof req.body?.topicId === 'number' && Number.isSafeInteger(req.body.topicId) ? req.body.topicId : undefined;
20562
+ const topicId = typeof (hasV1Envelope ? req.body?.topicHint : req.body?.topicId) === 'number'
20563
+ && Number.isSafeInteger(hasV1Envelope ? req.body.topicHint : req.body.topicId)
20564
+ ? Number(hasV1Envelope ? req.body.topicHint : req.body.topicId) : undefined;
20540
20565
  const rawBindHeader = req.headers['x-instar-bind-token'];
20541
20566
  const rawBindToken = (Array.isArray(rawBindHeader) ? rawBindHeader[0] : rawBindHeader)
20542
20567
  ?? (typeof req.body?.bindToken === 'string' ? req.body.bindToken : undefined);
20568
+ const observationBind = topicId === undefined ? null : verifyConversationBind({ bindAuth: ctx.conversationBindAuth,
20569
+ numericTopicId: topicId, rawToken: rawBindToken, attention: ctx.telegram });
20570
+ const boundObservationTopicId = observationBind?.ok ? topicId : undefined;
20571
+ const boundSessionName = observationBind?.ok && observationBind.boundBy?.startsWith('session:')
20572
+ ? observationBind.boundBy.slice('session:'.length) : undefined;
20573
+ const boundSession = boundSessionName ? ctx.state.listSessions().find((session) => session.tmuxSession === boundSessionName) : undefined;
20574
+ const observationNow = new Date();
20575
+ const sessionSnapshot = boundSession ? {
20576
+ state: String(boundSession.status),
20577
+ elapsedMs: Math.max(0, observationNow.getTime() - Date.parse(boundSession.startedAt)),
20578
+ revision: `${boundSession.id}:${boundSession.status}:${boundSession.startedAt}`,
20579
+ observedAt: observationNow.toISOString(),
20580
+ } : undefined;
20581
+ const commitmentSnapshots = Object.fromEntries((boundObservationTopicId === undefined ? [] : (ctx.commitmentTracker?.getActive() ?? [])
20582
+ .filter((commitment) => commitment.topicId === boundObservationTopicId))
20583
+ .slice(0, 100)
20584
+ .map((commitment) => [commitment.id, { state: commitment.status,
20585
+ revision: `${commitment.id}:${commitment.status}:${commitment.lastVerifiedAt ?? commitment.createdAt}`,
20586
+ observedAt: observationNow.toISOString() }]));
20587
+ const guardSnapshots = Object.fromEntries((ctx.guardRegistry?.registeredKeys() ?? []).slice(0, 100).flatMap((key) => {
20588
+ const read = ctx.guardRegistry?.read(key);
20589
+ if (!read || read.kind !== 'ok')
20590
+ return [];
20591
+ const state = !read.status.enabled ? 'off' : read.status.dryRun ? 'dry-run' : 'on';
20592
+ return [[key, { state, revision: `${key}:${state}:${read.status.lastTickAt ?? 0}`,
20593
+ observedAt: observationNow.toISOString() }]];
20594
+ }));
20543
20595
  const admission = ctx.completionClaimVerifier.enqueue(message, evidence, (arbitration) => {
20544
20596
  if (ctx.config.monitoring?.completionClaimVerification?.dryRun === false) {
20545
20597
  registerUnifiedFutureClaims({ message, topicId, rawBindToken, arbitration });
20546
20598
  }
20547
- });
20599
+ }, { ...(messageAttemptId ? { messageAttemptId } : {}), ...(boundObservationTopicId !== undefined ? { topicId: boundObservationTopicId } : {}),
20600
+ ...(sessionSnapshot ? { sessionSnapshot } : {}), commitmentSnapshots, guardSnapshots, originFramework: 'claude-code' });
20548
20601
  if (!admission.accepted && ctx.config.monitoring?.completionClaimVerification?.dryRun === false) {
20549
20602
  // Queue pressure/duplicate/provider uncertainty must never suppress the
20550
20603
  // already-shipped Action-Claim behavior.
@@ -20560,39 +20613,53 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
20560
20613
  return;
20561
20614
  }
20562
20615
  const limit = Math.max(1, Math.min(Number(req.query.limit) || 100, 500));
20563
- const records = ctx.completionClaimVerifier.readAudit(limit);
20616
+ const poolProjection = req.query.projection === 'pool' || req.query.scope === 'pool';
20617
+ const localPage = poolProjection ? ctx.completionClaimVerifier.readPoolPage(limit, typeof req.query.cursor === 'string' ? req.query.cursor : undefined) : undefined;
20618
+ const records = localPage?.records ?? ctx.completionClaimVerifier.readAudit(limit);
20564
20619
  if (req.query.scope !== 'pool') {
20565
- res.json({ records, count: records.length, scope: 'local' });
20620
+ res.json({ records, count: records.length,
20621
+ ...(localPage?.nextCursor ? { nextCursor: localPage.nextCursor } : {}), scope: 'local', denominator: 'server-admitted-only' });
20566
20622
  return;
20567
20623
  }
20568
- const peers = ctx.resolvePeerUrls?.() ?? [];
20624
+ const allPeers = ctx.resolvePeerUrls?.() ?? [];
20625
+ const peers = allPeers.slice(0, 16);
20569
20626
  const extraAllowlist = ctx.config.multiMachine?.peerUrlAllowlist;
20570
20627
  const remote = [];
20571
20628
  const failed = [];
20629
+ let remainingBytes = 256 * 1024;
20572
20630
  await Promise.all(peers.map(async (peer) => {
20573
20631
  if (!isPeerUrlAllowedForCredentials(peer.url, extraAllowlist).ok) {
20574
20632
  failed.push({ machineId: peer.machineId, error: 'url-rejected' });
20575
20633
  return;
20576
20634
  }
20577
20635
  try {
20578
- const response = await fetch(`${peer.url}/completion-claim/audit?limit=${limit}`, {
20579
- headers: { Authorization: `Bearer ${ctx.config.authToken}` }, signal: AbortSignal.timeout(5000),
20636
+ const response = await fetch(`${peer.url}/completion-claim/audit?limit=${limit}&projection=pool`, {
20637
+ headers: { Authorization: `Bearer ${ctx.config.authToken}` }, signal: AbortSignal.timeout(250),
20580
20638
  });
20581
20639
  if (!response.ok) {
20582
20640
  failed.push({ machineId: peer.machineId, error: `HTTP ${response.status}` });
20583
20641
  return;
20584
20642
  }
20585
- const body = await response.json();
20643
+ const raw = await response.text();
20644
+ const size = Buffer.byteLength(raw);
20645
+ if (size > remainingBytes) {
20646
+ failed.push({ machineId: peer.machineId, error: 'response-bound' });
20647
+ return;
20648
+ }
20649
+ remainingBytes -= size;
20650
+ const body = JSON.parse(raw);
20586
20651
  for (const row of (body.records ?? []).slice(0, limit)) {
20587
20652
  // Explicit allowlist: peer audit prose and unknown fields never cross.
20588
- remote.push({ machineId: peer.machineId, remote: true,
20589
- ...(typeof row.ts === 'string' ? { ts: row.ts.slice(0, 64) } : {}),
20590
- ...(typeof row.evaluated === 'boolean' ? { evaluated: row.evaluated } : {}),
20591
- ...(typeof row.flagged === 'boolean' ? { flagged: row.flagged } : {}),
20592
- ...(typeof row.dryRun === 'boolean' ? { dryRun: row.dryRun } : {}),
20593
- ...(typeof row.verdict === 'string' ? { verdict: row.verdict.slice(0, 64) } : {}),
20594
- ...(typeof row.actionKind === 'string' ? { actionKind: row.actionKind.slice(0, 64) } : {}),
20595
- ...(typeof row.hadToolCalls === 'boolean' ? { hadToolCalls: row.hadToolCalls } : {}),
20653
+ remote.push({ machineId: peer.machineId, remote: true, automationEligible: false,
20654
+ ...(typeof row.day === 'string' ? { day: row.day.slice(0, 10) } : {}),
20655
+ ...(typeof row.claimShapeId === 'string' ? { claimShapeId: row.claimShapeId.slice(0, 128) } : {}),
20656
+ ...(typeof row.modelDoor === 'string' ? { modelDoor: row.modelDoor.slice(0, 64) } : {}),
20657
+ ...(typeof row.verifierVersion === 'string' ? { verifierVersion: row.verifierVersion.slice(0, 64) } : {}),
20658
+ ...(typeof row.count === 'number' ? { count: Math.max(0, Math.floor(row.count)) } : {}),
20659
+ ...(row.verdicts && typeof row.verdicts === 'object' ? { verdicts: Object.fromEntries(['supported', 'refuted', 'unverifiable', 'unknown'].flatMap((key) => {
20660
+ const value = row.verdicts[key];
20661
+ return typeof value === 'number' && Number.isFinite(value) ? [[key, Math.max(0, Math.floor(value))]] : [];
20662
+ })) } : {}),
20596
20663
  });
20597
20664
  }
20598
20665
  }
@@ -20600,8 +20667,13 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
20600
20667
  failed.push({ machineId: peer.machineId, error: error instanceof Error ? error.name : 'unreachable' });
20601
20668
  }
20602
20669
  }));
20603
- const merged = [...records.map((row) => ({ ...row, remote: false })), ...remote].slice(0, limit * (peers.length + 1));
20604
- res.json({ records: merged, count: merged.length, scope: 'pool', pool: { peersQueried: peers.length, failed } });
20670
+ const merged = [...records.map((row) => ({ ...row, remote: false })), ...remote]
20671
+ .sort((a, b) => `${a.remote ? String(a.machineId) : 'local'}|${String(a.day ?? '')}|${String(a.claimShapeId ?? '')}`
20672
+ .localeCompare(`${b.remote ? String(b.machineId) : 'local'}|${String(b.day ?? '')}|${String(b.claimShapeId ?? '')}`))
20673
+ .slice(0, Math.min(limit, 200));
20674
+ res.json({ records: merged, count: merged.length, ...(localPage?.nextCursor ? { nextCursor: localPage.nextCursor } : {}),
20675
+ scope: 'pool', denominator: 'server-admitted-only', partial: failed.length > 0 || allPeers.length > peers.length,
20676
+ pool: { peersQueried: peers.length, peersOmitted: Math.max(0, allPeers.length - peers.length), failed } });
20605
20677
  });
20606
20678
  // The recurrence analyzer + closed-loop tick (Correction & Preference Learning
20607
20679
  // Sentinel, spec §3.5/§3.6/§3.7). Invoked by the off-by-default