instar 1.3.34 → 1.3.36

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 (56) hide show
  1. package/README.md +1 -0
  2. package/dist/commands/server.d.ts.map +1 -1
  3. package/dist/commands/server.js +53 -3
  4. package/dist/commands/server.js.map +1 -1
  5. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  6. package/dist/config/ConfigDefaults.js +15 -0
  7. package/dist/config/ConfigDefaults.js.map +1 -1
  8. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  9. package/dist/core/PostUpdateMigrator.js +15 -0
  10. package/dist/core/PostUpdateMigrator.js.map +1 -1
  11. package/dist/core/featureRolloutScan.d.ts +23 -0
  12. package/dist/core/featureRolloutScan.d.ts.map +1 -1
  13. package/dist/core/featureRolloutScan.js +102 -0
  14. package/dist/core/featureRolloutScan.js.map +1 -1
  15. package/dist/core/types.d.ts +45 -0
  16. package/dist/core/types.d.ts.map +1 -1
  17. package/dist/core/types.js.map +1 -1
  18. package/dist/messaging/AgentTelegramComms.d.ts +77 -0
  19. package/dist/messaging/AgentTelegramComms.d.ts.map +1 -1
  20. package/dist/messaging/AgentTelegramComms.js +108 -0
  21. package/dist/messaging/AgentTelegramComms.js.map +1 -1
  22. package/dist/monitoring/ReleaseReadinessSentinel.d.ts +172 -0
  23. package/dist/monitoring/ReleaseReadinessSentinel.d.ts.map +1 -0
  24. package/dist/monitoring/ReleaseReadinessSentinel.js +315 -0
  25. package/dist/monitoring/ReleaseReadinessSentinel.js.map +1 -0
  26. package/dist/monitoring/releaseReadinessWiring.d.ts +54 -0
  27. package/dist/monitoring/releaseReadinessWiring.d.ts.map +1 -0
  28. package/dist/monitoring/releaseReadinessWiring.js +241 -0
  29. package/dist/monitoring/releaseReadinessWiring.js.map +1 -0
  30. package/dist/scaffold/templates.d.ts.map +1 -1
  31. package/dist/scaffold/templates.js +5 -0
  32. package/dist/scaffold/templates.js.map +1 -1
  33. package/dist/server/AgentServer.d.ts +1 -0
  34. package/dist/server/AgentServer.d.ts.map +1 -1
  35. package/dist/server/AgentServer.js +1 -0
  36. package/dist/server/AgentServer.js.map +1 -1
  37. package/dist/server/CapabilityIndex.d.ts.map +1 -1
  38. package/dist/server/CapabilityIndex.js +14 -0
  39. package/dist/server/CapabilityIndex.js.map +1 -1
  40. package/dist/server/routes.d.ts +3 -0
  41. package/dist/server/routes.d.ts.map +1 -1
  42. package/dist/server/routes.js +55 -0
  43. package/dist/server/routes.js.map +1 -1
  44. package/package.json +1 -1
  45. package/scripts/analyze-release.js +221 -0
  46. package/scripts/upgrade-guide-validator.mjs +120 -0
  47. package/src/data/builtin-manifest.json +63 -63
  48. package/src/scaffold/templates/jobs/instar/release-readiness-check.md +24 -0
  49. package/src/scaffold/templates.ts +5 -0
  50. package/upgrades/1.3.35.md +44 -0
  51. package/upgrades/1.3.36.md +39 -0
  52. package/upgrades/side-effects/agent-telegram-comms-send.md +71 -0
  53. package/upgrades/side-effects/release-readiness-visibility-pr2a.md +27 -0
  54. package/upgrades/side-effects/release-readiness-visibility-pr2b.md +26 -0
  55. package/upgrades/side-effects/release-readiness-visibility-pr2c.md +37 -0
  56. package/upgrades/side-effects/release-readiness-visibility-pr3.md +33 -0
@@ -1 +1 @@
1
- {"version":3,"file":"AgentTelegramComms.d.ts","sourceRoot":"","sources":["../../src/messaging/AgentTelegramComms.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AgentTelegramComms.d.ts","sourceRoot":"","sources":["../../src/messaging/AgentTelegramComms.ts"],"names":[],"mappings":"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"}
@@ -167,4 +167,112 @@ export class CycleDetector {
167
167
  }
168
168
  }
169
169
  }
