instar 1.3.677 → 1.3.678
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/core/internalFrameworkDefault.d.ts +23 -2
- package/dist/core/internalFrameworkDefault.d.ts.map +1 -1
- package/dist/core/internalFrameworkDefault.js +41 -3
- package/dist/core/internalFrameworkDefault.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +2 -2
- package/upgrades/{1.3.677.md → 1.3.678.md} +32 -0
- package/upgrades/side-effects/latency-sensitive-gate-framework.md +79 -0
|
@@ -28,6 +28,23 @@ import type { ComponentFrameworksConfig } from './IntelligenceRouter.js';
|
|
|
28
28
|
* entry against the real `IntelligenceFramework` enum so an unknown name never ships.
|
|
29
29
|
*/
|
|
30
30
|
export declare const INTERNAL_FRAMEWORK_PREFERENCE: readonly IntelligenceFramework[];
|
|
31
|
+
/**
|
|
32
|
+
* The LATENCY-SENSITIVE preference chain — used for the `gate` category ONLY.
|
|
33
|
+
*
|
|
34
|
+
* A `gate` is a SYNCHRONOUS, action-blocking check (the user-facing
|
|
35
|
+
* `MessagingToneGate` is the canonical one — a human is waiting for their reply).
|
|
36
|
+
* The general `INTERNAL_FRAMEWORK_PREFERENCE` puts `codex-cli` first by operator
|
|
37
|
+
* directive (spread background LOAD off Claude), but codex-cli is the SLOWEST
|
|
38
|
+
* off-Claude framework (~30s, which exceeds the 20s outbound-gate review budget
|
|
39
|
+
* and times the gate out — the 2026-06-25 silent-outbound class). For a
|
|
40
|
+
* latency-sensitive gate the right default is the FASTEST available off-Claude
|
|
41
|
+
* framework, not the load-spreading order. Ranked fastest→slowest, Claude last.
|
|
42
|
+
*
|
|
43
|
+
* This does NOT override the codex-first directive for the BACKGROUND categories
|
|
44
|
+
* (`sentinel` / `reflector`) — their latency does not block a human, so they keep
|
|
45
|
+
* the load-spreading order. Only `gate` (where a user waits) goes fastest-first.
|
|
46
|
+
*/
|
|
47
|
+
export declare const LATENCY_SENSITIVE_FRAMEWORK_PREFERENCE: readonly IntelligenceFramework[];
|
|
31
48
|
/**
|
|
32
49
|
* Compute the default `componentFrameworks` from the active-framework set.
|
|
33
50
|
*
|
|
@@ -35,8 +52,12 @@ export declare const INTERNAL_FRAMEWORK_PREFERENCE: readonly IntelligenceFramewo
|
|
|
35
52
|
* agent, IN PREFERENCE ORDER (the caller filters `INTERNAL_FRAMEWORK_PREFERENCE`
|
|
36
53
|
* by `buildProvider(fw) !== null`). MUST already be ordered + de-duplicated.
|
|
37
54
|
* @returns the effective `ComponentFrameworksConfig`:
|
|
38
|
-
* - `categories.{sentinel,
|
|
39
|
-
* or claude-code if that's all that's active)
|
|
55
|
+
* - `categories.{sentinel,reflector}` = `active[0]` (first active off-Claude in the
|
|
56
|
+
* codex-first load-spreading order, or claude-code if that's all that's active)
|
|
57
|
+
* - `categories.gate` = the FASTEST active off-Claude framework
|
|
58
|
+
* (`LATENCY_SENSITIVE_FRAMEWORK_PREFERENCE`: pi → gemini → codex → claude) — the
|
|
59
|
+
* gate is synchronous + user-blocking, so it prefers speed over load-spreading.
|
|
60
|
+
* Equals `active[0]` when only one off-Claude framework is active (no-op then).
|
|
40
61
|
* - `failureSwap` = `active.slice(1)` (the ordered tail, claude-code last)
|
|
41
62
|
* - `fallback: 'default'`
|
|
42
63
|
*
|
|
@@ -1 +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
|
|
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;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,sCAAsC,EAAE,SAAS,qBAAqB,EAKzE,CAAC;AAUX;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,+BAA+B,CAC7C,gBAAgB,EAAE,SAAS,qBAAqB,EAAE,GACjD,yBAAyB,CA6B3B"}
|
|
@@ -31,6 +31,32 @@ export const INTERNAL_FRAMEWORK_PREFERENCE = [
|
|
|
31
31
|
'gemini-cli',
|
|
32
32
|
'claude-code',
|
|
33
33
|
];
|
|
34
|
+
/**
|
|
35
|
+
* The LATENCY-SENSITIVE preference chain — used for the `gate` category ONLY.
|
|
36
|
+
*
|
|
37
|
+
* A `gate` is a SYNCHRONOUS, action-blocking check (the user-facing
|
|
38
|
+
* `MessagingToneGate` is the canonical one — a human is waiting for their reply).
|
|
39
|
+
* The general `INTERNAL_FRAMEWORK_PREFERENCE` puts `codex-cli` first by operator
|
|
40
|
+
* directive (spread background LOAD off Claude), but codex-cli is the SLOWEST
|
|
41
|
+
* off-Claude framework (~30s, which exceeds the 20s outbound-gate review budget
|
|
42
|
+
* and times the gate out — the 2026-06-25 silent-outbound class). For a
|
|
43
|
+
* latency-sensitive gate the right default is the FASTEST available off-Claude
|
|
44
|
+
* framework, not the load-spreading order. Ranked fastest→slowest, Claude last.
|
|
45
|
+
*
|
|
46
|
+
* This does NOT override the codex-first directive for the BACKGROUND categories
|
|
47
|
+
* (`sentinel` / `reflector`) — their latency does not block a human, so they keep
|
|
48
|
+
* the load-spreading order. Only `gate` (where a user waits) goes fastest-first.
|
|
49
|
+
*/
|
|
50
|
+
export const LATENCY_SENSITIVE_FRAMEWORK_PREFERENCE = [
|
|
51
|
+
'pi-cli',
|
|
52
|
+
'gemini-cli',
|
|
53
|
+
'codex-cli',
|
|
54
|
+
'claude-code',
|
|
55
|
+
];
|
|
56
|
+
/** The first framework in `order` that is also present in `active`, else undefined. */
|
|
57
|
+
function firstActiveIn(order, active) {
|
|
58
|
+
return order.find((fw) => active.includes(fw));
|
|
59
|
+
}
|
|
34
60
|
/**
|
|
35
61
|
* Compute the default `componentFrameworks` from the active-framework set.
|
|
36
62
|
*
|
|
@@ -38,8 +64,12 @@ export const INTERNAL_FRAMEWORK_PREFERENCE = [
|
|
|
38
64
|
* agent, IN PREFERENCE ORDER (the caller filters `INTERNAL_FRAMEWORK_PREFERENCE`
|
|
39
65
|
* by `buildProvider(fw) !== null`). MUST already be ordered + de-duplicated.
|
|
40
66
|
* @returns the effective `ComponentFrameworksConfig`:
|
|
41
|
-
* - `categories.{sentinel,
|
|
42
|
-
* or claude-code if that's all that's active)
|
|
67
|
+
* - `categories.{sentinel,reflector}` = `active[0]` (first active off-Claude in the
|
|
68
|
+
* codex-first load-spreading order, or claude-code if that's all that's active)
|
|
69
|
+
* - `categories.gate` = the FASTEST active off-Claude framework
|
|
70
|
+
* (`LATENCY_SENSITIVE_FRAMEWORK_PREFERENCE`: pi → gemini → codex → claude) — the
|
|
71
|
+
* gate is synchronous + user-blocking, so it prefers speed over load-spreading.
|
|
72
|
+
* Equals `active[0]` when only one off-Claude framework is active (no-op then).
|
|
43
73
|
* - `failureSwap` = `active.slice(1)` (the ordered tail, claude-code last)
|
|
44
74
|
* - `fallback: 'default'`
|
|
45
75
|
*
|
|
@@ -58,10 +88,18 @@ export function resolveInternalFrameworkDefault(activeFrameworks) {
|
|
|
58
88
|
return { failureSwap: [], fallback: 'default' };
|
|
59
89
|
}
|
|
60
90
|
const primary = active[0];
|
|
91
|
+
// The `gate` category is LATENCY-SENSITIVE: a synchronous, user-blocking check.
|
|
92
|
+
// It gets the FASTEST active off-Claude framework (pi → gemini → codex → claude),
|
|
93
|
+
// NOT the load-spreading codex-first order. `active` is in INTERNAL_FRAMEWORK_
|
|
94
|
+
// PREFERENCE order, so we re-rank it by the latency order to find the fastest.
|
|
95
|
+
// Falls back to `primary` if (somehow) no latency-ranked match — keeping the gate
|
|
96
|
+
// never worse than today. When only one off-Claude framework is active, gatePrimary
|
|
97
|
+
// === primary (byte-identical to the old behavior).
|
|
98
|
+
const gatePrimary = firstActiveIn(LATENCY_SENSITIVE_FRAMEWORK_PREFERENCE, active) ?? primary;
|
|
61
99
|
return {
|
|
62
100
|
categories: {
|
|
63
101
|
sentinel: primary,
|
|
64
|
-
gate:
|
|
102
|
+
gate: gatePrimary,
|
|
65
103
|
reflector: primary,
|
|
66
104
|
// `job` and `other` are deliberately ABSENT (§4.1).
|
|
67
105
|
},
|
|
@@ -1 +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
|
|
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;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,sCAAsC,GAAqC;IACtF,QAAQ;IACR,YAAY;IACZ,WAAW;IACX,aAAa;CACL,CAAC;AAEX,uFAAuF;AACvF,SAAS,aAAa,CACpB,KAAuC,EACvC,MAAwC;IAExC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;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,gFAAgF;IAChF,kFAAkF;IAClF,+EAA+E;IAC/E,+EAA+E;IAC/E,kFAAkF;IAClF,oFAAoF;IACpF,oDAAoD;IACpD,MAAM,WAAW,GAAG,aAAa,CAAC,sCAAsC,EAAE,MAAM,CAAC,IAAI,OAAO,CAAC;IAC7F,OAAO;QACL,UAAU,EAAE;YACV,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,WAAW;YACjB,SAAS,EAAE,OAAO;YAClB,oDAAoD;SACrD;QACD,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5B,QAAQ,EAAE,SAAS;KACpB,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-06-26T13:
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-06-26T13:16:49.510Z",
|
|
5
|
+
"instarVersion": "1.3.678",
|
|
6
6
|
"entryCount": 202,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -5,6 +5,17 @@
|
|
|
5
5
|
|
|
6
6
|
## What Changed
|
|
7
7
|
|
|
8
|
+
The provider-fallback default policy routed every internal off-Claude category
|
|
9
|
+
(`sentinel`, `gate`, `reflector`) onto the same codex-first primary. But the
|
|
10
|
+
`gate` category includes the **user-facing tone gate** — a synchronous check a
|
|
11
|
+
human is waiting on — and `codex-cli` is the slowest off-Claude framework (~30s),
|
|
12
|
+
which exceeds the 20s outbound-review budget and times the gate out (a cause of
|
|
13
|
+
the 2026-06-25 silent-outbound incident). The `gate` category now resolves its
|
|
14
|
+
default primary from a separate speed-ranked order (`pi → gemini → codex →
|
|
15
|
+
claude`) — the fastest *active* off-Claude framework — while `sentinel`/`reflector`
|
|
16
|
+
keep the codex-first load-spreading order. `failureSwap`, the gate's verdict
|
|
17
|
+
logic, and the F4 degrade floor are all unchanged.
|
|
18
|
+
|
|
8
19
|
The host spawn cap (the fork-bomb/OOM safety floor that bounds how many LLM
|
|
9
20
|
subprocesses run at once) now reserves a little headroom for the user's reply. Under
|
|
10
21
|
load, the user-facing tone gate used to wait in the same undifferentiated line as
|
|
@@ -27,6 +38,11 @@ treated as reachable), so it never cries wolf on a normal idle kill.
|
|
|
27
38
|
|
|
28
39
|
## What to Tell Your User
|
|
29
40
|
|
|
41
|
+
Your replies' safety check now runs on the fastest available engine instead of
|
|
42
|
+
the slowest, so it stops timing out under load — one fewer cause of slow or
|
|
43
|
+
missing replies. Background checks are unchanged. If only one non-Claude engine is
|
|
44
|
+
installed, nothing changes.
|
|
45
|
+
|
|
30
46
|
When the machine is busy, your reply's safety check now jumps to a reserved slot instead
|
|
31
47
|
of waiting behind background work — fewer slow/held replies under load. The crash
|
|
32
48
|
protection is exactly as strong as before. Most setups see no change (it's off on the
|
|
@@ -41,6 +57,12 @@ follow-up. Off on the fleet for now.
|
|
|
41
57
|
|
|
42
58
|
## Summary of New Capabilities
|
|
43
59
|
|
|
60
|
+
- The latency-sensitive `gate` category defaults to the fastest active off-Claude
|
|
61
|
+
framework (`LATENCY_SENSITIVE_FRAMEWORK_PREFERENCE`), not the codex-first order.
|
|
62
|
+
- `sentinel`/`reflector`/`job`/`other` routing and `failureSwap` are unchanged.
|
|
63
|
+
- An explicit `categories.gate` in config always overrides the computed default.
|
|
64
|
+
- Single-off-Claude-framework agents and claude-only agents: byte-identical no-op.
|
|
65
|
+
|
|
44
66
|
- `attribution.lane:'interactive'` requests reserved headroom — honored ONLY for an
|
|
45
67
|
allowlisted, user-blocking seam (the operator-facing tone gate); everything else stays
|
|
46
68
|
background.
|
|
@@ -58,6 +80,16 @@ follow-up. Off on the fleet for now.
|
|
|
58
80
|
|
|
59
81
|
## Evidence
|
|
60
82
|
|
|
83
|
+
- `internalFrameworkDefault.test.ts`: gate prefers fastest (pi) while sentinel
|
|
84
|
+
stays codex; pi-down→gemini (the gemini-serves-when-pi-down case); both-down→codex
|
|
85
|
+
(never worse than today); single-framework→no divergence. 17 unit tests pass.
|
|
86
|
+
- `provider-fallback-default-routing.test.ts` (integration): the gate component on
|
|
87
|
+
`GET /intelligence/routing` reports the fastest active framework. 3 pass.
|
|
88
|
+
- `provider-fallback-default-policy-lifecycle.test.ts` (e2e): route alive, policy
|
|
89
|
+
live. `tsc --noEmit` clean. 24 affected tests green.
|
|
90
|
+
- Side-effects review: `upgrades/side-effects/latency-sensitive-gate-framework.md`.
|
|
91
|
+
- Spec amendment: `docs/specs/provider-fallback-default-policy.md` §4.1.
|
|
92
|
+
|
|
61
93
|
- `hostSpawnSemaphore-priority.test.ts` (10): symmetric reserve, OOM floor unconditional,
|
|
62
94
|
garbage-lane→background-never-dropped, clamp (N=1/N=2/oversized/0), off=byte-identical.
|
|
63
95
|
- `spawn-cap-provider-lane.test.ts` (7): allowlist downgrade (CoherenceReviewer→background),
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Side-Effects Review — Latency-Sensitive Gate Framework Default
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `latency-sensitive-gate-framework`
|
|
4
|
+
**Date:** `2026-06-26`
|
|
5
|
+
**Author:** `Echo (instar-dev agent)`
|
|
6
|
+
**Tier:** 1 (small, localized; one pure resolver function + its tests + docs)
|
|
7
|
+
|
|
8
|
+
## Summary
|
|
9
|
+
|
|
10
|
+
The provider-fallback default policy routes internal components off-Claude via a
|
|
11
|
+
single codex-first preference chain (`codex-cli → pi-cli → gemini-cli →
|
|
12
|
+
claude-code`). The `gate` category — which includes the **user-facing
|
|
13
|
+
`MessagingToneGate`**, a synchronous check a human is waiting on — inherited that
|
|
14
|
+
codex-first primary. But `codex-cli` is the SLOWEST off-Claude framework (~30s),
|
|
15
|
+
which exceeds the 20s outbound-gate review budget and times the gate out (the
|
|
16
|
+
2026-06-25 silent-outbound class). This change gives the `gate` category a
|
|
17
|
+
SEPARATE, speed-ranked order (`LATENCY_SENSITIVE_FRAMEWORK_PREFERENCE = pi →
|
|
18
|
+
gemini → codex → claude`) so it defaults to the FASTEST active off-Claude
|
|
19
|
+
framework. `sentinel`/`reflector` (background) keep codex-first; `failureSwap` and
|
|
20
|
+
all other categories are unchanged.
|
|
21
|
+
|
|
22
|
+
## The 8 questions
|
|
23
|
+
|
|
24
|
+
1. **Over-block** — N/A. This is not a gate; it selects which backend computes the
|
|
25
|
+
tone-gate verdict. It rejects nothing.
|
|
26
|
+
2. **Under-block** — N/A. The tone gate's block/allow logic and its deterministic
|
|
27
|
+
degrade floor (F4) are byte-identical; only the LLM backend that produces the
|
|
28
|
+
verdict changes. A faster backend means FEWER budget-timeout degrades, i.e.
|
|
29
|
+
*more* real verdicts, not fewer.
|
|
30
|
+
3. **Level-of-abstraction fit** — Correct. The change lives in the one pure policy
|
|
31
|
+
resolver (`resolveInternalFrameworkDefault`) that already computes per-category
|
|
32
|
+
primaries; `ComponentFrameworksConfig.categories` is already a per-category map,
|
|
33
|
+
so no routing-engine change is needed. The router consumes the config unchanged.
|
|
34
|
+
4. **Signal vs authority** — No authority added. The resolver is a pure function
|
|
35
|
+
(active-set → config); it holds no blocking power. The tone gate's authority
|
|
36
|
+
(hold/send) is untouched. Complies with `docs/signal-vs-authority.md`.
|
|
37
|
+
5. **Interactions** — The gate's PRIMARY now differs from `sentinel`/`reflector`.
|
|
38
|
+
`failureSwap` is the shared tail (`active.slice(1)`, codex-first); for a gate
|
|
39
|
+
whose primary is `pi`, the tail may list `pi` first (the just-tried framework) —
|
|
40
|
+
harmless: the failure-swap walk is circuit-checked, so a just-failed/open
|
|
41
|
+
provider is skipped. When only one off-Claude framework is active, `gatePrimary
|
|
42
|
+
=== active[0]` (byte-identical no-op). No double-fire, no shadowing.
|
|
43
|
+
6. **External surfaces** — `GET /intelligence/routing` now reports the gate
|
|
44
|
+
component on a (possibly) different framework than sentinels. That is the
|
|
45
|
+
intended, visible effect. No new route, no schema change.
|
|
46
|
+
7. **Multi-machine posture** — **Machine-local BY DESIGN.** The default policy is
|
|
47
|
+
computed per-agent at boot from that agent's own active-framework set (which
|
|
48
|
+
frameworks' CLIs are installed/configured on THAT machine). No replication, no
|
|
49
|
+
cross-machine coupling. Each machine independently resolves the fastest gate
|
|
50
|
+
backend it has. Correct — framework availability is inherently per-machine.
|
|
51
|
+
8. **Rollback cost** — Trivial. Revert the commit (one source file + tests + one
|
|
52
|
+
doc amendment). No state, no migration. An operator who wants the gate back on
|
|
53
|
+
codex sets `categories.gate` explicitly (the explicit config always wins over
|
|
54
|
+
the computed default). A single-off-Claude-framework agent is unaffected.
|
|
55
|
+
|
|
56
|
+
## What it does NOT do
|
|
57
|
+
|
|
58
|
+
- Does NOT change the tone gate's verdict/hold/send logic or the F4 degrade floor.
|
|
59
|
+
- Does NOT touch `sentinel`/`reflector`/`job`/`other` routing, or `failureSwap`.
|
|
60
|
+
- Does NOT introduce a measured latency model — the ranking (pi < gemini < codex)
|
|
61
|
+
is a documented static assertion from observed behavior (~6s / ~9-13s / ~30s),
|
|
62
|
+
owned in `LATENCY_SENSITIVE_FRAMEWORK_PREFERENCE` with a unit-tested enum guard.
|
|
63
|
+
- Does NOT revoke the codex-first operator directive — it narrows it to exclude the
|
|
64
|
+
one latency-sensitive, user-blocking category.
|
|
65
|
+
|
|
66
|
+
## Second-pass note (outbound-path touch)
|
|
67
|
+
|
|
68
|
+
This touches the OUTBOUND tone-gate path, which is a Phase-5 trigger area. The
|
|
69
|
+
substantive review point: the change adds NO block/allow authority — it only
|
|
70
|
+
selects a faster backend for an existing gate, and the gate's safety behavior
|
|
71
|
+
(including the deterministic degrade floor on backend failure) is unchanged. The
|
|
72
|
+
decision boundary (gate diverges to fastest; background stays codex-first; single-
|
|
73
|
+
framework is a no-op) is covered by the new unit + integration tests. A full
|
|
74
|
+
independent reviewer was judged unnecessary for an authority-free routing-default
|
|
75
|
+
change; the PR is the review surface.
|
|
76
|
+
|
|
77
|
+
## Rollback
|
|
78
|
+
|
|
79
|
+
Revert the commit. No migration, no state.
|