instar 1.3.586 → 1.3.588
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.
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +229 -39
- package/dist/commands/server.js.map +1 -1
- package/dist/core/IntelligenceRouter.d.ts +10 -0
- package/dist/core/IntelligenceRouter.d.ts.map +1 -1
- package/dist/core/IntelligenceRouter.js +37 -3
- package/dist/core/IntelligenceRouter.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +17 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/WorkEvidence.d.ts +17 -0
- package/dist/core/WorkEvidence.d.ts.map +1 -1
- package/dist/core/WorkEvidence.js +17 -0
- package/dist/core/WorkEvidence.js.map +1 -1
- package/dist/core/gapBCommitmentEvidence.d.ts +143 -0
- package/dist/core/gapBCommitmentEvidence.d.ts.map +1 -0
- package/dist/core/gapBCommitmentEvidence.js +138 -0
- package/dist/core/gapBCommitmentEvidence.js.map +1 -0
- package/dist/core/internalFrameworkDefault.d.ts +50 -0
- package/dist/core/internalFrameworkDefault.d.ts.map +1 -0
- package/dist/core/internalFrameworkDefault.js +72 -0
- package/dist/core/internalFrameworkDefault.js.map +1 -0
- package/dist/core/types.d.ts +39 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/CommitmentTracker.d.ts +12 -0
- package/dist/monitoring/CommitmentTracker.d.ts.map +1 -1
- package/dist/monitoring/CommitmentTracker.js +14 -0
- package/dist/monitoring/CommitmentTracker.js.map +1 -1
- package/dist/monitoring/ReapLog.d.ts +11 -0
- package/dist/monitoring/ReapLog.d.ts.map +1 -1
- package/dist/monitoring/ReapLog.js +1 -0
- package/dist/monitoring/ReapLog.js.map +1 -1
- package/dist/monitoring/ResumeQueueDrainer.d.ts +15 -0
- package/dist/monitoring/ResumeQueueDrainer.d.ts.map +1 -1
- package/dist/monitoring/ResumeQueueDrainer.js +12 -1
- package/dist/monitoring/ResumeQueueDrainer.js.map +1 -1
- package/dist/scaffold/templates.js +4 -4
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +19 -19
- package/src/scaffold/templates.ts +4 -4
- package/upgrades/1.3.587.md +28 -0
- package/upgrades/1.3.588.md +27 -0
- package/upgrades/side-effects/autonomous-registration-guarantee.md +51 -0
- package/upgrades/side-effects/provider-fallback-default-policy.md +52 -0
|
@@ -35,6 +35,23 @@ export declare const MARKER_WORK_EVIDENCE: readonly ["unverified-under-pressure"
|
|
|
35
35
|
* evidence-vocabulary string is here (imported by server.ts + ResumeQueueDrainer.ts).
|
|
36
36
|
*/
|
|
37
37
|
export declare const AGE_LIMIT_ACTIVE_RUN_REASON = "age-limit (active autonomous run)";
|
|
38
|
+
/**
|
|
39
|
+
* The reap-reason tag for an age-limit recycle whose topic has no per-topic
|
|
40
|
+
* autonomous-run state file (the run was never registered) BUT carries a fresh,
|
|
41
|
+
* qualifying open agent-commitment corroborated by a recent user message
|
|
42
|
+
* (spec: docs/specs/autonomous-registration-guarantee.md, GAP-B Part B). This is
|
|
43
|
+
* the BACKSTOP for an unregistered-but-actively-working autonomous run: the
|
|
44
|
+
* commitment is the independent live-work signal the state-file source cannot see.
|
|
45
|
+
*
|
|
46
|
+
* Parallel to AGE_LIMIT_ACTIVE_RUN_REASON (registered runs) so the drainer can
|
|
47
|
+
* route this candidate to its OWN drain-time liveness re-check
|
|
48
|
+
* (`commitmentStillActiveForTopic`) instead of the state-file read (which is
|
|
49
|
+
* absent here by construction). The reason is the provenance carrier — there is
|
|
50
|
+
* NO new WorkEvidence enum value (the strong `build-or-autonomous-active` signal
|
|
51
|
+
* is reused; the clamped WorkEvidenceName union is untouched). Imported by
|
|
52
|
+
* server.ts (injection) + ResumeQueueDrainer.ts (drain-time routing).
|
|
53
|
+
*/
|
|
54
|
+
export declare const COMMITMENT_ACTIVE_RUN_REASON = "age-limit (committed unregistered run)";
|
|
38
55
|
/**
|
|
39
56
|
* Closed-world predicate: is this resume-queue PAUSE reason a blunt
|
|
40
57
|
* emergency/sentinel stop that the drainer may auto-resume once it has gone
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkEvidence.d.ts","sourceRoot":"","sources":["../../src/core/WorkEvidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,eAAO,MAAM,oBAAoB,yJAavB,CAAC;AAEX,eAAO,MAAM,kBAAkB,0FAKrB,CAAC;AAEX,eAAO,MAAM,oBAAoB,wCAAyC,CAAC;AAE3E;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,2BAA2B,sCAAsC,CAAC;AAE/E;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mCAAmC,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAG9F;AAED,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AACvE,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AACnE,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AACvE,MAAM,MAAM,gBAAgB,GAAG,kBAAkB,GAAG,gBAAgB,GAAG,kBAAkB,CAAC;AAY1F;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,EAAE,CAYpE;AAED,gDAAgD;AAChD,wBAAgB,SAAS,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAE9D;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAE9E;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAE5E;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,UAAU,EAAE,OAAO,GAAG,OAAO,CAI1F"}
|
|
1
|
+
{"version":3,"file":"WorkEvidence.d.ts","sourceRoot":"","sources":["../../src/core/WorkEvidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,eAAO,MAAM,oBAAoB,yJAavB,CAAC;AAEX,eAAO,MAAM,kBAAkB,0FAKrB,CAAC;AAEX,eAAO,MAAM,oBAAoB,wCAAyC,CAAC;AAE3E;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,2BAA2B,sCAAsC,CAAC;AAE/E;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,4BAA4B,2CAA2C,CAAC;AAErF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mCAAmC,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAG9F;AAED,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AACvE,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AACnE,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AACvE,MAAM,MAAM,gBAAgB,GAAG,kBAAkB,GAAG,gBAAgB,GAAG,kBAAkB,CAAC;AAY1F;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,EAAE,CAYpE;AAED,gDAAgD;AAChD,wBAAgB,SAAS,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAE9D;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAE9E;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAE5E;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,UAAU,EAAE,OAAO,GAAG,OAAO,CAI1F"}
|
|
@@ -53,6 +53,23 @@ export const MARKER_WORK_EVIDENCE = ['unverified-under-pressure'];
|
|
|
53
53
|
* evidence-vocabulary string is here (imported by server.ts + ResumeQueueDrainer.ts).
|
|
54
54
|
*/
|
|
55
55
|
export const AGE_LIMIT_ACTIVE_RUN_REASON = 'age-limit (active autonomous run)';
|
|
56
|
+
/**
|
|
57
|
+
* The reap-reason tag for an age-limit recycle whose topic has no per-topic
|
|
58
|
+
* autonomous-run state file (the run was never registered) BUT carries a fresh,
|
|
59
|
+
* qualifying open agent-commitment corroborated by a recent user message
|
|
60
|
+
* (spec: docs/specs/autonomous-registration-guarantee.md, GAP-B Part B). This is
|
|
61
|
+
* the BACKSTOP for an unregistered-but-actively-working autonomous run: the
|
|
62
|
+
* commitment is the independent live-work signal the state-file source cannot see.
|
|
63
|
+
*
|
|
64
|
+
* Parallel to AGE_LIMIT_ACTIVE_RUN_REASON (registered runs) so the drainer can
|
|
65
|
+
* route this candidate to its OWN drain-time liveness re-check
|
|
66
|
+
* (`commitmentStillActiveForTopic`) instead of the state-file read (which is
|
|
67
|
+
* absent here by construction). The reason is the provenance carrier — there is
|
|
68
|
+
* NO new WorkEvidence enum value (the strong `build-or-autonomous-active` signal
|
|
69
|
+
* is reused; the clamped WorkEvidenceName union is untouched). Imported by
|
|
70
|
+
* server.ts (injection) + ResumeQueueDrainer.ts (drain-time routing).
|
|
71
|
+
*/
|
|
72
|
+
export const COMMITMENT_ACTIVE_RUN_REASON = 'age-limit (committed unregistered run)';
|
|
56
73
|
/**
|
|
57
74
|
* Closed-world predicate: is this resume-queue PAUSE reason a blunt
|
|
58
75
|
* emergency/sentinel stop that the drainer may auto-resume once it has gone
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkEvidence.js","sourceRoot":"","sources":["../../src/core/WorkEvidence.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WorkEvidence.js","sourceRoot":"","sources":["../../src/core/WorkEvidence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GAP-B commitment-evidence backstop — the pure qualifying + agreement predicate.
|
|
3
|
+
*
|
|
4
|
+
* Spec: docs/specs/autonomous-registration-guarantee.md (Part B + Frontloaded
|
|
5
|
+
* Decisions D1/D2/D7/D8).
|
|
6
|
+
*
|
|
7
|
+
* The reaper revives a REGISTERED autonomous run from its per-topic state file.
|
|
8
|
+
* An UNregistered-but-actively-working run (operator said "go autonomous" but the
|
|
9
|
+
* skill never wrote the state file) has no state file → today it dies at the
|
|
10
|
+
* age-limit reap. This module is the BACKSTOP: it recognizes an independent
|
|
11
|
+
* live-work signal — a FRESH open agent-commitment for the topic, CORROBORATED by
|
|
12
|
+
* a recent user message — and (when armed, dark by default) lets the existing
|
|
13
|
+
* revival machinery keep the run alive.
|
|
14
|
+
*
|
|
15
|
+
* This file holds ONLY the deterministic predicates (D1 freshness, D2 qualifying
|
|
16
|
+
* set, D8 agreement). The wiring (the dark-gate, the injection, the Part A
|
|
17
|
+
* surface, the drain-time re-check) lives at the server callsite. Extracting the
|
|
18
|
+
* predicate here makes D1/D2/D7/D8 unit-testable against a REAL CommitmentTracker
|
|
19
|
+
* with no server boot — and guarantees the enqueue-time check and the drain-time
|
|
20
|
+
* re-check (D9) compute the IDENTICAL verdict (they call this same function), so
|
|
21
|
+
* they can never disagree.
|
|
22
|
+
*
|
|
23
|
+
* Signal vs Authority: this returns a boolean SIGNAL. The authority that decides
|
|
24
|
+
* revival remains the unchanged `evidenceEligible`/drainer. No new WorkEvidence
|
|
25
|
+
* enum value; provenance rides the reason tag + the reap-log `evidenceSource`.
|
|
26
|
+
*/
|
|
27
|
+
import type { Commitment } from '../monitoring/CommitmentTracker.js';
|
|
28
|
+
/**
|
|
29
|
+
* Part D (spec: autonomous-registration-guarantee.md) — the pure inbound-user-
|
|
30
|
+
* message recency predicate over a topic's message-history tail. Extracted here
|
|
31
|
+
* so it is unit-testable against real TelegramAdapter.getTopicHistory output
|
|
32
|
+
* WITHOUT a server boot, and shared by every `recentUserMessage` consumer (the
|
|
33
|
+
* ReapGuard/SessionReaper deps AND the GAP-B D8 agreement check) so KEEP and
|
|
34
|
+
* eligibility compute the identical truth.
|
|
35
|
+
*
|
|
36
|
+
* An inbound USER message = `fromUser === true` (NOT an agent/system echo).
|
|
37
|
+
* Freshness = its `timestamp` within `withinMs`. History is oldest→newest, so the
|
|
38
|
+
* newest user entry (the first hit scanning backwards) is the verdict. A
|
|
39
|
+
* non-parseable timestamp is skipped (never a false positive). Returns false on
|
|
40
|
+
* an empty / user-message-free history. Pure — the server callsite wraps the
|
|
41
|
+
* getTopicHistory call in its own try/catch (D7 fail-open).
|
|
42
|
+
*/
|
|
43
|
+
export interface RecencyLogEntry {
|
|
44
|
+
fromUser: boolean;
|
|
45
|
+
timestamp: string;
|
|
46
|
+
}
|
|
47
|
+
export declare function recentUserMessageFromHistory(history: readonly RecencyLogEntry[], withinMs: number, now?: number): boolean;
|
|
48
|
+
/** The minimal slice of CommitmentTracker this predicate reads. */
|
|
49
|
+
export interface GapBCommitmentSource {
|
|
50
|
+
/** Active commitments bound to a topic (pending/verified/violated, not expired). */
|
|
51
|
+
getActiveByTopicId(topicId: number): Commitment[];
|
|
52
|
+
}
|
|
53
|
+
export interface GapBQualifyDeps {
|
|
54
|
+
/** This machine's mesh identity, for the D2 local-origin filter. May be absent
|
|
55
|
+
* (single-machine / pre-mesh) — then no commitment is excluded on origin. */
|
|
56
|
+
ownMachineId?: string;
|
|
57
|
+
/** D1 freshness horizon on `createdAt` (ms). */
|
|
58
|
+
freshCommitmentWindowMs: number;
|
|
59
|
+
/** D8 agreement window — the SAME `recentUserMessage(topic, window)` predicate
|
|
60
|
+
* ReapGuard's commitment KEEP uses (the staleCommitmentWindowMs / 8h horizon). */
|
|
61
|
+
staleCommitmentWindowMs: number;
|
|
62
|
+
/** D8 corroboration: a recent INBOUND USER message on the topic within window.
|
|
63
|
+
* Shared with ReapGuard's dep so KEEP and eligibility cannot disagree. */
|
|
64
|
+
recentUserMessage: (topicId: number, withinMs: number) => boolean;
|
|
65
|
+
/** Wall clock (injected for testability). Default Date.now. */
|
|
66
|
+
now?: () => number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* D2 qualifying-commitment predicate (the per-commitment half).
|
|
70
|
+
*
|
|
71
|
+
* A commitment counts as live-work evidence only if ALL hold:
|
|
72
|
+
* - `status === 'pending'` (NOT verified/violated — a violated commitment is a
|
|
73
|
+
* FAILING session, not a working one);
|
|
74
|
+
* - agent-driven: `owner === 'agent'` (default), OR `owner === 'user'` with
|
|
75
|
+
* `blockedOn` ∈ {none, undefined} — a commitment WAITING on the user
|
|
76
|
+
* (`blockedOn` ∈ {user-input, user-authorization}) is the opposite of an
|
|
77
|
+
* active autonomous run and is excluded;
|
|
78
|
+
* - not beacon-paused and not beacon-suppressed;
|
|
79
|
+
* - local-origin: `originMachineId` is this machine or absent (a replicated peer
|
|
80
|
+
* commitment is advisory data, never revival authority);
|
|
81
|
+
* - D1 freshness: `createdAt` within `freshCommitmentWindowMs` — `createdAt` ONLY
|
|
82
|
+
* (no `updatedAt` exists; bookkeeping/beacon timestamps must NOT refresh
|
|
83
|
+
* freshness — a 3-day promise a beacon pinged 5min ago is not a live session).
|
|
84
|
+
*/
|
|
85
|
+
export declare function commitmentQualifies(c: Commitment, deps: Pick<GapBQualifyDeps, 'ownMachineId' | 'freshCommitmentWindowMs' | 'now'>): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* The full GAP-B eligibility verdict for a topic (D1/D2 + D8 agreement).
|
|
88
|
+
*
|
|
89
|
+
* True iff (a) at least one qualifying commitment exists for the topic (D1/D2),
|
|
90
|
+
* AND (b) there is a recent user message within the stale-commitment window (D8 —
|
|
91
|
+
* the SAME corroboration ReapGuard's commitment KEEP uses, so KEEP and
|
|
92
|
+
* eligibility AGREE; without this the 2026-06-13 13-session reap/revive loop
|
|
93
|
+
* returns). Fail-open (D7): any read throwing ⇒ false (no injection), never a
|
|
94
|
+
* spurious eligibility.
|
|
95
|
+
*/
|
|
96
|
+
export declare function gapBEligibleForTopic(topicId: number, source: GapBCommitmentSource, deps: GapBQualifyDeps): boolean;
|
|
97
|
+
/** Dark-gate posture for the Part B injection (D5), resolved from config. */
|
|
98
|
+
export interface GapBInjectionGate {
|
|
99
|
+
/** True only when `monitoring.resumeQueue.commitmentEvidence.enabled === true`.
|
|
100
|
+
* Omitted ⇒ OFF on BOTH fleet AND dev (the containment). */
|
|
101
|
+
armed: boolean;
|
|
102
|
+
/** dryRun defaults TRUE when armed: logs "would inject" without tagging the
|
|
103
|
+
* candidate (the dark soak proving KEEP/eligibility agree before evidence
|
|
104
|
+
* flows). Only `armed && !dryRun` actually injects. */
|
|
105
|
+
dryRun: boolean;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Resolve the Part B dark-gate from the resumeQueue config block (D5).
|
|
109
|
+
* `enabled` MUST be an explicit `true` — absence/false ⇒ disarmed (no injection
|
|
110
|
+
* on fleet OR dev). `dryRun` defaults true when armed.
|
|
111
|
+
*/
|
|
112
|
+
export declare function resolveGapBInjectionGate(cfg?: {
|
|
113
|
+
enabled?: boolean;
|
|
114
|
+
dryRun?: boolean;
|
|
115
|
+
}): GapBInjectionGate;
|
|
116
|
+
/** The full reaped-session decision: did GAP-B evidence fire, and does it INJECT? */
|
|
117
|
+
export interface GapBInjectionDecision {
|
|
118
|
+
/** The qualifying-commitment + D8 verdict fired (drives the Part A surface,
|
|
119
|
+
* even in dryRun — the surface exists to make the unregistered run visible). */
|
|
120
|
+
fired: boolean;
|
|
121
|
+
/** The LIVE injection switch: `fired && armed && !dryRun`. Only this tags the
|
|
122
|
+
* candidate + the reap-log. dryRun logs the verdict but injects nothing. */
|
|
123
|
+
inject: boolean;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Compute the reaped-session GAP-B decision. Pinned to the SAME branch the
|
|
127
|
+
* state-file source uses: an `age-limit` reap whose per-topic state file is
|
|
128
|
+
* ABSENT (`stateFilePresent === false` — a registered run is handled upstream by
|
|
129
|
+
* AGE_LIMIT_ACTIVE_RUN_REASON). When disarmed, returns a strict no-op
|
|
130
|
+
* `{fired:false, inject:false}` (the dark-default containment: no injection ⇒ no
|
|
131
|
+
* revival ⇒ the 2026-06-13 loop is structurally impossible while dark).
|
|
132
|
+
*
|
|
133
|
+
* `eligible` is the precomputed `gapBEligibleForTopic` verdict (kept a parameter
|
|
134
|
+
* so the caller can short-circuit the cost when disarmed, and so this stays a
|
|
135
|
+
* pure decision function over booleans).
|
|
136
|
+
*/
|
|
137
|
+
export declare function decideGapBInjection(input: {
|
|
138
|
+
gate: GapBInjectionGate;
|
|
139
|
+
reason: string;
|
|
140
|
+
stateFilePresent: boolean;
|
|
141
|
+
eligible: boolean;
|
|
142
|
+
}): GapBInjectionDecision;
|
|
143
|
+
//# sourceMappingURL=gapBCommitmentEvidence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gapBCommitmentEvidence.d.ts","sourceRoot":"","sources":["../../src/core/gapBCommitmentEvidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAErE;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,SAAS,eAAe,EAAE,EACnC,QAAQ,EAAE,MAAM,EAChB,GAAG,GAAE,MAAmB,GACvB,OAAO,CAYT;AAED,mEAAmE;AACnE,MAAM,WAAW,oBAAoB;IACnC,oFAAoF;IACpF,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,CAAC;CACnD;AAED,MAAM,WAAW,eAAe;IAC9B;kFAC8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gDAAgD;IAChD,uBAAuB,EAAE,MAAM,CAAC;IAChC;uFACmF;IACnF,uBAAuB,EAAE,MAAM,CAAC;IAChC;+EAC2E;IAC3E,iBAAiB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IAClE,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CACjC,CAAC,EAAE,UAAU,EACb,IAAI,EAAE,IAAI,CAAC,eAAe,EAAE,cAAc,GAAG,yBAAyB,GAAG,KAAK,CAAC,GAC9E,OAAO,CAgBT;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,oBAAoB,EAC5B,IAAI,EAAE,eAAe,GACpB,OAAO,CAcT;AAED,6EAA6E;AAC7E,MAAM,WAAW,iBAAiB;IAChC;iEAC6D;IAC7D,KAAK,EAAE,OAAO,CAAC;IACf;;4DAEwD;IACxD,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,CAAC,EAAE;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GAAG,iBAAiB,CAGpB;AAED,qFAAqF;AACrF,MAAM,WAAW,qBAAqB;IACpC;qFACiF;IACjF,KAAK,EAAE,OAAO,CAAC;IACf;iFAC6E;IAC7E,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,IAAI,EAAE,iBAAiB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;CACnB,GAAG,qBAAqB,CAMxB"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GAP-B commitment-evidence backstop — the pure qualifying + agreement predicate.
|
|
3
|
+
*
|
|
4
|
+
* Spec: docs/specs/autonomous-registration-guarantee.md (Part B + Frontloaded
|
|
5
|
+
* Decisions D1/D2/D7/D8).
|
|
6
|
+
*
|
|
7
|
+
* The reaper revives a REGISTERED autonomous run from its per-topic state file.
|
|
8
|
+
* An UNregistered-but-actively-working run (operator said "go autonomous" but the
|
|
9
|
+
* skill never wrote the state file) has no state file → today it dies at the
|
|
10
|
+
* age-limit reap. This module is the BACKSTOP: it recognizes an independent
|
|
11
|
+
* live-work signal — a FRESH open agent-commitment for the topic, CORROBORATED by
|
|
12
|
+
* a recent user message — and (when armed, dark by default) lets the existing
|
|
13
|
+
* revival machinery keep the run alive.
|
|
14
|
+
*
|
|
15
|
+
* This file holds ONLY the deterministic predicates (D1 freshness, D2 qualifying
|
|
16
|
+
* set, D8 agreement). The wiring (the dark-gate, the injection, the Part A
|
|
17
|
+
* surface, the drain-time re-check) lives at the server callsite. Extracting the
|
|
18
|
+
* predicate here makes D1/D2/D7/D8 unit-testable against a REAL CommitmentTracker
|
|
19
|
+
* with no server boot — and guarantees the enqueue-time check and the drain-time
|
|
20
|
+
* re-check (D9) compute the IDENTICAL verdict (they call this same function), so
|
|
21
|
+
* they can never disagree.
|
|
22
|
+
*
|
|
23
|
+
* Signal vs Authority: this returns a boolean SIGNAL. The authority that decides
|
|
24
|
+
* revival remains the unchanged `evidenceEligible`/drainer. No new WorkEvidence
|
|
25
|
+
* enum value; provenance rides the reason tag + the reap-log `evidenceSource`.
|
|
26
|
+
*/
|
|
27
|
+
export function recentUserMessageFromHistory(history, withinMs, now = Date.now()) {
|
|
28
|
+
const cutoff = now - withinMs;
|
|
29
|
+
for (let i = history.length - 1; i >= 0; i--) {
|
|
30
|
+
const entry = history[i];
|
|
31
|
+
if (!entry.fromUser)
|
|
32
|
+
continue; // skip agent/system echoes
|
|
33
|
+
const ts = Date.parse(entry.timestamp);
|
|
34
|
+
if (!Number.isFinite(ts))
|
|
35
|
+
continue;
|
|
36
|
+
// The first USER entry scanning backwards is the NEWEST user message — its
|
|
37
|
+
// recency is the verdict (every earlier user entry is older).
|
|
38
|
+
return ts >= cutoff;
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* D2 qualifying-commitment predicate (the per-commitment half).
|
|
44
|
+
*
|
|
45
|
+
* A commitment counts as live-work evidence only if ALL hold:
|
|
46
|
+
* - `status === 'pending'` (NOT verified/violated — a violated commitment is a
|
|
47
|
+
* FAILING session, not a working one);
|
|
48
|
+
* - agent-driven: `owner === 'agent'` (default), OR `owner === 'user'` with
|
|
49
|
+
* `blockedOn` ∈ {none, undefined} — a commitment WAITING on the user
|
|
50
|
+
* (`blockedOn` ∈ {user-input, user-authorization}) is the opposite of an
|
|
51
|
+
* active autonomous run and is excluded;
|
|
52
|
+
* - not beacon-paused and not beacon-suppressed;
|
|
53
|
+
* - local-origin: `originMachineId` is this machine or absent (a replicated peer
|
|
54
|
+
* commitment is advisory data, never revival authority);
|
|
55
|
+
* - D1 freshness: `createdAt` within `freshCommitmentWindowMs` — `createdAt` ONLY
|
|
56
|
+
* (no `updatedAt` exists; bookkeeping/beacon timestamps must NOT refresh
|
|
57
|
+
* freshness — a 3-day promise a beacon pinged 5min ago is not a live session).
|
|
58
|
+
*/
|
|
59
|
+
export function commitmentQualifies(c, deps) {
|
|
60
|
+
if (c.status !== 'pending')
|
|
61
|
+
return false;
|
|
62
|
+
const owner = c.owner ?? 'agent';
|
|
63
|
+
const blockedOn = c.blockedOn ?? 'none';
|
|
64
|
+
const agentDriven = owner === 'agent' || (owner === 'user' && blockedOn === 'none');
|
|
65
|
+
if (!agentDriven)
|
|
66
|
+
return false;
|
|
67
|
+
if (c.beaconPaused || c.beaconSuppressed)
|
|
68
|
+
return false;
|
|
69
|
+
if (c.originMachineId && deps.ownMachineId && c.originMachineId !== deps.ownMachineId) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
const nowMs = (deps.now ?? Date.now)();
|
|
73
|
+
const createdMs = Date.parse(c.createdAt);
|
|
74
|
+
if (!Number.isFinite(createdMs) || createdMs < nowMs - deps.freshCommitmentWindowMs) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The full GAP-B eligibility verdict for a topic (D1/D2 + D8 agreement).
|
|
81
|
+
*
|
|
82
|
+
* True iff (a) at least one qualifying commitment exists for the topic (D1/D2),
|
|
83
|
+
* AND (b) there is a recent user message within the stale-commitment window (D8 —
|
|
84
|
+
* the SAME corroboration ReapGuard's commitment KEEP uses, so KEEP and
|
|
85
|
+
* eligibility AGREE; without this the 2026-06-13 13-session reap/revive loop
|
|
86
|
+
* returns). Fail-open (D7): any read throwing ⇒ false (no injection), never a
|
|
87
|
+
* spurious eligibility.
|
|
88
|
+
*/
|
|
89
|
+
export function gapBEligibleForTopic(topicId, source, deps) {
|
|
90
|
+
try {
|
|
91
|
+
const qualifies = source
|
|
92
|
+
.getActiveByTopicId(topicId)
|
|
93
|
+
.some((c) => commitmentQualifies(c, deps));
|
|
94
|
+
if (!qualifies)
|
|
95
|
+
return false;
|
|
96
|
+
// D8 AGREEMENT — non-negotiable. A commitment that would NOT keep the session
|
|
97
|
+
// alive (no recent user message) cannot revive it either.
|
|
98
|
+
return deps.recentUserMessage(topicId, deps.staleCommitmentWindowMs);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// @silent-fallback-ok — D7: a throwing tracker/predicate contributes NOTHING;
|
|
102
|
+
// the reap proceeds exactly as today (no injection, no revive).
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Resolve the Part B dark-gate from the resumeQueue config block (D5).
|
|
108
|
+
* `enabled` MUST be an explicit `true` — absence/false ⇒ disarmed (no injection
|
|
109
|
+
* on fleet OR dev). `dryRun` defaults true when armed.
|
|
110
|
+
*/
|
|
111
|
+
export function resolveGapBInjectionGate(cfg) {
|
|
112
|
+
const armed = cfg?.enabled === true;
|
|
113
|
+
return { armed, dryRun: cfg?.dryRun !== false };
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Compute the reaped-session GAP-B decision. Pinned to the SAME branch the
|
|
117
|
+
* state-file source uses: an `age-limit` reap whose per-topic state file is
|
|
118
|
+
* ABSENT (`stateFilePresent === false` — a registered run is handled upstream by
|
|
119
|
+
* AGE_LIMIT_ACTIVE_RUN_REASON). When disarmed, returns a strict no-op
|
|
120
|
+
* `{fired:false, inject:false}` (the dark-default containment: no injection ⇒ no
|
|
121
|
+
* revival ⇒ the 2026-06-13 loop is structurally impossible while dark).
|
|
122
|
+
*
|
|
123
|
+
* `eligible` is the precomputed `gapBEligibleForTopic` verdict (kept a parameter
|
|
124
|
+
* so the caller can short-circuit the cost when disarmed, and so this stays a
|
|
125
|
+
* pure decision function over booleans).
|
|
126
|
+
*/
|
|
127
|
+
export function decideGapBInjection(input) {
|
|
128
|
+
if (!input.gate.armed)
|
|
129
|
+
return { fired: false, inject: false };
|
|
130
|
+
if (input.reason !== 'age-limit')
|
|
131
|
+
return { fired: false, inject: false };
|
|
132
|
+
if (input.stateFilePresent)
|
|
133
|
+
return { fired: false, inject: false };
|
|
134
|
+
if (!input.eligible)
|
|
135
|
+
return { fired: false, inject: false };
|
|
136
|
+
return { fired: true, inject: !input.gate.dryRun };
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=gapBCommitmentEvidence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gapBCommitmentEvidence.js","sourceRoot":"","sources":["../../src/core/gapBCommitmentEvidence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* internalFrameworkDefault — the PROVIDER-FALLBACK DEFAULT POLICY
|
|
3
|
+
* (docs/specs/provider-fallback-default-policy.md §4.1–4.2).
|
|
4
|
+
*
|
|
5
|
+
* Computes the effective `ComponentFrameworksConfig` that turns the already-shipped
|
|
6
|
+
* IntelligenceRouter failure-swap engine ON out-of-the-box: internal, lightweight,
|
|
7
|
+
* high-frequency categories (sentinel / gate / reflector) run on the FIRST ACTIVE
|
|
8
|
+
* framework in a documented preference chain, with the remaining active frameworks
|
|
9
|
+
* as the ordered `failureSwap` tail and Claude as the last resort.
|
|
10
|
+
*
|
|
11
|
+
* This is a PURE policy resolver — it does NOT probe the system. The caller passes
|
|
12
|
+
* the already-computed active-framework set (probed once at boot via the router's
|
|
13
|
+
* own `buildProvider(fw) !== null` truth — §4.2), so this module is unit-testable
|
|
14
|
+
* in isolation.
|
|
15
|
+
*
|
|
16
|
+
* What it does NOT do (deliberate, per §4.1):
|
|
17
|
+
* - `job` is EXCLUDED — routing cost-bearing background jobs (e.g. CartographerSweep)
|
|
18
|
+
* off Claude by default would silently auto-arm them; an operator arms `categories.job`.
|
|
19
|
+
* - `other` is left on the agent default (unchanged).
|
|
20
|
+
* - Spawned interactive sessions stay on `topicFrameworks` (out of scope).
|
|
21
|
+
*/
|
|
22
|
+
import type { IntelligenceFramework } from './intelligenceProviderFactory.js';
|
|
23
|
+
import type { ComponentFrameworksConfig } from './IntelligenceRouter.js';
|
|
24
|
+
/**
|
|
25
|
+
* The internal-component provider preference chain (§4.1 / §6.5). ONE named,
|
|
26
|
+
* documented, inspectable place. Order: Codex first (operator directive), Claude
|
|
27
|
+
* last (the true last resort for background work). A unit test validates every
|
|
28
|
+
* entry against the real `IntelligenceFramework` enum so an unknown name never ships.
|
|
29
|
+
*/
|
|
30
|
+
export declare const INTERNAL_FRAMEWORK_PREFERENCE: readonly IntelligenceFramework[];
|
|
31
|
+
/**
|
|
32
|
+
* Compute the default `componentFrameworks` from the active-framework set.
|
|
33
|
+
*
|
|
34
|
+
* @param activeFrameworks the preference chain filtered to frameworks ACTIVE in this
|
|
35
|
+
* agent, IN PREFERENCE ORDER (the caller filters `INTERNAL_FRAMEWORK_PREFERENCE`
|
|
36
|
+
* by `buildProvider(fw) !== null`). MUST already be ordered + de-duplicated.
|
|
37
|
+
* @returns the effective `ComponentFrameworksConfig`:
|
|
38
|
+
* - `categories.{sentinel,gate,reflector}` = `active[0]` (first active off-Claude,
|
|
39
|
+
* or claude-code if that's all that's active)
|
|
40
|
+
* - `failureSwap` = `active.slice(1)` (the ordered tail, claude-code last)
|
|
41
|
+
* - `fallback: 'default'`
|
|
42
|
+
*
|
|
43
|
+
* No-op cases (byte-identical to today — primary is the agent default, empty swap):
|
|
44
|
+
* - `active === []` → `{ failureSwap: [], fallback: 'default' }`
|
|
45
|
+
* - `active === ['claude-code']` → `{ failureSwap: [], fallback: 'default' }`
|
|
46
|
+
* (claude-code IS the default framework, so emitting it as the primary category
|
|
47
|
+
* value is harmless, but we leave categories unset to keep the no-op truly inert)
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveInternalFrameworkDefault(activeFrameworks: readonly IntelligenceFramework[]): ComponentFrameworksConfig;
|
|
50
|
+
//# sourceMappingURL=internalFrameworkDefault.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internalFrameworkDefault.d.ts","sourceRoot":"","sources":["../../src/core/internalFrameworkDefault.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAC9E,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAEzE;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,EAAE,SAAS,qBAAqB,EAKhE,CAAC;AAEX;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,+BAA+B,CAC7C,gBAAgB,EAAE,SAAS,qBAAqB,EAAE,GACjD,yBAAyB,CAqB3B"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* internalFrameworkDefault — the PROVIDER-FALLBACK DEFAULT POLICY
|
|
3
|
+
* (docs/specs/provider-fallback-default-policy.md §4.1–4.2).
|
|
4
|
+
*
|
|
5
|
+
* Computes the effective `ComponentFrameworksConfig` that turns the already-shipped
|
|
6
|
+
* IntelligenceRouter failure-swap engine ON out-of-the-box: internal, lightweight,
|
|
7
|
+
* high-frequency categories (sentinel / gate / reflector) run on the FIRST ACTIVE
|
|
8
|
+
* framework in a documented preference chain, with the remaining active frameworks
|
|
9
|
+
* as the ordered `failureSwap` tail and Claude as the last resort.
|
|
10
|
+
*
|
|
11
|
+
* This is a PURE policy resolver — it does NOT probe the system. The caller passes
|
|
12
|
+
* the already-computed active-framework set (probed once at boot via the router's
|
|
13
|
+
* own `buildProvider(fw) !== null` truth — §4.2), so this module is unit-testable
|
|
14
|
+
* in isolation.
|
|
15
|
+
*
|
|
16
|
+
* What it does NOT do (deliberate, per §4.1):
|
|
17
|
+
* - `job` is EXCLUDED — routing cost-bearing background jobs (e.g. CartographerSweep)
|
|
18
|
+
* off Claude by default would silently auto-arm them; an operator arms `categories.job`.
|
|
19
|
+
* - `other` is left on the agent default (unchanged).
|
|
20
|
+
* - Spawned interactive sessions stay on `topicFrameworks` (out of scope).
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* The internal-component provider preference chain (§4.1 / §6.5). ONE named,
|
|
24
|
+
* documented, inspectable place. Order: Codex first (operator directive), Claude
|
|
25
|
+
* last (the true last resort for background work). A unit test validates every
|
|
26
|
+
* entry against the real `IntelligenceFramework` enum so an unknown name never ships.
|
|
27
|
+
*/
|
|
28
|
+
export const INTERNAL_FRAMEWORK_PREFERENCE = [
|
|
29
|
+
'codex-cli',
|
|
30
|
+
'pi-cli',
|
|
31
|
+
'gemini-cli',
|
|
32
|
+
'claude-code',
|
|
33
|
+
];
|
|
34
|
+
/**
|
|
35
|
+
* Compute the default `componentFrameworks` from the active-framework set.
|
|
36
|
+
*
|
|
37
|
+
* @param activeFrameworks the preference chain filtered to frameworks ACTIVE in this
|
|
38
|
+
* agent, IN PREFERENCE ORDER (the caller filters `INTERNAL_FRAMEWORK_PREFERENCE`
|
|
39
|
+
* by `buildProvider(fw) !== null`). MUST already be ordered + de-duplicated.
|
|
40
|
+
* @returns the effective `ComponentFrameworksConfig`:
|
|
41
|
+
* - `categories.{sentinel,gate,reflector}` = `active[0]` (first active off-Claude,
|
|
42
|
+
* or claude-code if that's all that's active)
|
|
43
|
+
* - `failureSwap` = `active.slice(1)` (the ordered tail, claude-code last)
|
|
44
|
+
* - `fallback: 'default'`
|
|
45
|
+
*
|
|
46
|
+
* No-op cases (byte-identical to today — primary is the agent default, empty swap):
|
|
47
|
+
* - `active === []` → `{ failureSwap: [], fallback: 'default' }`
|
|
48
|
+
* - `active === ['claude-code']` → `{ failureSwap: [], fallback: 'default' }`
|
|
49
|
+
* (claude-code IS the default framework, so emitting it as the primary category
|
|
50
|
+
* value is harmless, but we leave categories unset to keep the no-op truly inert)
|
|
51
|
+
*/
|
|
52
|
+
export function resolveInternalFrameworkDefault(activeFrameworks) {
|
|
53
|
+
const active = activeFrameworks;
|
|
54
|
+
// No off-Claude provider active ⇒ a true no-op: no category routing, empty swap.
|
|
55
|
+
// 'claude-code' alone means there is nothing to route OFF Claude onto, so the
|
|
56
|
+
// policy is inert (matches §4.2 — never made worse, never spammed with degrades).
|
|
57
|
+
if (active.length === 0 || (active.length === 1 && active[0] === 'claude-code')) {
|
|
58
|
+
return { failureSwap: [], fallback: 'default' };
|
|
59
|
+
}
|
|
60
|
+
const primary = active[0];
|
|
61
|
+
return {
|
|
62
|
+
categories: {
|
|
63
|
+
sentinel: primary,
|
|
64
|
+
gate: primary,
|
|
65
|
+
reflector: primary,
|
|
66
|
+
// `job` and `other` are deliberately ABSENT (§4.1).
|
|
67
|
+
},
|
|
68
|
+
failureSwap: active.slice(1),
|
|
69
|
+
fallback: 'default',
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=internalFrameworkDefault.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internalFrameworkDefault.js","sourceRoot":"","sources":["../../src/core/internalFrameworkDefault.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAKH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAqC;IAC7E,WAAW;IACX,QAAQ;IACR,YAAY;IACZ,aAAa;CACL,CAAC;AAEX;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,+BAA+B,CAC7C,gBAAkD;IAElD,MAAM,MAAM,GAAG,gBAAgB,CAAC;IAEhC,iFAAiF;IACjF,8EAA8E;IAC9E,kFAAkF;IAClF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,aAAa,CAAC,EAAE,CAAC;QAChF,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IAClD,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAC1B,OAAO;QACL,UAAU,EAAE;YACV,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,OAAO;YACb,SAAS,EAAE,OAAO;YAClB,oDAAoD;SACrD;QACD,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5B,QAAQ,EAAE,SAAS;KACpB,CAAC;AACJ,CAAC"}
|
package/dist/core/types.d.ts
CHANGED
|
@@ -228,6 +228,14 @@ export interface SessionManagerConfig {
|
|
|
228
228
|
categories?: Partial<Record<'sentinel' | 'gate' | 'job' | 'reflector' | 'other', 'claude-code' | 'codex-cli' | 'gemini-cli' | 'pi-cli'>>;
|
|
229
229
|
overrides?: Record<string, 'claude-code' | 'codex-cli' | 'gemini-cli' | 'pi-cli'>;
|
|
230
230
|
fallback?: 'default' | 'none';
|
|
231
|
+
/**
|
|
232
|
+
* Ordered fallback frameworks a SAFETY-GATING call tries when its primary
|
|
233
|
+
* provider fails at runtime, before failing closed (provider-fallback-default-policy.md).
|
|
234
|
+
* The provider-fallback DEFAULT POLICY computes this automatically from the active
|
|
235
|
+
* set (sentinel/gate/reflector → first active off-Claude, remaining active as the
|
|
236
|
+
* tail) when this whole block is unset; an operator who sets the block supplies it.
|
|
237
|
+
*/
|
|
238
|
+
failureSwap?: Array<'claude-code' | 'codex-cli' | 'gemini-cli' | 'pi-cli'>;
|
|
231
239
|
};
|
|
232
240
|
/**
|
|
233
241
|
* The agent's resolved runtime framework — the single source of
|
|
@@ -2676,6 +2684,16 @@ export interface InstarConfig {
|
|
|
2676
2684
|
*/
|
|
2677
2685
|
openMs?: number;
|
|
2678
2686
|
};
|
|
2687
|
+
/**
|
|
2688
|
+
* Per-attempt swap timeout (ms) for the IntelligenceRouter failure-swap loop
|
|
2689
|
+
* (docs/specs/provider-fallback-default-policy.md §4.5). Each gating swap attempt
|
|
2690
|
+
* races this cap; a slow-but-not-erroring provider is abandoned at the cap and the
|
|
2691
|
+
* loop advances to the next target. INLINE-DEFAULTED to 5000ms at the router
|
|
2692
|
+
* construction site — absent ⇒ 5s applies; present ⇒ the operator's value wins.
|
|
2693
|
+
* Deliberately kept out of ConfigDefaults/migrateConfig (codexExecJson precedent)
|
|
2694
|
+
* so absence is the default state, never a persisted block.
|
|
2695
|
+
*/
|
|
2696
|
+
swapAttemptTimeoutMs?: number;
|
|
2679
2697
|
/**
|
|
2680
2698
|
* Anthropic subscription-path routing for INTERNAL intelligence calls
|
|
2681
2699
|
* (sentinels, gates, extractors) — the June-15 readiness lever
|
|
@@ -4146,6 +4164,27 @@ export interface MonitoringConfig {
|
|
|
4146
4164
|
* ConfigDefaults — preserves the fleet flip).
|
|
4147
4165
|
*/
|
|
4148
4166
|
autoHealStaleHostLock?: boolean;
|
|
4167
|
+
/**
|
|
4168
|
+
* GAP-B commitment-evidence backstop (spec:
|
|
4169
|
+
* autonomous-registration-guarantee.md, Part B). When an age-limit reap hits
|
|
4170
|
+
* a topic with NO per-topic autonomous-run state file but a FRESH qualifying
|
|
4171
|
+
* open agent-commitment corroborated by a recent user message (D8), inject
|
|
4172
|
+
* `build-or-autonomous-active` so an UNregistered-but-working run survives.
|
|
4173
|
+
*
|
|
4174
|
+
* Ships DARK (the containment): `enabled` is OMITTED so the injection is OFF
|
|
4175
|
+
* on BOTH fleet AND dev by default — no injection ⇒ no revival ⇒ the
|
|
4176
|
+
* 2026-06-13 loop is structurally impossible while dark. Set `enabled:true`
|
|
4177
|
+
* to arm; `dryRun:true` (the default when armed) logs "would inject" without
|
|
4178
|
+
* tagging the candidate, so a dark-soak can confirm KEEP/eligibility agree on
|
|
4179
|
+
* real data BEFORE evidence actually flows. CODE-defaulted (absent from
|
|
4180
|
+
* ConfigDefaults — the resumeQueue.* dark-default discipline, no migration).
|
|
4181
|
+
*/
|
|
4182
|
+
commitmentEvidence?: {
|
|
4183
|
+
enabled?: boolean;
|
|
4184
|
+
dryRun?: boolean;
|
|
4185
|
+
/** Freshness horizon on `createdAt` (D1). Default 6h. */
|
|
4186
|
+
freshCommitmentWindowMs?: number;
|
|
4187
|
+
};
|
|
4149
4188
|
};
|
|
4150
4189
|
/**
|
|
4151
4190
|
* AgentWorktreeReaper (Responsible Resource Usage — OS resource hygiene).
|