170
+ /**
171
+ * Send an agent-to-agent Telegram message. Formats the marker, calls the injected
172
+ * adapter, writes the sent-audit row (always — even on refusal/failure), and scrubs the
173
+ * bot token from any error surface before returning.
174
+ *
175
+ * Anti-loop invariant (spec §Fix 2a anti-loop #1): refuses any `role` not in the caller's
176
+ * `allowedRoles` set at runtime — no marker is formed, no send is attempted, an audit row
177
+ * is written with `result: 'role-refused'`. A role-handler that consumes role X cannot
178
+ * therefore send role X (the import-surface lint is a backup; this is the runtime guard).
179
+ */
180
+ export async function sendAgentMessage(input, deps) {
181
+ const now = deps.now();
182
+ const a2aId = input.id ?? deps.mintId();
183
+ const corr = input.correlationId ?? a2aId;
184
+ // Runtime anti-loop guard (spec §Fix 2a anti-loop #1).
185
+ if (!deps.allowedRoles.has(input.role)) {
186
+ deps.appendAudit({
187
+ localTs: new Date(now).toISOString(),
188
+ direction: 'sent',
189
+ fromAgent: input.fromAgent,
190
+ toAgent: input.toAgent,
191
+ role: input.role,
192
+ id: a2aId,
193
+ corr,
194
+ ts: now,
195
+ telegramFromBotId: deps.fromBotId,
196
+ telegramToBotId: deps.toBotId,
197
+ topicId: input.toTopicId,
198
+ result: 'role-refused',
199
+ reason: `role "${input.role}" not in caller's allowedRoles`,
200
+ });
201
+ return { ok: false, a2aId, reason: `role "${input.role}" not in caller's allowedRoles` };
202
+ }
203
+ let text;
204
+ try {
205
+ text = formatMarker({ from: input.fromAgent, to: input.toAgent, role: input.role, id: a2aId, corr, ts: now }, input.message);
206
+ }
207
+ catch (err) {
208
+ const reason = scrubToken(err instanceof Error ? err.message : String(err), deps.botToken);
209
+ deps.appendAudit({
210
+ localTs: new Date(now).toISOString(),
211
+ direction: 'sent',
212
+ fromAgent: input.fromAgent,
213
+ toAgent: input.toAgent,
214
+ role: input.role,
215
+ id: a2aId,
216
+ corr,
217
+ ts: now,
218
+ telegramFromBotId: deps.fromBotId,
219
+ telegramToBotId: deps.toBotId,
220
+ topicId: input.toTopicId,
221
+ result: 'failed',
222
+ reason: `format: ${reason}`,
223
+ });
224
+ return { ok: false, a2aId, reason: `format: ${reason}` };
225
+ }
226
+ const result = await deps.send(input.toTopicId, text);
227
+ const row = {
228
+ localTs: new Date(now).toISOString(),
229
+ direction: 'sent',
230
+ fromAgent: input.fromAgent,
231
+ toAgent: input.toAgent,
232
+ role: input.role,
233
+ id: a2aId,
234
+ corr,
235
+ ts: now,
236
+ telegramFromBotId: deps.fromBotId,
237
+ telegramToBotId: deps.toBotId,
238
+ topicId: input.toTopicId,
239
+ result: result.ok ? 'ok' : 'failed',
240
+ sentMessageId: result.ok ? result.messageId : undefined,
241
+ reason: result.ok ? undefined : scrubToken(stringifyError(result.error), deps.botToken),
242
+ };
243
+ deps.appendAudit(row);
244
+ return result.ok
245
+ ? { ok: true, a2aId, sentMessageId: result.messageId }
246
+ : { ok: false, a2aId, reason: row.reason };
247
+ }
248
+ /** Stringify an unknown error without crashing on weird shapes. */
249
+ function stringifyError(err) {
250
+ if (err instanceof Error)
251
+ return err.message;
252
+ if (typeof err === 'string')
253
+ return err;
254
+ try {
255
+ return JSON.stringify(err);
256
+ }
257
+ catch {
258
+ return '[unstringifiable error]';
259
+ }
260
+ }
261
+ /** Scrub the bot token from a string so it can't leak through logs / audit / DegradationReporter
262
+ * (round-2 adversarial F5: Telegram 401 response bodies sometimes echo the token). The
263
+ * token is fixed-length and high-entropy enough that a literal-string replace is enough;
264
+ * we strip the trailing path segment defensively in case only part is echoed. */
265
+ export function scrubToken(s, token) {
266
+ if (!token)
267
+ return s;
268
+ let out = s.split(token).join('[REDACTED-BOT-TOKEN]');
269
+ // Telegram tokens are <bot-id>:<secret>. If only the secret appears, scrub it too.
270
+ const colonIdx = token.indexOf(':');
271
+ if (colonIdx > 0) {
272
+ const secret = token.slice(colonIdx + 1);
273
+ if (secret.length >= 16)
274
+ out = out.split(secret).join('[REDACTED-BOT-TOKEN]');
275
+ }
276
+ return out;
277
+ }
170
278
  //# sourceMappingURL=AgentTelegramComms.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AgentTelegramComms.js","sourceRoot":"","sources":["../../src/messaging/AgentTelegramComms.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AgentTelegramComms.js","sourceRoot":"","sources":["../../src/messaging/AgentTelegramComms.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * ReleaseReadinessSentinel — Layer B of the release-readiness-visibility spec.
