instar 1.3.1647 → 1.3.1649

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 (116) hide show
  1. package/dashboard/console/console.css +3 -0
  2. package/dashboard/console/maturation-board-model.js +51 -0
  3. package/dashboard/console/maturation-board.js +17 -1
  4. package/dist/commands/server.d.ts.map +1 -1
  5. package/dist/commands/server.js +20 -0
  6. package/dist/commands/server.js.map +1 -1
  7. package/dist/core/PostUpdateMigrator.d.ts +5 -0
  8. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  9. package/dist/core/PostUpdateMigrator.js +24 -0
  10. package/dist/core/PostUpdateMigrator.js.map +1 -1
  11. package/dist/core/SessionManager.d.ts +6 -121
  12. package/dist/core/SessionManager.d.ts.map +1 -1
  13. package/dist/core/SessionManager.js +40 -7
  14. package/dist/core/SessionManager.js.map +1 -1
  15. package/dist/core/devGatedFeatures.d.ts.map +1 -1
  16. package/dist/core/devGatedFeatures.js +6 -0
  17. package/dist/core/devGatedFeatures.js.map +1 -1
  18. package/dist/core/sessionCapacityRefusedError.d.ts +8 -0
  19. package/dist/core/sessionCapacityRefusedError.d.ts.map +1 -0
  20. package/dist/core/sessionCapacityRefusedError.js +13 -0
  21. package/dist/core/sessionCapacityRefusedError.js.map +1 -0
  22. package/dist/core/types.d.ts +11 -0
  23. package/dist/core/types.d.ts.map +1 -1
  24. package/dist/core/types.js.map +1 -1
  25. package/dist/data/standards-guard-index.json +1 -1
  26. package/dist/data/standards-guard-index.meta.json +2 -2
  27. package/dist/data/standards-registry.meta.json +1 -1
  28. package/dist/messaging/TelegramAdapter.d.ts +10 -0
  29. package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
  30. package/dist/messaging/TelegramAdapter.js +12 -1
  31. package/dist/messaging/TelegramAdapter.js.map +1 -1
  32. package/dist/messaging/telegram-origin/TelegramOriginBoot.d.ts +2 -0
  33. package/dist/messaging/telegram-origin/TelegramOriginBoot.d.ts.map +1 -1
  34. package/dist/messaging/telegram-origin/TelegramOriginBoot.js +2 -0
  35. package/dist/messaging/telegram-origin/TelegramOriginBoot.js.map +1 -1
  36. package/dist/messaging/telegram-origin/TelegramOriginRuntime.d.ts +16 -0
  37. package/dist/messaging/telegram-origin/TelegramOriginRuntime.d.ts.map +1 -1
  38. package/dist/messaging/telegram-origin/TelegramOriginRuntime.js +23 -2
  39. package/dist/messaging/telegram-origin/TelegramOriginRuntime.js.map +1 -1
  40. package/dist/messaging/telegram-origin/TelegramOriginService.d.ts +1 -0
  41. package/dist/messaging/telegram-origin/TelegramOriginService.d.ts.map +1 -1
  42. package/dist/messaging/telegram-origin/TelegramOriginService.js +5 -2
  43. package/dist/messaging/telegram-origin/TelegramOriginService.js.map +1 -1
  44. package/dist/monitoring/BlockerLifecycleService.d.ts +26 -3
  45. package/dist/monitoring/BlockerLifecycleService.d.ts.map +1 -1
  46. package/dist/monitoring/BlockerLifecycleService.js +92 -17
  47. package/dist/monitoring/BlockerLifecycleService.js.map +1 -1
  48. package/dist/monitoring/FeatureEvidenceLog.d.ts +53 -0
  49. package/dist/monitoring/FeatureEvidenceLog.d.ts.map +1 -0
  50. package/dist/monitoring/FeatureEvidenceLog.js +99 -0
  51. package/dist/monitoring/FeatureEvidenceLog.js.map +1 -0
  52. package/dist/monitoring/LadderEvidenceReader.d.ts +31 -0
  53. package/dist/monitoring/LadderEvidenceReader.d.ts.map +1 -0
  54. package/dist/monitoring/LadderEvidenceReader.js +204 -0
  55. package/dist/monitoring/LadderEvidenceReader.js.map +1 -0
  56. package/dist/monitoring/MaturationBoard.d.ts +1 -1
  57. package/dist/monitoring/MaturationBoard.d.ts.map +1 -1
  58. package/dist/monitoring/MaturationBoard.js +5 -1
  59. package/dist/monitoring/MaturationBoard.js.map +1 -1
  60. package/dist/monitoring/MaturationLadder.d.ts +214 -0
  61. package/dist/monitoring/MaturationLadder.d.ts.map +1 -0
  62. package/dist/monitoring/MaturationLadder.js +495 -0
  63. package/dist/monitoring/MaturationLadder.js.map +1 -0
  64. package/dist/monitoring/MaturationLadderService.d.ts +189 -0
  65. package/dist/monitoring/MaturationLadderService.d.ts.map +1 -0
  66. package/dist/monitoring/MaturationLadderService.js +593 -0
  67. package/dist/monitoring/MaturationLadderService.js.map +1 -0
  68. package/dist/monitoring/maturationUniverse.d.ts +14 -0
  69. package/dist/monitoring/maturationUniverse.d.ts.map +1 -0
  70. package/dist/monitoring/maturationUniverse.js +54 -0
  71. package/dist/monitoring/maturationUniverse.js.map +1 -0
  72. package/dist/native/InstarWedgeCanary.app/Contents/MacOS/InstarWedgeCanary +0 -0
  73. package/dist/native/instar-desktop-host +0 -0
  74. package/dist/scaffold/templates.d.ts.map +1 -1
  75. package/dist/scaffold/templates.js +2 -1
  76. package/dist/scaffold/templates.js.map +1 -1
  77. package/dist/scheduler/JobScheduler.d.ts.map +1 -1
  78. package/dist/scheduler/JobScheduler.js +6 -1
  79. package/dist/scheduler/JobScheduler.js.map +1 -1
  80. package/dist/server/AgentServer.d.ts +5 -0
  81. package/dist/server/AgentServer.d.ts.map +1 -1
  82. package/dist/server/AgentServer.js +115 -1
  83. package/dist/server/AgentServer.js.map +1 -1
  84. package/dist/server/CapabilityIndex.d.ts.map +1 -1
  85. package/dist/server/CapabilityIndex.js +9 -0
  86. package/dist/server/CapabilityIndex.js.map +1 -1
  87. package/dist/server/maturationBoardRoutes.d.ts +2 -0
  88. package/dist/server/maturationBoardRoutes.d.ts.map +1 -1
  89. package/dist/server/maturationBoardRoutes.js +34 -1
  90. package/dist/server/maturationBoardRoutes.js.map +1 -1
  91. package/dist/server/maturationLadderRoutes.d.ts +29 -0
  92. package/dist/server/maturationLadderRoutes.d.ts.map +1 -0
  93. package/dist/server/maturationLadderRoutes.js +143 -0
  94. package/dist/server/maturationLadderRoutes.js.map +1 -0
  95. package/dist/server/routes.d.ts.map +1 -1
  96. package/dist/server/routes.js +5 -1
  97. package/dist/server/routes.js.map +1 -1
  98. package/dist/testing/selfActionRegistry.d.ts.map +1 -1
  99. package/dist/testing/selfActionRegistry.js +37 -0
  100. package/dist/testing/selfActionRegistry.js.map +1 -1
  101. package/package.json +1 -1
  102. package/skills/spec-converge/scripts/write-convergence-tag.mjs +5 -2
  103. package/src/core/FeatureMaturationPlanGate.mjs +15 -1
  104. package/src/data/builtin-manifest.json +66 -66
  105. package/src/data/feature-ladders.json +191 -0
  106. package/src/data/standards-guard-index.json +1 -1
  107. package/src/data/standards-guard-index.meta.json +2 -2
  108. package/src/data/standards-registry.meta.json +1 -1
  109. package/src/data/state-coherence-registry.json +32 -0
  110. package/src/scaffold/templates.ts +2 -1
  111. package/upgrades/1.3.1648.md +29 -0
  112. package/upgrades/1.3.1649.md +28 -0
  113. package/upgrades/job-alert-global-cap.eli16.md +9 -0
  114. package/upgrades/side-effects/echo-bugs-recovered-reply-history.md +67 -0
  115. package/upgrades/side-effects/feature-maturation-ladder.md +69 -0
  116. package/upgrades/side-effects/job-alert-global-cap.md +66 -0
