instar 1.3.337 → 1.3.339

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.
@@ -0,0 +1,40 @@
1
+ /**
2
+ * LearningVelocityScorer — EXO 3.0's KPI inversion (Salim Ismail, "Your KPI
3
+ * System Is Training You to Miss the Future").
4
+ *
5
+ * Backward-looking operational KPIs (throughput, utilization, efficiency) reward
6
+ * the existing model and suppress the weak signals where the future shows up.
7
+ * EXO 3.0 says measure **learning velocity** instead — adaptability,
8
+ * experimentation, capability creation. Instar already emits the raw learning
9
+ * events (registered learnings, Playbook items added, corrections captured,
10
+ * evolution actions); this scorer turns them into a velocity + trend + diversity
11
+ * signal so an org can watch how fast it's *learning*, not just how much it's
12
+ * *producing*.
13
+ *
14
+ * Pure + deterministic so it's testable and reproducible. The route gathers the
15
+ * real events; this computes the metric.
16
+ */
17
+ export interface LearningEvent {
18
+ /** ISO timestamp of the learning event. */
19
+ timestamp: string;
20
+ /** Category: 'learning' | 'playbook' | 'correction' | 'evolution' | 'memory' | string. */
21
+ type: string;
22
+ }
23
+ export type VelocityTrend = 'accelerating' | 'steady' | 'declining' | 'insufficient-data';
24
+ export interface LearningVelocityResult {
25
+ windowDays: number;
26
+ totalEvents: number;
27
+ /** Events per day across the window. */
28
+ eventsPerDay: number;
29
+ /** Count by event type. */
30
+ byType: Record<string, number>;
31
+ /** Distinct learning categories seen (a diversity proxy). */
32
+ typeDiversity: number;
33
+ /** First-half vs second-half comparison of the window. */
34
+ trend: VelocityTrend;
35
+ /** 0–100, blends velocity (capped) and category diversity. */
36
+ adaptabilityScore: number;
37
+ reason: string;
38
+ }
39
+ export declare function computeLearningVelocity(events: LearningEvent[], nowIso: string, windowDays?: number): LearningVelocityResult;
40
+ //# sourceMappingURL=LearningVelocityScorer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LearningVelocityScorer.d.ts","sourceRoot":"","sources":["../../src/core/LearningVelocityScorer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,0FAA0F;IAC1F,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,QAAQ,GAAG,WAAW,GAAG,mBAAmB,CAAC;AAE1F,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,6DAA6D;IAC7D,aAAa,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,KAAK,EAAE,aAAa,CAAC;IACrB,8DAA8D;IAC9D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB;AAWD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,aAAa,EAAE,EACvB,MAAM,EAAE,MAAM,EACd,UAAU,SAAK,GACd,sBAAsB,CA8CxB"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * LearningVelocityScorer — EXO 3.0's KPI inversion (Salim Ismail, "Your KPI
3
+ * System Is Training You to Miss the Future").
4
+ *
5
+ * Backward-looking operational KPIs (throughput, utilization, efficiency) reward
6
+ * the existing model and suppress the weak signals where the future shows up.
7
+ * EXO 3.0 says measure **learning velocity** instead — adaptability,
8
+ * experimentation, capability creation. Instar already emits the raw learning
9
+ * events (registered learnings, Playbook items added, corrections captured,
10
+ * evolution actions); this scorer turns them into a velocity + trend + diversity
11
+ * signal so an org can watch how fast it's *learning*, not just how much it's
12
+ * *producing*.
13
+ *
14
+ * Pure + deterministic so it's testable and reproducible. The route gathers the
15
+ * real events; this computes the metric.
16
+ */
17
+ // ── Tunables ─────────────────────────────────────────────────────────
18
+ const MIN_EVENTS_FOR_TREND = 4;
19
+ /** events/day at which the velocity component saturates to 100. */
20
+ const VELOCITY_SATURATION = 3;
21
+ const KNOWN_TYPES = ['learning', 'playbook', 'correction', 'evolution', 'memory'];
22
+ // ── Public API ───────────────────────────────────────────────────────
23
+ export function computeLearningVelocity(events, nowIso, windowDays = 30) {
24
+ const now = Date.parse(nowIso);
25
+ const windowMs = windowDays * 24 * 60 * 60 * 1000;
26
+ const cutoff = now - windowMs;
27
+ const midpoint = now - windowMs / 2;
28
+ const inWindow = events.filter((e) => {
29
+ const t = Date.parse(e.timestamp);
30
+ return !Number.isNaN(t) && t >= cutoff && t <= now;
31
+ });
32
+ const byType = {};
33
+ let firstHalf = 0;
34
+ let secondHalf = 0;
35
+ for (const e of inWindow) {
36
+ byType[e.type] = (byType[e.type] ?? 0) + 1;
37
+ if (Date.parse(e.timestamp) >= midpoint)
38
+ secondHalf++;
39
+ else
40
+ firstHalf++;
41
+ }
42
+ const totalEvents = inWindow.length;
43
+ const eventsPerDay = windowDays > 0 ? totalEvents / windowDays : 0;
44
+ const typeDiversity = Object.keys(byType).length;
45
+ let trend;
46
+ if (totalEvents < MIN_EVENTS_FOR_TREND) {
47
+ trend = 'insufficient-data';
48
+ }
49
+ else if (secondHalf > firstHalf * 1.2) {
50
+ trend = 'accelerating';
51
+ }
52
+ else if (secondHalf < firstHalf * 0.8) {
53
+ trend = 'declining';
54
+ }
55
+ else {
56
+ trend = 'steady';
57
+ }
58
+ // Adaptability: 70% velocity (saturating) + 30% category diversity.
59
+ const velocityComponent = Math.min(1, eventsPerDay / VELOCITY_SATURATION);
60
+ const diversityComponent = Math.min(1, typeDiversity / KNOWN_TYPES.length);
61
+ const adaptabilityScore = Math.round((velocityComponent * 0.7 + diversityComponent * 0.3) * 100);
62
+ const reason = totalEvents === 0
63
+ ? `No learning events in the last ${windowDays} days — the org may be optimizing the old model rather than learning. (This metric is the EXO 3.0 antidote to backward-looking KPIs.)`
64
+ : `${totalEvents} learning event(s) over ${windowDays}d (${eventsPerDay.toFixed(2)}/day) across ${typeDiversity} categor${typeDiversity === 1 ? 'y' : 'ies'}; trend ${trend}. Adaptability ${adaptabilityScore}/100.`;
65
+ return { windowDays, totalEvents, eventsPerDay, byType, typeDiversity, trend, adaptabilityScore, reason };
66
+ }
67
+ //# sourceMappingURL=LearningVelocityScorer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LearningVelocityScorer.js","sourceRoot":"","sources":["../../src/core/LearningVelocityScorer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA6BH,wEAAwE;AAExE,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAC/B,mEAAmE;AACnE,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAC9B,MAAM,WAAW,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;AAElF,wEAAwE;AAExE,MAAM,UAAU,uBAAuB,CACrC,MAAuB,EACvB,MAAc,EACd,UAAU,GAAG,EAAE;IAEf,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,MAAM,QAAQ,GAAG,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAClD,MAAM,MAAM,GAAG,GAAG,GAAG,QAAQ,CAAC;IAC9B,MAAM,QAAQ,GAAG,GAAG,GAAG,QAAQ,GAAG,CAAC,CAAC;IAEpC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QACnC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,GAAG,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC3C,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,QAAQ;YAAE,UAAU,EAAE,CAAC;;YACjD,SAAS,EAAE,CAAC;IACnB,CAAC;IAED,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC;IACpC,MAAM,YAAY,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;IAEjD,IAAI,KAAoB,CAAC;IACzB,IAAI,WAAW,GAAG,oBAAoB,EAAE,CAAC;QACvC,KAAK,GAAG,mBAAmB,CAAC;IAC9B,CAAC;SAAM,IAAI,UAAU,GAAG,SAAS,GAAG,GAAG,EAAE,CAAC;QACxC,KAAK,GAAG,cAAc,CAAC;IACzB,CAAC;SAAM,IAAI,UAAU,GAAG,SAAS,GAAG,GAAG,EAAE,CAAC;QACxC,KAAK,GAAG,WAAW,CAAC;IACtB,CAAC;SAAM,CAAC;QACN,KAAK,GAAG,QAAQ,CAAC;IACnB,CAAC;IAED,oEAAoE;IACpE,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,GAAG,mBAAmB,CAAC,CAAC;IAC1E,MAAM,kBAAkB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3E,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,iBAAiB,GAAG,GAAG,GAAG,kBAAkB,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;IAEjG,MAAM,MAAM,GACV,WAAW,KAAK,CAAC;QACf,CAAC,CAAC,kCAAkC,UAAU,uIAAuI;QACrL,CAAC,CAAC,GAAG,WAAW,2BAA2B,UAAU,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,aAAa,WAAW,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,WAAW,KAAK,kBAAkB,iBAAiB,OAAO,CAAC;IAE1N,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,CAAC;AAC5G,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * OwnerSuspectBreaker — the per-peer circuit breaker behind the SessionRouter's
3
+ * `markOwnerSuspect` hook ("No Unbounded Loops" / P19).
4
+ *
5
+ * The router's forward path already had the SHAPE of a breaker: on delivery
6
+ * retry exhaustion it calls `markOwnerSuspect(owner)` before re-placing the
7
+ * message. But the hook was NEVER WIRED in production (the dep is optional and
8
+ * no implementation existed) — "constructed but inert". The consequence: every
9
+ * session owned by a slow-or-dead peer independently re-paid the full retry
10
+ * tax (3 attempts × backoff ≈ 4.5s+) per message, because `isMachineAlive`
11
+ * reads only capacity heartbeats, which a slow-but-alive peer keeps passing.
12
+ *
13
+ * This class is the wiring's missing half. Half-open TTL semantics:
14
+ *
15
+ * markSuspect(peer) — start/extend a suspect window (default 30s). The
16
+ * FIRST mark of an episode logs once; an episode
17
+ * sustained past signalAfterMs raises ONE degradation
18
+ * signal (per-peer FailureEpisodeLatch — P19 cond. 4).
19
+ * isSuspect(peer) — true inside the window. The composed isMachineAlive
20
+ * then short-circuits dispatches for ALL of that
21
+ * peer's sessions straight to the existing failover
22
+ * re-place path — no per-message retry tax repaid.
23
+ * recordSuccess(peer) — a delivery reached the peer: window cleared,
24
+ * recovery logged once, latch re-armed.
25
+ *
26
+ * After the TTL expires the breaker is HALF-OPEN: the next message tries the
27
+ * peer for real (paying one retry cycle); success clears, failure re-marks.
28
+ * The peer is never written off permanently — the TTL is the backoff, the
29
+ * suspect state is the breaker, the per-message retry config is the cap.
30
+ *
31
+ * Deliberately POLICY-NEUTRAL: what happens to messages while a peer is
32
+ * suspect (today: the router's existing re-place path) is the wiring's choice
33
+ * — the queue-vs-replace stability policy is a separate operator decision
34
+ * <!-- tracked: CMT-1109 -->. Pure: injectable clock, per-peer bounded state.
35
+ */
36
+ export interface OwnerSuspectBreakerOpts {
37
+ /** Suspect window per mark (the half-open backoff). Default 30s. */
38
+ suspectTtlMs?: number;
39
+ /** Sustained-suspicion threshold for the one-per-episode degradation signal. Default 10min. */
40
+ signalAfterMs?: number;
41
+ now?: () => number;
42
+ logger?: (msg: string) => void;
43
+ /** One-per-episode sustained-suspicion sink (wired to DegradationReporter). */
44
+ reportSustained?: (info: {
45
+ machineId: string;
46
+ suspectForMs: number;
47
+ marks: number;
48
+ }) => void;
49
+ }
50
+ export declare class OwnerSuspectBreaker {
51
+ private readonly ttlMs;
52
+ private readonly now;
53
+ private readonly opts;
54
+ /** Per-peer suspect-window end (ms epoch). Deleted on success. */
55
+ private suspectUntil;
56
+ /** Per-peer episode accounting (created on first mark, deleted on success). */
57
+ private episodes;
58
+ constructor(opts?: OwnerSuspectBreakerOpts);
59
+ private log;
60
+ /** Delivery retries to this peer exhausted — open its suspect window.
61
+ *
62
+ * ABSOLUTE per-episode TTL: a mark that arrives while a window is ALREADY open
63
+ * does NOT push the window end forward. Otherwise a steady message stream
64
+ * arriving faster than the TTL would re-extend the window on every dispatch
65
+ * (each suspect dispatch re-enters dispatchOne's dead-owner branch, which
66
+ * re-calls markOwnerSuspect), so `isSuspect` would never go false at the
67
+ * moment a message arrives — the half-open re-probe (the ONLY path that ever
68
+ * re-attempts delivery and thus the ONLY path that can clear suspicion) would
69
+ * never be reached, leaving a fully-RECOVERED peer suspect forever and
70
+ * force-failing-over all its sessions on every message. The episode latch
71
+ * still records each mark (sustained-suspicion accounting), but the window
72
+ * end is fixed at the first mark of each TTL period. */
73
+ markSuspect(machineId: string): void;
74
+ /** Inside an open suspect window? (Half-open after the TTL — callers re-probe.) */
75
+ isSuspect(machineId: string): boolean;
76
+ /** A delivery reached the peer — close the episode and re-arm. */
77
+ recordSuccess(machineId: string): void;
78
+ }
79
+ //# sourceMappingURL=OwnerSuspectBreaker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OwnerSuspectBreaker.d.ts","sourceRoot":"","sources":["../../src/core/OwnerSuspectBreaker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAIH,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+FAA+F;IAC/F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,+EAA+E;IAC/E,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAC9F;AAKD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0B;IAC/C,kEAAkE;IAClE,OAAO,CAAC,YAAY,CAA6B;IACjD,+EAA+E;IAC/E,OAAO,CAAC,QAAQ,CAA0C;gBAE9C,IAAI,GAAE,uBAA4B;IAM9C,OAAO,CAAC,GAAG;IAIX;;;;;;;;;;;;4DAYwD;IACxD,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAsBpC,mFAAmF;IACnF,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAKrC,kEAAkE;IAClE,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;CASvC"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * OwnerSuspectBreaker — the per-peer circuit breaker behind the SessionRouter's
3
+ * `markOwnerSuspect` hook ("No Unbounded Loops" / P19).
4
+ *
5
+ * The router's forward path already had the SHAPE of a breaker: on delivery
6
+ * retry exhaustion it calls `markOwnerSuspect(owner)` before re-placing the
7
+ * message. But the hook was NEVER WIRED in production (the dep is optional and
8
+ * no implementation existed) — "constructed but inert". The consequence: every
9
+ * session owned by a slow-or-dead peer independently re-paid the full retry
10
+ * tax (3 attempts × backoff ≈ 4.5s+) per message, because `isMachineAlive`
11
+ * reads only capacity heartbeats, which a slow-but-alive peer keeps passing.
12
+ *
13
+ * This class is the wiring's missing half. Half-open TTL semantics:
14
+ *
15
+ * markSuspect(peer) — start/extend a suspect window (default 30s). The
16
+ * FIRST mark of an episode logs once; an episode
17
+ * sustained past signalAfterMs raises ONE degradation
18
+ * signal (per-peer FailureEpisodeLatch — P19 cond. 4).
19
+ * isSuspect(peer) — true inside the window. The composed isMachineAlive
20
+ * then short-circuits dispatches for ALL of that
21
+ * peer's sessions straight to the existing failover
22
+ * re-place path — no per-message retry tax repaid.
23
+ * recordSuccess(peer) — a delivery reached the peer: window cleared,
24
+ * recovery logged once, latch re-armed.
25
+ *
26
+ * After the TTL expires the breaker is HALF-OPEN: the next message tries the
27
+ * peer for real (paying one retry cycle); success clears, failure re-marks.
28
+ * The peer is never written off permanently — the TTL is the backoff, the
29
+ * suspect state is the breaker, the per-message retry config is the cap.
30
+ *
31
+ * Deliberately POLICY-NEUTRAL: what happens to messages while a peer is
32
+ * suspect (today: the router's existing re-place path) is the wiring's choice
33
+ * — the queue-vs-replace stability policy is a separate operator decision
34
+ * <!-- tracked: CMT-1109 -->. Pure: injectable clock, per-peer bounded state.
35
+ */
36
+ import { FailureEpisodeLatch } from './FailureEpisodeLatch.js';
37
+ const DEFAULT_SUSPECT_TTL_MS = 30_000;
38
+ const DEFAULT_SIGNAL_AFTER_MS = 10 * 60_000;
39
+ export class OwnerSuspectBreaker {
40
+ ttlMs;
41
+ now;
42
+ opts;
43
+ /** Per-peer suspect-window end (ms epoch). Deleted on success. */
44
+ suspectUntil = new Map();
45
+ /** Per-peer episode accounting (created on first mark, deleted on success). */
46
+ episodes = new Map();
47
+ constructor(opts = {}) {
48
+ this.opts = opts;
49
+ this.ttlMs = opts.suspectTtlMs ?? DEFAULT_SUSPECT_TTL_MS;
50
+ this.now = opts.now ?? Date.now;
51
+ }
52
+ log(m) {
53
+ this.opts.logger?.(`[owner-suspect] ${m}`);
54
+ }
55
+ /** Delivery retries to this peer exhausted — open its suspect window.
56
+ *
57
+ * ABSOLUTE per-episode TTL: a mark that arrives while a window is ALREADY open
58
+ * does NOT push the window end forward. Otherwise a steady message stream
59
+ * arriving faster than the TTL would re-extend the window on every dispatch
60
+ * (each suspect dispatch re-enters dispatchOne's dead-owner branch, which
61
+ * re-calls markOwnerSuspect), so `isSuspect` would never go false at the
62
+ * moment a message arrives — the half-open re-probe (the ONLY path that ever
63
+ * re-attempts delivery and thus the ONLY path that can clear suspicion) would
64
+ * never be reached, leaving a fully-RECOVERED peer suspect forever and
65
+ * force-failing-over all its sessions on every message. The episode latch
66
+ * still records each mark (sustained-suspicion accounting), but the window
67
+ * end is fixed at the first mark of each TTL period. */
68
+ markSuspect(machineId) {
69
+ if (!this.isSuspect(machineId)) {
70
+ this.suspectUntil.set(machineId, this.now() + this.ttlMs);
71
+ }
72
+ let latch = this.episodes.get(machineId);
73
+ if (!latch) {
74
+ latch = new FailureEpisodeLatch({
75
+ signalAfterMs: this.opts.signalAfterMs ?? DEFAULT_SIGNAL_AFTER_MS,
76
+ now: this.now,
77
+ });
78
+ this.episodes.set(machineId, latch);
79
+ }
80
+ const f = latch.recordFailure();
81
+ if (f.firstOfEpisode) {
82
+ this.log(`owner ${machineId} SUSPECT (delivery retries exhausted) — short-circuiting its sessions' dispatches for ${Math.round(this.ttlMs / 1000)}s windows until a delivery succeeds`);
83
+ }
84
+ if (f.shouldSignal) {
85
+ this.log(`owner ${machineId} suspect for ${Math.round(f.failingForMs / 60_000)}min (${f.failures} marks) — signaling once; half-open re-probes continue`);
86
+ this.opts.reportSustained?.({ machineId, suspectForMs: f.failingForMs, marks: f.failures });
87
+ }
88
+ }
89
+ /** Inside an open suspect window? (Half-open after the TTL — callers re-probe.) */
90
+ isSuspect(machineId) {
91
+ const until = this.suspectUntil.get(machineId);
92
+ return until !== undefined && this.now() < until;
93
+ }
94
+ /** A delivery reached the peer — close the episode and re-arm. */
95
+ recordSuccess(machineId) {
96
+ this.suspectUntil.delete(machineId);
97
+ const latch = this.episodes.get(machineId);
98
+ if (latch) {
99
+ const s = latch.recordSuccess();
100
+ if (s.recovered)
101
+ this.log(`owner ${machineId} recovered after ${s.failures} suspect mark(s)`);
102
+ this.episodes.delete(machineId);
103
+ }
104
+ }
105
+ }
106
+ //# sourceMappingURL=OwnerSuspectBreaker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OwnerSuspectBreaker.js","sourceRoot":"","sources":["../../src/core/OwnerSuspectBreaker.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"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"}
@@ -2718,6 +2718,19 @@ Rule: I do not state that work landed inside another agent's state unless I have
2718
2718
  patched = true;
2719
2719
  result.upgraded.push('CLAUDE.md: added Session Boot Self-Knowledge section');
2720
2720
  }
2721
+ // Learning-Velocity Metric (EXO 3.0 G5): forward-looking learning KPI.
2722
+ // Existing agents need /metrics/learning-velocity awareness to answer
2723
+ // "are we actually learning?". Content-sniffed on a distinctive marker.
2724
+ if (!content.includes('Learning-Velocity Metric (EXO 3.0')) {
2725
+ const learningVelocitySection = `
2726
+ **Learning-Velocity Metric (EXO 3.0).** Measures how fast you're *learning* (adaptability, experimentation, capability creation) rather than backward-looking operational throughput — Salim Ismail's KPI inversion ("your KPIs are training you to miss the future"). Read-only.
2727
+ - \`curl -H "Authorization: Bearer $AUTH" "http://localhost:${port}/metrics/learning-velocity?windowDays=30"\` → \`{ totalEvents, eventsPerDay, byType, typeDiversity, trend (accelerating/steady/declining/insufficient-data), adaptabilityScore (0-100), reason }\`. Gathers your real learning events (registered learnings, corrections, evolution actions).
2728
+ - **When to use** (PROACTIVE): when asked "are we actually learning / adapting?", or to contrast learning velocity against operational metrics. A flat/declining trend means the org may be optimizing the old model instead of learning.
2729
+ `;
2730
+ content += '\n' + learningVelocitySection;
2731
+ patched = true;
2732
+ result.upgraded.push('CLAUDE.md: added Learning-Velocity Metric section');
2733
+ }
2721
2734
  // Agent-Readiness Scoring (EXO 3.0 G2): the coordination-vs-judgment
2722
2735
  // diagnostic. Existing agents need to know /agent-readiness/score exists
2723
2736
  // before delegating work. Content-sniffed on a distinctive marker.
@@ -4392,6 +4405,10 @@ Create worktrees for collaborator repos with \`instar worktree create <branch>\`
4392
4405
  // never learns /passport/verify can't check a peer's proposed action
4393
4406
  // against its passport before trusting it.
4394
4407
  '**Agent Digital Passport (EXO 3.0',
4408
+ // Learning-Velocity Metric (EXO 3.0 G5): the forward-looking learning
4409
+ // KPI. A Codex/Gemini agent that never learns /metrics/learning-velocity
4410
+ // can't answer "are we actually learning?" with real numbers.
4411
+ '**Learning-Velocity Metric (EXO 3.0',
4395
4412
  ];
4396
4413
  for (const shadowName of ['AGENTS.md', 'GEMINI.md']) {
4397
4414
  const shadowPath = path.join(this.config.projectDir, shadowName);