3
+ *
4
+ * Watches whether a release is blocked/stalling and makes it impossible to miss.
5
+ * The original incident (2026-05-27): npm publishing silently stalled since
6
+ * v1.3.26 — green merges, green CI, no published release, no alert. The publish
7
+ * workflow's NEXT.md gate is a *silent skip*: a stalled release is
8
+ * indistinguishable from "nothing to publish". This sentinel is the missing
9
+ * visibility — a recurring, near-silent check that surfaces a stuck release as
10
+ * a single, deduped, escalating Attention item.
11
+ *
12
+ * Design (spec §4.2):
13
+ * - Reads canonical `main` (FETCH_HEAD), not the local checkout, so a stale
14
+ * dev branch can't produce a false "all clear".
15
+ * - "Blocked" is decoupled from NEXT.md state (so Layer A's auto-draft can't
16
+ * silence the alarm by clearing the file): unreleased feature/fix commits
17
+ * exist AND the guide can't publish (missing/template/unreviewed), OR the
18
+ * analyzer reports critical/high coverage gaps.
19
+ * - Near-silent: silent below threshold (state + log only); ONE Attention
20
+ * item per stall episode above it, keyed on the OLDEST unreleased commit
21
+ * SHA (stable across ticks — not a resettable per-tick id), priority scaled
22
+ * by backlog age, 12h hysteresis on re-raise after an auto-resolve.
23
+ * - Fail-loud: any evaluation failure (fetch error, analyzer error) raises a
24
+ * low-priority Attention item — never a silent catch (that would re-create
25
+ * the exact bug this fixes).
26
+ * - Lifecycle owner: detect → surface → auto-resolve → reap, with
27
+ * resolveEpisodesInRange consulted by the publish-finalize path.
28
+ * - Repo-gated: needs an analyzable instar git repo (dev/maintainer env). On
29
+ * an npm-installed agent with no such repo the deps make the check inert.
30
+ * - Supervision: Tier 0 (mechanical computation + fixed-template wording).
31
+ */
32
+ import { EventEmitter } from 'node:events';
33
+ /** Parsed subset of `analyze-release.js --json` the sentinel needs. */
34
+ export interface AnalyzerReport {
35
+ lastTag: string;
36
+ commitCount: number;
37
+ analysis: {
38
+ commitClassification: {
39
+ features: number;
40
+ fixes: number;
41
+ };
42
+ };
43
+ guideCoverage: {
44
+ criticalGaps: number;
45
+ highGaps: number;
46
+ };
47
+ }
48
+ export interface OldestCommit {
49
+ sha: string;
50
+ dateMs: number;
51
+ }
52
+ export interface ReadinessEpisode {
53
+ /** Stable key: SHA of the oldest unreleased commit at first detection. */
54
+ oldestSha: string;
55
+ firstDetectedMs: number;
56
+ /** Set when an Attention item was raised (age crossed the threshold). */
57
+ openedMs?: number;
58
+ attentionId?: string;
59
+ lastPriority?: ReadinessPriority;
60
+ resolvedMs?: number;
61
+ resolvedReason?: 'published' | 'stale' | 'rolled-back' | 'cleared';
62
+ }
63
+ export interface ReadinessState {
64
+ episodes: ReadinessEpisode[];
65
+ /** Episodes resolved recently — used for the re-raise hysteresis window. */
66
+ recentResolves: Array<{
67
+ oldestSha: string;
68
+ resolvedMs: number;
69
+ }>;
70
+ /** Last failure-episode key we signaled, to dedupe fail-loud notices. */
71
+ lastFailureKey?: string;
72
+ lastTickAt?: number;
73
+ lastSignalAt?: number;
74
+ cacheHeadSha?: string;
75
+ canonicalRemoteOverridden?: boolean;
76
+ /** Runtime kill-switch set by POST /release-readiness/rollback. When true,
77
+ * tick() no-ops without evaluating. Cleared by /release-readiness/enable. */
78
+ disabled?: boolean;
79
+ rollbackHistory?: Array<{
80
+ ts: number;
81
+ sessionId?: string;
82
+ sourceIp?: string;
83
+ reason?: string;
84
+ }>;
85
+ }
86
+ export type ReadinessPriority = 'LOW' | 'MEDIUM' | 'HIGH';
87
+ export interface AttentionItem {
88
+ id: string;
89
+ title: string;
90
+ summary: string;
91
+ category?: string;
92
+ priority?: string;
93
+ }
94
+ export interface ReleaseReadinessSentinelDeps {
95
+ /** Fetch canonical main; resolve FETCH_HEAD sha. ok:false ⇒ unreachable. */
96
+ fetchCanonical(): Promise<{
97
+ ok: boolean;
98
+ headSha?: string;
99
+ }>;
100
+ /** Run analyze-release.js --json --ref against the canonical ref. null ⇒ error. */
101
+ runAnalyzer(ref: string): Promise<AnalyzerReport | null>;
102
+ /** Oldest unreleased feature/fix commit relative to lastTag..ref. */
103
+ oldestUnreleasedCommit(lastTag: string, ref: string): Promise<OldestCommit | null>;
104
+ /** True when the publish gate would refuse the guide (missing/template/unreviewed). */
105
+ guideBlocksPublish(): Promise<boolean>;
106
+ /** Best-effort: seed NEXT.md via Layer A (analyze-release.js --draft-guide). */
107
+ draftGuide(ref: string): Promise<void>;
108
+ /** Post an Attention item; resolves to true on delivery. */
109
+ postAttention(item: AttentionItem): Promise<boolean>;
110
+ /** Resolve an open Attention item by id. */
111
+ resolveAttention(id: string, reason: string): Promise<boolean>;
112
+ /** Load persisted state (or a fresh empty state). */
113
+ loadState(): ReadinessState;
114
+ /** Persist state atomically. */
115
+ saveState(state: ReadinessState): void;
116
+ /** Is `sha` an ancestor of `ref`? (for resolveEpisodesInRange) */
117
+ isAncestor(sha: string, ref: string): Promise<boolean>;
118
+ /** Append a structured audit line (sentinel-events.jsonl). */
119
+ audit(event: Record<string, unknown>): void;
120
+ now(): number;
121
+ }
122
+ export interface ReleaseReadinessSentinelConfig {
123
+ enabled?: boolean;
124
+ tickIntervalMs?: number;
125
+ backlogAgeDaysSilent?: number;
126
+ backlogAgeDaysLow?: number;
127
+ backlogAgeDaysMedium?: number;
128
+ backlogAgeDaysHigh?: number;
129
+ hysteresisHours?: number;
130
+ staleEpisodeTtlDays?: number;
131
+ }
132
+ export declare class ReleaseReadinessSentinel extends EventEmitter {
133
+ private readonly deps;
134
+ private readonly cfg;
135
+ private tickHandle;
136
+ constructor(deps: ReleaseReadinessSentinelDeps, cfg?: ReleaseReadinessSentinelConfig);
137
+ start(): void;
138
+ stop(): void;
139
+ /** Priority for a given backlog age, or null when below the silent threshold. */
140
+ priorityForAge(ageDays: number): ReadinessPriority | null;
141
+ /** The cron entry point. Top-level catch converts any error into a loud signal. */
142
+ tick(): Promise<void>;
143
+ /** Read-only snapshot of current state (for GET /release-readiness). */
144
+ snapshot(): ReadinessState;
145
+ /**
146
+ * Runtime kill-switch (POST /release-readiness/rollback). Disables future
147
+ * ticks, resolves all open Attention items, and is ITSELF loud — raises a
148
+ * HIGH-priority Attention item + audits — so the rollback can never be a
149
+ * silent way to mute the alarm (iter-3 Adversarial V5).
150
+ */
151
+ rollback(meta?: {
152
+ sessionId?: string;
153
+ sourceIp?: string;
154
+ }): Promise<void>;
155
+ /** Re-arm after a rollback. */
156
+ enable(): void;
157
+ private evaluate;
158
+ private isBlocked;
159
+ private raiseGapOnly;
160
+ private failLoud;
161
+ private resolveAll;
162
+ /**
163
+ * Called by the publish-finalize path (and the /rollback route via 'rolled-back').
164
+ * Resolves every open episode whose oldestSha is an ancestor of newTagSha —
165
+ * correct even when the oldest-unreleased SHA churned during the open window.
166
+ */
167
+ resolveEpisodesInRange(newTagSha: string, reason?: ReadinessEpisode['resolvedReason']): Promise<void>;
168
+ /** TTL-reap episodes/resolves so state doesn't grow unbounded. */
169
+ private reap;
170
+ static emptyState(): ReadinessState;
171
+ }
172
+ //# sourceMappingURL=ReleaseReadinessSentinel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReleaseReadinessSentinel.d.ts","sourceRoot":"","sources":["../../src/monitoring/ReleaseReadinessSentinel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,uEAAuE;AACvE,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE;QACR,oBAAoB,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAC3D,CAAC;IACF,aAAa,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3D;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,WAAW,GAAG,OAAO,GAAG,aAAa,GAAG,SAAS,CAAC;CACpE;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,4EAA4E;IAC5E,cAAc,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjE,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC;kFAC8E;IAC9E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjG;AAED,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE1D,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,4BAA4B;IAC3C,4EAA4E;IAC5E,cAAc,IAAI,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7D,mFAAmF;IACnF,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACzD,qEAAqE;IACrE,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IACnF,uFAAuF;IACvF,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,gFAAgF;IAChF,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,4DAA4D;IAC5D,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrD,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/D,qDAAqD;IACrD,SAAS,IAAI,cAAc,CAAC;IAC5B,gCAAgC;IAChC,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IACvC,kEAAkE;IAClE,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvD,8DAA8D;IAC9D,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5C,GAAG,IAAI,MAAM,CAAC;CACf;AAED,MAAM,WAAW,8BAA8B;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAgBD,qBAAa,wBAAyB,SAAQ,YAAY;IAKtD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJvB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA2C;IAC/D,OAAO,CAAC,UAAU,CAA+C;gBAG9C,IAAI,EAAE,4BAA4B,EACnD,GAAG,GAAE,8BAAmC;IAM1C,KAAK,IAAI,IAAI;IAQb,IAAI,IAAI,IAAI;IAOZ,iFAAiF;IACjF,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI;IAOzD,mFAAmF;IAC7E,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB3B,wEAAwE;IACxE,QAAQ,IAAI,cAAc;IAI1B;;;;;OAKG;IACG,QAAQ,CAAC,IAAI,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBnF,+BAA+B;IAC/B,MAAM,IAAI,IAAI;YAOA,QAAQ;IAsFtB,OAAO,CAAC,SAAS;YAQH,YAAY;YAuBZ,QAAQ;YAgBR,UAAU;IAWxB;;;;OAIG;IACG,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,GAAE,gBAAgB,CAAC,gBAAgB,CAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBxH,kEAAkE;IAClE,OAAO,CAAC,IAAI;IAmBZ,MAAM,CAAC,UAAU,IAAI,cAAc;CAGpC"}
@@ -0,0 +1,315 @@
1
+ /**
2
+ * ReleaseReadinessSentinel — Layer B of the release-readiness-visibility spec.
3
+ *
4
+ * Watches whether a release is blocked/stalling and makes it impossible to miss.
5
+ * The original incident (2026-05-27): npm publishing silently stalled since
6
+ * v1.3.26 — green merges, green CI, no published release, no alert. The publish
7
+ * workflow's NEXT.md gate is a *silent skip*: a stalled release is
8
+ * indistinguishable from "nothing to publish". This sentinel is the missing
9
+ * visibility — a recurring, near-silent check that surfaces a stuck release as
10
+ * a single, deduped, escalating Attention item.
11
+ *
12
+ * Design (spec §4.2):
13
+ * - Reads canonical `main` (FETCH_HEAD), not the local checkout, so a stale
14
+ * dev branch can't produce a false "all clear".
15
+ * - "Blocked" is decoupled from NEXT.md state (so Layer A's auto-draft can't
16
+ * silence the alarm by clearing the file): unreleased feature/fix commits
17
+ * exist AND the guide can't publish (missing/template/unreviewed), OR the
18
+ * analyzer reports critical/high coverage gaps.
19
+ * - Near-silent: silent below threshold (state + log only); ONE Attention
20
+ * item per stall episode above it, keyed on the OLDEST unreleased commit
21
+ * SHA (stable across ticks — not a resettable per-tick id), priority scaled
22
+ * by backlog age, 12h hysteresis on re-raise after an auto-resolve.
23
+ * - Fail-loud: any evaluation failure (fetch error, analyzer error) raises a
24
+ * low-priority Attention item — never a silent catch (that would re-create
25
+ * the exact bug this fixes).
26
+ * - Lifecycle owner: detect → surface → auto-resolve → reap, with
27
+ * resolveEpisodesInRange consulted by the publish-finalize path.
28
+ * - Repo-gated: needs an analyzable instar git repo (dev/maintainer env). On
29
+ * an npm-installed agent with no such repo the deps make the check inert.
30
+ * - Supervision: Tier 0 (mechanical computation + fixed-template wording).
31
+ */
32
+ import { EventEmitter } from 'node:events';
33
+ const DEFAULTS = {
34
+ enabled: false,
35
+ tickIntervalMs: 6 * 60 * 60 * 1000, // 6h
36
+ backlogAgeDaysSilent: 2,
37
+ backlogAgeDaysLow: 2,
38
+ backlogAgeDaysMedium: 4,
39
+ backlogAgeDaysHigh: 7,
40
+ hysteresisHours: 12,
41
+ staleEpisodeTtlDays: 30,
42
+ };
43
+ const DAY_MS = 24 * 60 * 60 * 1000;
44
+ const HOUR_MS = 60 * 60 * 1000;
45
+ export class ReleaseReadinessSentinel extends EventEmitter {
46
+ deps;
47
+ cfg;
48
+ tickHandle = null;
49
+ constructor(deps, cfg = {}) {
50
+ super();
51
+ this.deps = deps;
52
+ this.cfg = { ...DEFAULTS, ...cfg };
53
+ }
54
+ start() {
55
+ if (!this.cfg.enabled || this.tickHandle)
56
+ return;
57
+ this.tickHandle = setInterval(() => {
58
+ void this.tick();
59
+ }, this.cfg.tickIntervalMs);
60
+ if (typeof this.tickHandle.unref === 'function')
61
+ this.tickHandle.unref();
62
+ }
63
+ stop() {
64
+ if (this.tickHandle) {
65
+ clearInterval(this.tickHandle);
66
+ this.tickHandle = null;
67
+ }
68
+ }
69
+ /** Priority for a given backlog age, or null when below the silent threshold. */
70
+ priorityForAge(ageDays) {
71
+ if (ageDays >= this.cfg.backlogAgeDaysHigh)
72
+ return 'HIGH';
73
+ if (ageDays >= this.cfg.backlogAgeDaysMedium)
74
+ return 'MEDIUM';
75
+ if (ageDays >= this.cfg.backlogAgeDaysLow)
76
+ return 'LOW';
77
+ return null;
78
+ }
79
+ /** The cron entry point. Top-level catch converts any error into a loud signal. */
80
+ async tick() {
81
+ const state = this.deps.loadState();
82
+ state.lastTickAt = this.deps.now();
83
+ if (state.disabled) {
84
+ this.deps.audit({ kind: 'release-readiness', event: 'tick-skipped-disabled' });
85
+ this.deps.saveState(state);
86
+ return;
87
+ }
88
+ try {
89
+ await this.evaluate(state);
90
+ this.deps.saveState(state);
91
+ }
92
+ catch (err) {
93
+ // Fail-loud — a silent catch here would re-create the very silent-failure
94
+ // bug this sentinel exists to fix.
95
+ await this.failLoud(state, 'tick', err);
96
+ this.deps.saveState(state);
97
+ }
98
+ }
99
+ /** Read-only snapshot of current state (for GET /release-readiness). */
100
+ snapshot() {
101
+ return this.deps.loadState();
102
+ }
103
+ /**
104
+ * Runtime kill-switch (POST /release-readiness/rollback). Disables future
105
+ * ticks, resolves all open Attention items, and is ITSELF loud — raises a
106
+ * HIGH-priority Attention item + audits — so the rollback can never be a
107
+ * silent way to mute the alarm (iter-3 Adversarial V5).
108
+ */
109
+ async rollback(meta = {}) {
110
+ const state = this.deps.loadState();
111
+ state.disabled = true;
112
+ await this.resolveAll(state, 'rolled-back');
113
+ state.rollbackHistory ??= [];
114
+ state.rollbackHistory.push({ ts: this.deps.now(), sessionId: meta.sessionId, sourceIp: meta.sourceIp, reason: 'rollback' });
115
+ this.deps.audit({ kind: 'release-readiness', event: 'rollback', sessionId: meta.sessionId, sourceIp: meta.sourceIp });
116
+ await this.deps.postAttention({
117
+ id: 'release-readiness-rolled-back',
118
+ title: 'Release-readiness alarm disabled',
119
+ summary: `The release-readiness watchdog was disabled via /release-readiness/rollback${meta.sessionId ? ` by session ${meta.sessionId}` : ''} at ${new Date(this.deps.now()).toISOString()}. Re-enable via POST /release-readiness/enable.`,
120
+ category: 'degradation',
121
+ priority: 'HIGH',
122
+ });
123
+ this.deps.saveState(state);
124
+ }
125
+ /** Re-arm after a rollback. */
126
+ enable() {
127
+ const state = this.deps.loadState();
128
+ state.disabled = false;
129
+ this.deps.audit({ kind: 'release-readiness', event: 'enabled' });
130
+ this.deps.saveState(state);
131
+ }
132
+ async evaluate(state) {
133
+ const fetched = await this.deps.fetchCanonical();
134
+ if (!fetched.ok) {
135
+ await this.failLoud(state, 'fetch', new Error('canonical ref unreachable'));
136
+ return;
137
+ }
138
+ state.cacheHeadSha = fetched.headSha;
139
+ const ref = fetched.headSha ?? 'FETCH_HEAD';
140
+ // Keep NEXT.md seeded (Layer A). Best-effort: a draft failure is not a
141
+ // readiness failure.
142
+ try {
143
+ await this.deps.draftGuide(ref);
144
+ }
145
+ catch {
146
+ /* draft is advisory; the readiness signal below is what matters */
147
+ }
148
+ const report = await this.deps.runAnalyzer(ref);
149
+ if (!report) {
150
+ await this.failLoud(state, 'analyzer', new Error('analyze-release returned no report'));
151
+ return;
152
+ }
153
+ const blocked = this.isBlocked(report, await this.deps.guideBlocksPublish());
154
+ if (!blocked) {
155
+ // Backlog clear — resolve any open episodes.
156
+ await this.resolveAll(state, 'cleared');
157
+ // A successful evaluation clears any prior fail-loud episode.
158
+ state.lastFailureKey = undefined;
159
+ this.reap(state);
160
+ return;
161
+ }
162
+ const oldest = await this.deps.oldestUnreleasedCommit(report.lastTag, ref);
163
+ if (!oldest) {
164
+ // Blocked by coverage gaps but no datable commit — surface at LOW.
165
+ await this.raiseGapOnly(state, report);
166
+ this.reap(state);
167
+ return;
168
+ }
169
+ const ageDays = (this.deps.now() - oldest.dateMs) / DAY_MS;
170
+ const priority = this.priorityForAge(ageDays);
171
+ let episode = state.episodes.find((e) => e.oldestSha === oldest.sha && !e.resolvedMs);
172
+ if (!episode) {
173
+ episode = { oldestSha: oldest.sha, firstDetectedMs: this.deps.now() };
174
+ state.episodes.push(episode);
175
+ }
176
+ if (!priority) {
177
+ // Below the silent threshold — recorded, no message.
178
+ this.reap(state);
179
+ return;
180
+ }
181
+ // Hysteresis: don't re-raise the same sha within the window of a recent resolve.
182
+ const recent = state.recentResolves.find((r) => r.oldestSha === oldest.sha);
183
+ if (recent && this.deps.now() - recent.resolvedMs < this.cfg.hysteresisHours * HOUR_MS && !episode.openedMs) {
184
+ this.reap(state);
185
+ return;
186
+ }
187
+ if (!episode.openedMs || episode.lastPriority !== priority) {
188
+ const id = episode.attentionId ?? `release-readiness-${oldest.sha.slice(0, 12)}`;
189
+ const days = Math.floor(ageDays);
190
+ const delivered = await this.deps.postAttention({
191
+ id,
192
+ title: 'Release blocked — unreleased work is piling up',
193
+ summary: `${report.analysis.commitClassification.features + report.analysis.commitClassification.fixes} ` +
194
+ `unreleased feature/fix commit(s) since ${report.lastTag}; oldest is ${days} day(s) old and publishing is blocked ` +
195
+ `(NEXT.md needs review/coverage). Oldest commit ${oldest.sha.slice(0, 12)}.`,
196
+ category: 'degradation',
197
+ priority,
198
+ });
199
+ episode.openedMs = episode.openedMs ?? this.deps.now();
200
+ episode.attentionId = id;
201
+ episode.lastPriority = priority;
202
+ state.lastSignalAt = this.deps.now();
203
+ this.deps.audit({ kind: 'release-readiness', event: 'signal', oldestSha: oldest.sha, priority, ageDays: days, delivered });
204
+ this.emit('signal', { oldestSha: oldest.sha, priority });
205
+ }
206
+ this.reap(state);
207
+ }
208
+ isBlocked(report, guideBlocks) {
209
+ const featureOrFix = report.analysis.commitClassification.features + report.analysis.commitClassification.fixes;
210
+ const backlogBlocked = featureOrFix > 0 && guideBlocks;
211
+ const coverageBlocked = report.guideCoverage.criticalGaps + report.guideCoverage.highGaps > 0;
212
+ return backlogBlocked || coverageBlocked;
213
+ }
214
+ async raiseGapOnly(state, report) {
215
+ const id = 'release-readiness-coverage-gaps';
216
+ let episode = state.episodes.find((e) => e.oldestSha === id && !e.resolvedMs);
217
+ if (!episode) {
218
+ episode = { oldestSha: id, firstDetectedMs: this.deps.now() };
219
+ state.episodes.push(episode);
220
+ }
221
+ if (!episode.openedMs) {
222
+ const delivered = await this.deps.postAttention({
223
+ id,
224
+ title: 'Release blocked — upgrade-guide coverage gaps',
225
+ summary: `analyze-release reports ${report.guideCoverage.criticalGaps + report.guideCoverage.highGaps} critical/high coverage gap(s) in the upgrade guide. Publishing is blocked until they are addressed.`,
226
+ category: 'degradation',
227
+ priority: 'LOW',
228
+ });
229
+ episode.openedMs = this.deps.now();
230
+ episode.attentionId = id;
231
+ episode.lastPriority = 'LOW';
232
+ state.lastSignalAt = this.deps.now();
233
+ this.deps.audit({ kind: 'release-readiness', event: 'signal-gaps', delivered });
234
+ }
235
+ }
236
+ async failLoud(state, stage, err) {
237
+ const key = `failure:${stage}`;
238
+ this.deps.audit({ kind: 'release-readiness', event: 'eval-failed', stage, error: String(err) });
239
+ if (state.lastFailureKey === key)
240
+ return; // dedupe per failure episode
241
+ state.lastFailureKey = key;
242
+ await this.deps.postAttention({
243
+ id: `release-readiness-eval-failure-${stage}`,
244
+ title: 'Release-readiness check could not evaluate',
245
+ summary: `The release-readiness check failed at the "${stage}" stage: ${String(err)}. Last evaluated ${state.lastSignalAt ? new Date(state.lastSignalAt).toISOString() : 'never'}.`,
246
+ category: 'degradation',
247
+ priority: 'LOW',
248
+ });
249
+ state.lastSignalAt = this.deps.now();
250
+ this.emit('eval-failed', { stage });
251
+ }
252
+ async resolveAll(state, reason) {
253
+ for (const e of state.episodes) {
254
+ if (e.resolvedMs)
255
+ continue;
256
+ if (e.attentionId)
257
+ await this.deps.resolveAttention(e.attentionId, reason ?? 'cleared');
258
+ e.resolvedMs = this.deps.now();
259
+ e.resolvedReason = reason;
260
+ state.recentResolves.push({ oldestSha: e.oldestSha, resolvedMs: this.deps.now() });
261
+ this.deps.audit({ kind: 'release-readiness', event: 'resolved', oldestSha: e.oldestSha, reason });
262
+ }
263
+ }
264
+ /**
265
+ * Called by the publish-finalize path (and the /rollback route via 'rolled-back').
266
+ * Resolves every open episode whose oldestSha is an ancestor of newTagSha —
267
+ * correct even when the oldest-unreleased SHA churned during the open window.
268
+ */
269
+ async resolveEpisodesInRange(newTagSha, reason = 'published') {
270
+ const state = this.deps.loadState();
271
+ let changed = false;
272
+ for (const e of state.episodes) {
273
+ if (e.resolvedMs)
274
+ continue;
275
+ if (e.oldestSha.startsWith('release-readiness-'))
276
+ continue; // synthetic (gap) episodes
277
+ const ancestor = await this.deps.isAncestor(e.oldestSha, newTagSha);
278
+ if (ancestor) {
279
+ if (e.attentionId)
280
+ await this.deps.resolveAttention(e.attentionId, reason ?? 'published');
281
+ e.resolvedMs = this.deps.now();
282
+ e.resolvedReason = reason;
283
+ state.recentResolves.push({ oldestSha: e.oldestSha, resolvedMs: this.deps.now() });
284
+ this.deps.audit({ kind: 'release-readiness', event: 'resolved-in-range', oldestSha: e.oldestSha, newTagSha, reason });
285
+ changed = true;
286
+ }
287
+ }
288
+ if (changed)
289
+ this.deps.saveState(state);
290
+ }
291
+ /** TTL-reap episodes/resolves so state doesn't grow unbounded. */
292
+ reap(state) {
293
+ const ttl = this.cfg.staleEpisodeTtlDays * DAY_MS;
294
+ const now = this.deps.now();
295
+ for (const e of state.episodes) {
296
+ if (!e.resolvedMs && now - e.firstDetectedMs > ttl) {
297
+ // Backlog vanished without a finalize (e.g. branch abandoned) — reap loudly.
298
+ e.resolvedMs = now;
299
+ e.resolvedReason = 'stale';
300
+ if (e.attentionId)
301
+ void this.deps.resolveAttention(e.attentionId, 'stale');
302
+ this.deps.audit({ kind: 'release-readiness', event: 'reaped-stale', oldestSha: e.oldestSha });
303
+ }
304
+ }
305
+ state.episodes = state.episodes.filter((e) => !e.resolvedMs || now - (e.resolvedMs ?? 0) < ttl);
306
+ state.recentResolves = state.recentResolves.filter((r) => now - r.resolvedMs < this.cfg.hysteresisHours * HOUR_MS * 2);
307
+ if ((state.rollbackHistory?.length ?? 0) > 50) {
308
+ state.rollbackHistory = state.rollbackHistory.slice(-50);
309
+ }
310
+ }
311
+ static emptyState() {
312
+ return { episodes: [], recentResolves: [] };
313
+ }
314
+ }
315
+ //# sourceMappingURL=ReleaseReadinessSentinel.js.map