@@ -1136,6 +1136,9 @@ a.machine-line-link:hover { border-color: var(--accent); color: var(--text); }
1136
1136
  .mb-card dt { color: var(--text-faint); font-size: 14px; padding-top: 1px; }
1137
1137
  .mb-card dd { margin: 0; font-size: 16px; line-height: 1.4; }
1138
1138
  .mb-card dd[data-tone="bad"] { color: #ef5b5b; font-weight: 600; }
1139
+ .mb-numbers { margin: 10px 0 0; padding: 0; list-style: none; font-size: 15px; line-height: 1.5; }
1140
+ .mb-numbers li[data-tone="bad"] { color: #ef5b5b; }
1141
+ .mb-numbers li[data-tone="ok"] { color: #34c38f; }
1139
1142
  .mb-card dd[data-tone="ok"] { color: #34c38f; font-weight: 600; }
1140
1143
  .mb-next { margin: 0 0 8px; }
1141
1144
  .mb-detail-line { margin: 0 0 8px; color: var(--text-muted); }
@@ -145,6 +145,8 @@ export function subline(board) {
145
145
  const fs = board.features || [];
146
146
  const a = attention(fs);
147
147
  const bits = [];
148
+ const ready = readyToMove(fs).length;
149
+ if (ready) bits.push(`${ready} ready to move up.`);
148
150
  if (a.need) {
149
151
  const parts = [];
150
152
  if (a.nobody) parts.push(`${a.nobody} have no fix planned`);
@@ -253,6 +255,54 @@ export function measureText(m) {
253
255
  return bits.join(' · ');
254
256
  }
255
257
 
258
+ const RUNG_WORDS = { dark: 'Off everywhere', 'dry-run': 'Practising, not acting', 'dev-agent-live': 'On for development agents', fleet: 'On by default' };
259
+ const LADDER_STATE_WORDS = {
260
+ 'ready-to-advance': 'Has met its numbers; waiting on the review',
261
+ soaking: 'Numbers met; holding them',
262
+ hold: 'A number is off target',
263
+ collecting: 'Not enough data yet',
264
+ 'no-data': 'Not recording anything yet',
265
+ 'no-opportunity': 'Hasn’t had a chance to run',
266
+ 'not-started': 'Nothing runs it yet',
267
+ harmed: 'Got worse after its last move',
268
+ held: 'Held by its operator',
269
+ 'at-final': 'At its last step',
270
+ 'retire-pending': 'Being retired',
271
+ composed: 'Moves with its parent feature',
272
+ };
273
+
274
+ /** The ladder's own facts for a row, from the machine that read them. */
275
+ export function ladderOf(f) {
276
+ const o = (f.owners || []).find((x) => x.source === 'ladder');
277
+ return o ? o.facts : null;
278
+ }
279
+
280
+ /** Ready to move up: the ladder says so, on any machine. */
281
+ export function readyToMove(features) {
282
+ return features.filter((f) => (ladderOf(f) || {}).state === 'ready-to-advance');
283
+ }
284
+
285
+ /** One plain line: where it is and what the numbers say. */
286
+ export function ladderLine(f) {
287
+ const l = ladderOf(f);
288
+ if (!l) return '';
289
+ const bits = [RUNG_WORDS[l.rung] || l.rung, LADDER_STATE_WORDS[l.state] || l.state];
290
+ if (l.total) bits.push(`${l.passing} of ${l.total} numbers met`);
291
+ if (l.state === 'soaking' && l.soakNeeded) bits.push(`held ${l.soakDays} of ${l.soakNeeded} days`);
292
+ return bits.join(' · ');
293
+ }
294
+
295
+ const ROLE_WORDS = { ran: 'Ran', quality: 'Quality', harm: 'Harm' };
296
+
297
+ /** A threshold as now vs target, in plain words. */
298
+ export function metricText(m) {
299
+ const target = `${m.direction === 'at-least' ? 'at least' : 'at most'} ${m.threshold}`;
300
+ if (m.value === null || m.value === undefined) return `${ROLE_WORDS[m.role] || m.role}: no number yet (target ${target})`;
301
+ const now = Number.isInteger(m.value) ? m.value : Number(m.value.toFixed(3));
302
+ const short = m.samples < m.minSamples ? `, only ${m.samples} of ${m.minSamples} samples` : '';
303
+ return `${ROLE_WORDS[m.role] || m.role}: ${now} (target ${target}${short})`;
304
+ }
305
+
256
306
  /** The short card under a tapped row. Rows with nothing to say are left out. */
257
307
  export function card(f) {
258
308
  const r = f.review || {};
@@ -260,6 +310,7 @@ export function card(f) {
260
310
  const due = d ? `${fmtDate(d.date)}${d.overdueDays != null ? ` (${d.overdueDays} days late)` : ''}` : '';
261
311
  return [
262
312
  { label: 'What it does', text: r.purpose || '' },
313
+ { label: 'Where it is', text: ladderLine(f), tone: (ladderOf(f) || {}).state === 'harmed' ? 'bad' : (ladderOf(f) || {}).state === 'ready-to-advance' ? 'ok' : '' },
263
314
  { label: 'To move up', text: r.goal || '' },
264
315
  { label: 'Now', text: measureText(r.measure) || r.summary || '', tone: r.measure && r.measure.trend === 'worse' ? 'bad' : r.measure && r.measure.trend === 'better' ? 'ok' : '' },
265
316
  { label: 'Plan', text: r.plan || r.nextStep || '' },
@@ -9,11 +9,12 @@ import { el, cantTell, setKids, firstPaint, arrivalScroll } from './ui.js';
9
9
  import { maturationPaceNode } from './pace.js';
10
10
  import {
11
11
  GROUPS, groupOf, groupCounts, headline, subline, parseState, stateQuery, openGroups,
12
- filterRows, orderInGroup, sortRows, SORTS, squares, humanName, humanArea, ownerChip, statusLine, timeline, fmtDate, card, isNobody,
12
+ filterRows, orderInGroup, sortRows, SORTS, squares, humanName, humanArea, ownerChip, statusLine, timeline, fmtDate, metricText, ladderOf, card, isNobody,
13
13
  } from './maturation-board-model.js';
14
14
 
15
15
  const POOL_TIMEOUT_MS = 12_000;
16
16
  let lastBoard = null;
17
+ let ladderApi = null;
17
18
 
18
19
  /**
19
20
  * @param main container element
@@ -21,6 +22,7 @@ let lastBoard = null;
21
22
  * @param nav { read() → query string, write(query) } — where view state lives in the URL
22
23
  */
23
24
  export async function renderMaturation(main, api, nav = consoleNav()) {
25
+ ladderApi = api;
24
26
  if (!lastBoard) firstPaint(main, el('p', { class: 'mb-loading', text: 'Reading every machine…' }));
25
27
  const r = await api.get('/maturation/board?scope=pool', POOL_TIMEOUT_MS);
26
28
  if (!r.ok) {
@@ -139,11 +141,14 @@ function detail(f) {
139
141
  const steps = timeline(f, Date.now());
140
142
  const fus = (f.followUp && f.followUp.items) || [];
141
143
  const rows = card(f);
144
+ const numbers = ladderOf(f) ? el('ul', { class: 'mb-numbers', 'aria-label': 'The numbers it must hit' }) : null;
145
+ if (numbers && ladderApi) fillNumbers(numbers, f);
142
146
  return el('div', { class: 'mb-detail' },
143
147
  rows.length ? el('dl', { class: 'mb-card' }, rows.flatMap((x) => [
144
148
  el('dt', { text: x.label }),
145
149
  el('dd', { text: x.text, 'data-tone': x.tone || null }),
146
150
  ])) : el('p', { class: 'mb-detail-line', text: 'The review hasn’t described this one in plain words yet.' }),
151
+ numbers,
147
152
  steps.length ? el('ol', { class: 'mb-steps', 'aria-label': 'What happened, by date' },
148
153
  steps.map((p) => el('li', { class: `${p.overdue ? 'overdue' : ''}${p.future ? ' future' : ''}` },
149
154
  el('span', { class: 'mb-when', text: p.when }), el('span', { text: p.label })))) : null,
@@ -162,6 +167,17 @@ function detail(f) {
162
167
  )));
163
168
  }
164
169
 
170
+ /** Thresholds, read on tap so the board stays light. A failed read just leaves the list empty. */
171
+ async function fillNumbers(list, f) {
172
+ const r = await ladderApi.get(`/maturation/ladder?id=${encodeURIComponent(f.id)}`, 8_000);
173
+ const row = r.ok && r.data && r.data.features && r.data.features[0];
174
+ if (!row) return;
175
+ setKids(list, ...row.metrics.map((m) => el('li', {
176
+ text: metricText(m),
177
+ 'data-tone': m.pass === false ? 'bad' : m.pass === true ? 'ok' : null,
178
+ })));
179
+ }
180
+
165
181
  function kv(k, v) { return v ? [el('dt', { text: k }), el('dd', { text: v })] : []; }
166
182
 
167
183
  function sourcesNote(board) {
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"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"}
@@ -6387,6 +6387,26 @@ export async function startServer(options) {
6387
6387
  const { bootTelegramOrigin } = await import('../messaging/telegram-origin/TelegramOriginBoot.js')
6388
6388
  .catch(error => { releaseOriginLeaseRenewal(); throw error; });
6389
6389
  telegramOriginBoot = await bootTelegramOrigin({ config, token: typeof originBotToken === 'string' && originBotToken ? originBotToken : undefined,
6390
+ onRecoveredMessage: entry => {
6391
+ telegram?.logRecoveredOriginMessage(entry);
6392
+ const attentionId = `telegram-origin-held-reply:${entry.operationId}`;
6393
+ if (telegram?.clearAttentionCondition({ id: attentionId }, `Telegram accepted recovered message ${entry.messageId}.`).closed === 0) {
6394
+ void telegram?.updateAttentionStatus(attentionId, 'DONE', { silent: true,
6395
+ closedBy: 'cause-cleared', resolution: `Telegram accepted recovered message ${entry.messageId}.` });
6396
+ }
6397
+ },
6398
+ onSessionDeliveryHeld: entry => {
6399
+ if (!telegram || !entry.chatId)
6400
+ return;
6401
+ const topicId = entry.chatId === String(originTelegramConfig.config.issuesChatId)
6402
+ ? 10_000_000_000 + (entry.threadId ?? 1) : entry.threadId;
6403
+ void telegram.createAttentionItem({ id: `telegram-origin-held-reply:${entry.operationId}`,
6404
+ category: 'telegram-origin', priority: 'HIGH', title: 'A session reply is delayed',
6405
+ sourceContext: 'telegram-origin-session-hold',
6406
+ summary: `A reply to topic ${topicId ?? 'unknown'} is still in the delivery queue. Telegram was unreachable before this attempt connected; the server will retry the same message.`,
6407
+ description: `Operation ${entry.operationId}. The advisory preflight does not confirm delivery.` }, { hubOnly: true })
6408
+ .catch(error => console.warn('[telegram-origin] held reply attention unavailable', error instanceof Error ? error.name : 'unknown-error'));
6409
+ },
6390
6410
  noticeOwner: typeof originBotToken === 'string' && !!originBotToken && !lifelineOwnsTelegramPoll(config.stateDir, originBotToken) && options.telegram !== false,
6391
6411
  holdsLease: () => coordinator.holdsLease(),
6392
6412
  isSessionLive: binding => {