@event4u/agent-config 14.2.0 → 14.4.0
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/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +286 -218
- package/agents/templates/.ai-council.yml.example +35 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +83 -12
- package/dist/agent-src/rules/roadmap-progress-sync.md +48 -4
- package/dist/agent-src/scripts/resume_probe.ts +154 -9
- package/dist/agent-src/scripts/roadmap_gates.ts +210 -6
- package/dist/agent-src/skills/roadmap-management/SKILL.md +9 -4
- package/dist/agent-src/templates/agent-settings.md +70 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/scripts/telemetry/remote.ts +571 -0
- package/dist/agent-src/templates/scripts/telemetry/settings.ts +222 -44
- package/dist/cli/python/workspace_drive.js +8 -3
- package/dist/cli/python/workspace_drive.js.map +1 -1
- package/dist/cli/python/workspace_hosts.js +16 -12
- package/dist/cli/python/workspace_hosts.js.map +1 -1
- package/dist/cli/registry.js +2 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/{chunk-F3YUF7SA.js → chunk-3UCJWMMP.js} +1 -1
- package/dist/cli-delegate/chunk-F7DQWYR5.js +69 -0
- package/dist/cli-delegate/{chunk-7PZ4FSZB.js → chunk-FBKL6JWT.js} +61 -2
- package/dist/cli-delegate/{chunk-MNWRDMR5.js → chunk-PKOBQADP.js} +1 -1
- package/dist/cli-delegate/cmd_conformance.js +26 -11
- package/dist/cli-delegate/cmd_doctor.js +2 -2
- package/dist/cli-delegate/cmd_handoff.js +3 -3
- package/dist/cli-delegate/cmd_route_audit.js +2 -2
- package/dist/cli-delegate/cmd_settings_set.js +17 -3
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +4 -4
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +3684 -1719
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1070 -408
- package/dist/scripts/_lib/host_launch.js +66 -0
- package/dist/scripts/_lib/host_launch.js.map +1 -0
- package/dist/server/io/yamlIO.js +175 -3
- package/dist/server/io/yamlIO.js.map +1 -1
- package/dist/server/routes/wizard.js +20 -1
- package/dist/server/routes/wizard.js.map +1 -1
- package/dist/shared/settingsConsent.js +25 -0
- package/dist/shared/settingsConsent.js.map +1 -1
- package/docs/contracts/settings-classes.md +11 -0
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +2 -1
- package/package.json +1 -1
- package/src/agent-src/scripts/resume_probe.ts +154 -9
- package/src/agent-src/scripts/roadmap_gates.ts +210 -6
- package/src/agent-src/templates/scripts/telemetry/remote.ts +571 -0
- package/src/agent-src/templates/scripts/telemetry/settings.ts +222 -44
- package/src/config/estate-count-budget.json +120 -0
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +32 -4
- package/src/config/gate-violation-baselines.json +63 -63
- package/src/config/gitignore-block.txt +5 -0
- package/src/config/hook-latency-budget.json +40 -1
- package/src/config/hook-token-budget.json +16 -0
- package/src/config/rule-stub-ceilings.json +11 -3
- package/src/scripts/_dispatch.bash +42 -1
- package/src/scripts/_lib/council_fallback_posture.ts +81 -0
- package/src/scripts/_lib/council_fallback_wiring.ts +126 -0
- package/src/scripts/_lib/council_settings_block.ts +152 -0
- package/src/scripts/_lib/headless_invocation.ts +285 -0
- package/src/scripts/_lib/host_launch.ts +72 -0
- package/src/scripts/_lib/map_to_object.ts +16 -0
- package/src/scripts/_lib/roadmap_checkboxes.ts +88 -0
- package/src/scripts/_lib/run_checkpoint.ts +409 -0
- package/src/scripts/_lib/session_register.ts +32 -1
- package/src/scripts/_lib/stdin.ts +35 -1
- package/src/scripts/_lib/turn_end_refusals.ts +12 -4
- package/src/scripts/_lib/unattended_guard.ts +371 -0
- package/src/scripts/ai_council/config.ts +27 -1
- package/src/scripts/ai_council/events_log.ts +12 -1
- package/src/scripts/ai_council/fallback_config.ts +114 -0
- package/src/scripts/ai_council/mid_flight_fallback.ts +295 -0
- package/src/scripts/ai_council/orchestrator.ts +251 -292
- package/src/scripts/ai_council/py_parity.ts +139 -0
- package/src/scripts/ai_council/response_render.ts +99 -0
- package/src/scripts/ai_council/spend_gate.ts +123 -0
- package/src/scripts/ai_council/transport_resolver.ts +81 -13
- package/src/scripts/bench_hook_injection.ts +100 -6
- package/src/scripts/bench_hook_latency.ts +442 -16
- package/src/scripts/check_estate_count.ts +924 -0
- package/src/scripts/compile_hook_manifest.ts +67 -0
- package/src/scripts/council_cli.ts +100 -125
- package/src/scripts/decision_memo.ts +325 -0
- package/src/scripts/hook_manifest.json +1 -0
- package/src/scripts/hook_manifest.yaml +172 -25
- package/src/scripts/hooks/concern_registry.ts +6 -0
- package/src/scripts/hooks/dispatch_hook.ts +183 -10
- package/src/scripts/hooks/dispatch_issues.ts +26 -0
- package/src/scripts/hooks/end_review_nudge_hook.ts +97 -24
- package/src/scripts/hooks/hook_stdin.ts +111 -5
- package/src/scripts/hooks/injection_budget.ts +595 -0
- package/src/scripts/hooks/payload_stub.ts +446 -0
- package/src/scripts/hooks/run_continuation_hook.ts +627 -0
- package/src/scripts/hooks/session_eol_hook.ts +52 -0
- package/src/scripts/hooks/telemetry_usage_hook.ts +339 -0
- package/src/scripts/hooks/tool_result_bytes_hook.ts +27 -0
- package/src/scripts/hooks/turn_end_gate_hook.ts +45 -7
- package/src/scripts/hooks_doctor.ts +16 -2
- package/src/scripts/interruption_report.ts +330 -13
- package/src/scripts/lint_hook_manifest.ts +167 -0
- package/src/scripts/roadmap_progress_hook.ts +254 -46
- package/src/scripts/run_supervise.ts +623 -0
- package/src/scripts/session_register_hook.ts +108 -8
- package/src/scripts/sessions_cli.ts +18 -6
- package/src/scripts/telemetry_disclosure_hook.ts +244 -0
- package/src/server/io/yamlIO.ts +167 -3
- package/src/shared/settingsConsent.ts +49 -2
- package/dist/cli-delegate/chunk-MMJL4TIX.js +0 -18
package/dist/mcp/server.mjs
CHANGED
|
@@ -12987,22 +12987,78 @@ var init_memory_lookup = __esm({
|
|
|
12987
12987
|
}
|
|
12988
12988
|
});
|
|
12989
12989
|
|
|
12990
|
-
// src/scripts/
|
|
12990
|
+
// src/scripts/_lib/stdin.ts
|
|
12991
12991
|
import * as fs13 from "node:fs";
|
|
12992
|
+
function _sleepSync(ms) {
|
|
12993
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
12994
|
+
}
|
|
12995
|
+
function readStdinText(fd = 0, opts = {}) {
|
|
12996
|
+
const chunks = [];
|
|
12997
|
+
const buf = Buffer.alloc(CHUNK);
|
|
12998
|
+
let retries = 0;
|
|
12999
|
+
let got_any = false;
|
|
13000
|
+
const first_byte_deadline = opts.firstByteTimeoutMs === void 0 ? null : Date.now() + opts.firstByteTimeoutMs;
|
|
13001
|
+
for (; ; ) {
|
|
13002
|
+
let read;
|
|
13003
|
+
try {
|
|
13004
|
+
read = fs13.readSync(fd, buf, 0, CHUNK, null);
|
|
13005
|
+
retries = 0;
|
|
13006
|
+
} catch (exc) {
|
|
13007
|
+
const code = exc.code;
|
|
13008
|
+
if (code === "EAGAIN") {
|
|
13009
|
+
if (!got_any && first_byte_deadline !== null && Date.now() >= first_byte_deadline) {
|
|
13010
|
+
return "";
|
|
13011
|
+
}
|
|
13012
|
+
retries += 1;
|
|
13013
|
+
if (retries > MAX_RETRIES) {
|
|
13014
|
+
throw new Error(
|
|
13015
|
+
`readStdinText: stdin stayed unreadable across ${String(MAX_RETRIES)} retries (~${String(MAX_RETRIES * RETRY_SLEEP_MS / 1e3)}s). Refusing to report an empty read as empty input.`
|
|
13016
|
+
);
|
|
13017
|
+
}
|
|
13018
|
+
_sleepSync(RETRY_SLEEP_MS);
|
|
13019
|
+
continue;
|
|
13020
|
+
}
|
|
13021
|
+
if (code === "EOF") break;
|
|
13022
|
+
throw exc;
|
|
13023
|
+
}
|
|
13024
|
+
if (read === 0) break;
|
|
13025
|
+
got_any = true;
|
|
13026
|
+
chunks.push(Buffer.from(buf.subarray(0, read)));
|
|
13027
|
+
}
|
|
13028
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
13029
|
+
}
|
|
13030
|
+
var CHUNK, RETRY_SLEEP_MS, MAX_RETRIES;
|
|
13031
|
+
var init_stdin = __esm({
|
|
13032
|
+
"src/scripts/_lib/stdin.ts"() {
|
|
13033
|
+
"use strict";
|
|
13034
|
+
CHUNK = 64 * 1024;
|
|
13035
|
+
RETRY_SLEEP_MS = 5;
|
|
13036
|
+
MAX_RETRIES = 2e3;
|
|
13037
|
+
}
|
|
13038
|
+
});
|
|
13039
|
+
|
|
13040
|
+
// src/scripts/hooks/hook_stdin.ts
|
|
13041
|
+
import * as tty from "node:tty";
|
|
13042
|
+
function readFd0ToEnd() {
|
|
13043
|
+
void process.stdin;
|
|
13044
|
+
return readStdinText(0, { firstByteTimeoutMs: HOOK_FIRST_BYTE_TIMEOUT_MS });
|
|
13045
|
+
}
|
|
12992
13046
|
function readHookStdin() {
|
|
12993
13047
|
if (_override !== null) return _override;
|
|
12994
13048
|
try {
|
|
12995
|
-
if (
|
|
12996
|
-
return
|
|
13049
|
+
if (tty.isatty(0)) return "";
|
|
13050
|
+
return readFd0ToEnd();
|
|
12997
13051
|
} catch {
|
|
12998
13052
|
return "";
|
|
12999
13053
|
}
|
|
13000
13054
|
}
|
|
13001
|
-
var _override;
|
|
13055
|
+
var _override, HOOK_FIRST_BYTE_TIMEOUT_MS;
|
|
13002
13056
|
var init_hook_stdin = __esm({
|
|
13003
13057
|
"src/scripts/hooks/hook_stdin.ts"() {
|
|
13004
13058
|
"use strict";
|
|
13059
|
+
init_stdin();
|
|
13005
13060
|
_override = null;
|
|
13061
|
+
HOOK_FIRST_BYTE_TIMEOUT_MS = 25;
|
|
13006
13062
|
}
|
|
13007
13063
|
});
|
|
13008
13064
|
|
|
@@ -20475,7 +20531,7 @@ import {
|
|
|
20475
20531
|
fsyncSync,
|
|
20476
20532
|
mkdirSync as mkdirSync8,
|
|
20477
20533
|
openSync,
|
|
20478
|
-
readFileSync as
|
|
20534
|
+
readFileSync as readFileSync21,
|
|
20479
20535
|
renameSync as renameSync4,
|
|
20480
20536
|
unlinkSync as unlinkSync2,
|
|
20481
20537
|
writeSync
|
|
@@ -20512,7 +20568,7 @@ function atomicWriteFile(target, data, options = {}) {
|
|
|
20512
20568
|
function atomicAppendLine(target, line) {
|
|
20513
20569
|
let existing = "";
|
|
20514
20570
|
try {
|
|
20515
|
-
existing =
|
|
20571
|
+
existing = readFileSync21(target, "utf8");
|
|
20516
20572
|
} catch {
|
|
20517
20573
|
existing = "";
|
|
20518
20574
|
}
|
|
@@ -26081,7 +26137,13 @@ var init_events_log = __esm({
|
|
|
26081
26137
|
"proceed",
|
|
26082
26138
|
"skip_necessity",
|
|
26083
26139
|
"block_quota",
|
|
26084
|
-
"quorum_result"
|
|
26140
|
+
"quorum_result",
|
|
26141
|
+
// A seat lost its cli transport mid-pass and was retried on the metered
|
|
26142
|
+
// api rung. Without this action, attendance analysis cannot tell a seat
|
|
26143
|
+
// SAVED by the fallback from a seat that was natively api all along — the
|
|
26144
|
+
// two are indistinguishable in the response set, and only one of them
|
|
26145
|
+
// costs money that the operator did not plan.
|
|
26146
|
+
"transport_fallback"
|
|
26085
26147
|
]);
|
|
26086
26148
|
_KILL_SWITCH_ENV = "AGENT_CONFIG_NO_EVENTS_LOG";
|
|
26087
26149
|
_HERE15 = fileURLToPath28(import.meta.url);
|
|
@@ -28101,6 +28163,46 @@ Type your follow-up question, end with a line containing only: ${this._end_marke
|
|
|
28101
28163
|
}
|
|
28102
28164
|
});
|
|
28103
28165
|
|
|
28166
|
+
// src/scripts/ai_council/fallback_config.ts
|
|
28167
|
+
function buildFallback(raw, d) {
|
|
28168
|
+
if (!d.isDict(raw)) return { api_on_quota: false };
|
|
28169
|
+
const v = raw["api_on_quota"];
|
|
28170
|
+
if (v === void 0) return { api_on_quota: false };
|
|
28171
|
+
if (!d.isBool(v)) {
|
|
28172
|
+
throw d.error(
|
|
28173
|
+
`\`fallback.api_on_quota\`=${d.repr(v)} must be a boolean (got ${d.typeName(v)}).`
|
|
28174
|
+
);
|
|
28175
|
+
}
|
|
28176
|
+
return { api_on_quota: v };
|
|
28177
|
+
}
|
|
28178
|
+
function buildSecondModel(entry, cls, locked, d) {
|
|
28179
|
+
if (!("second_model" in entry)) return null;
|
|
28180
|
+
if (locked.has(cls)) {
|
|
28181
|
+
throw d.error(
|
|
28182
|
+
`decision_resolution.classes.${cls}.second_model=${d.repr(entry["second_model"])}: a second-model rung is not configurable for high-impact / user-required decisions \u2014 those classes are LOCKED to \`user\` (Iron Law) and never resolve on a model of any kind.`
|
|
28183
|
+
);
|
|
28184
|
+
}
|
|
28185
|
+
const raw = entry["second_model"];
|
|
28186
|
+
if (raw === null) return null;
|
|
28187
|
+
if (!(d.isStr(raw) && SECOND_MODEL_PROVIDERS.has(raw))) {
|
|
28188
|
+
throw d.error(
|
|
28189
|
+
`decision_resolution.classes.${cls}.second_model=${d.repr(raw)} not in ${d.sortedListRepr(SECOND_MODEL_PROVIDERS)} \u2014 the rung must be a provider whose local CLI runs under subscription auth, so a resolution can never become metered USD spend.`
|
|
28190
|
+
);
|
|
28191
|
+
}
|
|
28192
|
+
return raw;
|
|
28193
|
+
}
|
|
28194
|
+
var SECOND_MODEL_PROVIDERS;
|
|
28195
|
+
var init_fallback_config = __esm({
|
|
28196
|
+
"src/scripts/ai_council/fallback_config.ts"() {
|
|
28197
|
+
"use strict";
|
|
28198
|
+
SECOND_MODEL_PROVIDERS = /* @__PURE__ */ new Set([
|
|
28199
|
+
"anthropic",
|
|
28200
|
+
"openai",
|
|
28201
|
+
"gemini"
|
|
28202
|
+
]);
|
|
28203
|
+
}
|
|
28204
|
+
});
|
|
28205
|
+
|
|
28104
28206
|
// src/scripts/ai_council/config.ts
|
|
28105
28207
|
var config_exports = {};
|
|
28106
28208
|
__export(config_exports, {
|
|
@@ -28403,6 +28505,7 @@ function _build_config(raw, source_path) {
|
|
|
28403
28505
|
const quorum_min_present = _build_quorum_min_present(
|
|
28404
28506
|
_get(raw, "quorum_min_present", SOLO_FLOOR_MIN_PRESENT)
|
|
28405
28507
|
);
|
|
28508
|
+
const fallback = buildFallback(_get(raw, "fallback", {}), _FALLBACK_DEPS);
|
|
28406
28509
|
const necessity_classifier = _build_necessity_classifier(
|
|
28407
28510
|
_asDict(_getOr(raw, "necessity_classifier", {}))
|
|
28408
28511
|
);
|
|
@@ -28452,6 +28555,7 @@ function _build_config(raw, source_path) {
|
|
|
28452
28555
|
cli_call_budget,
|
|
28453
28556
|
quorum,
|
|
28454
28557
|
quorum_min_present,
|
|
28558
|
+
fallback,
|
|
28455
28559
|
necessity_classifier,
|
|
28456
28560
|
model_downgrade,
|
|
28457
28561
|
debate,
|
|
@@ -28718,7 +28822,13 @@ function _build_decision_resolution(d) {
|
|
|
28718
28822
|
`decision_resolution.classes.${cls}.confidence_threshold must be in [0.0, 1.0] (got ${_pyRepr6(_f(threshold))}).`
|
|
28719
28823
|
);
|
|
28720
28824
|
}
|
|
28721
|
-
|
|
28825
|
+
const second_model = buildSecondModel(
|
|
28826
|
+
entry_raw,
|
|
28827
|
+
cls,
|
|
28828
|
+
_LOCKED_IMPACT_CLASSES,
|
|
28829
|
+
_FALLBACK_DEPS
|
|
28830
|
+
);
|
|
28831
|
+
classes.set(cls, { mode, confidence_threshold: threshold, second_model });
|
|
28722
28832
|
}
|
|
28723
28833
|
const fast_path_raw = _getOr(d, "fast_path", {});
|
|
28724
28834
|
if (!_isDict(fast_path_raw)) {
|
|
@@ -29377,7 +29487,7 @@ function _pyTruthy3(value) {
|
|
|
29377
29487
|
}
|
|
29378
29488
|
return Object.keys(value).length > 0;
|
|
29379
29489
|
}
|
|
29380
|
-
var import_yaml5, _VALID_PROVIDERS, _RAW_KEY_PREFIXES, CouncilConfigError, _Float, _VALID_NECESSITY_MODES, _VALID_DISCLOSURE_MODES, _VALID_CHAIRMAN_MODES, COUNCIL_CONFIG_RELNAME, COUNCIL_CONFIG_USER_GLOBAL_REL, COUNCIL_CONFIG_ENV, _VALID_CRITIC_PROTOCOLS, _VALID_RESOLUTION_MODES, _IMPACT_CLASSES, _LOCKED_IMPACT_CLASSES, _DEFAULT_RESOLUTION_MODES, _VALID_MEMBER_MODES, _VALID_DISPATCH_MODES, DEFAULT_CLI_CALLS_PER_DAY2;
|
|
29490
|
+
var import_yaml5, _VALID_PROVIDERS, _FALLBACK_DEPS, _RAW_KEY_PREFIXES, CouncilConfigError, _Float, _VALID_NECESSITY_MODES, _VALID_DISCLOSURE_MODES, _VALID_CHAIRMAN_MODES, COUNCIL_CONFIG_RELNAME, COUNCIL_CONFIG_USER_GLOBAL_REL, COUNCIL_CONFIG_ENV, _VALID_CRITIC_PROTOCOLS, _VALID_RESOLUTION_MODES, _IMPACT_CLASSES, _LOCKED_IMPACT_CLASSES, _DEFAULT_RESOLUTION_MODES, _VALID_MEMBER_MODES, _VALID_DISPATCH_MODES, DEFAULT_CLI_CALLS_PER_DAY2;
|
|
29381
29491
|
var init_config = __esm({
|
|
29382
29492
|
"src/scripts/ai_council/config.ts"() {
|
|
29383
29493
|
"use strict";
|
|
@@ -29386,6 +29496,7 @@ var init_config = __esm({
|
|
|
29386
29496
|
init_cli_call_budget();
|
|
29387
29497
|
init_clients();
|
|
29388
29498
|
init_quorum();
|
|
29499
|
+
init_fallback_config();
|
|
29389
29500
|
_VALID_PROVIDERS = /* @__PURE__ */ new Set([
|
|
29390
29501
|
"anthropic",
|
|
29391
29502
|
"openai",
|
|
@@ -29393,6 +29504,15 @@ var init_config = __esm({
|
|
|
29393
29504
|
"xai",
|
|
29394
29505
|
"perplexity"
|
|
29395
29506
|
]);
|
|
29507
|
+
_FALLBACK_DEPS = {
|
|
29508
|
+
isDict: _isDict,
|
|
29509
|
+
isBool: _isBool,
|
|
29510
|
+
isStr: _isStr,
|
|
29511
|
+
repr: _pyRepr6,
|
|
29512
|
+
typeName: _pyTypeName,
|
|
29513
|
+
sortedListRepr: _sortedListRepr,
|
|
29514
|
+
error: (msg) => new CouncilConfigError(msg)
|
|
29515
|
+
};
|
|
29396
29516
|
_RAW_KEY_PREFIXES = [
|
|
29397
29517
|
"sk-",
|
|
29398
29518
|
"sk-ant-",
|
|
@@ -30035,7 +30155,15 @@ function classifyCliFailure(raw) {
|
|
|
30035
30155
|
if (s === "cli_unsupported" || s === "unsupported" || s === "parse_failed") {
|
|
30036
30156
|
return "cli_unsupported";
|
|
30037
30157
|
}
|
|
30038
|
-
if (s.startsWith("model_unservable") ||
|
|
30158
|
+
if (s.startsWith("model_unservable") || // The token the PRODUCERS actually write. R2 round 6, finding 4:
|
|
30159
|
+
// `clients.ts` emits `model_unsupported_on_transport` at both sites
|
|
30160
|
+
// (the pre-spend gate at :1857 and the turn-failed path at :2002) and
|
|
30161
|
+
// puts the vendor sentence in `metadata.detail`, never in `error` — so
|
|
30162
|
+
// the class matched nothing a caller could produce and the contract's
|
|
30163
|
+
// fourth eligible class was dead. The token is matched here rather
|
|
30164
|
+
// than renamed at the producers because `code:` values reach the
|
|
30165
|
+
// events log and a rename would break every reader of the history.
|
|
30166
|
+
s.startsWith("model_unsupported_on_transport") || s.includes("is not supported when using codex")) {
|
|
30039
30167
|
return "model_unservable";
|
|
30040
30168
|
}
|
|
30041
30169
|
if (s === "timeout") return "timeout";
|
|
@@ -30043,6 +30171,10 @@ function classifyCliFailure(raw) {
|
|
|
30043
30171
|
if (/^exit_5\d\d$/.test(s) || s === "server_error" || s === "os") return "server_error";
|
|
30044
30172
|
return "other";
|
|
30045
30173
|
}
|
|
30174
|
+
function isFallbackEligibleUnder(failure, policy) {
|
|
30175
|
+
if (FALLBACK_ELIGIBLE.has(failure)) return true;
|
|
30176
|
+
return policy.apiOnQuota && failure === "quota_exhausted";
|
|
30177
|
+
}
|
|
30046
30178
|
function absentReasonFromCliFailure(failure) {
|
|
30047
30179
|
switch (failure) {
|
|
30048
30180
|
case "binary_missing":
|
|
@@ -30057,7 +30189,7 @@ function absentReasonFromCliFailure(failure) {
|
|
|
30057
30189
|
return null;
|
|
30058
30190
|
}
|
|
30059
30191
|
}
|
|
30060
|
-
var VALID_TRANSPORT_MODES, CLI_AUTH_SOURCES, KEY_AUTH_SOURCES;
|
|
30192
|
+
var VALID_TRANSPORT_MODES, CLI_AUTH_SOURCES, KEY_AUTH_SOURCES, FALLBACK_ELIGIBLE, DEFAULT_FALLBACK_POLICY, MidFlightFallback;
|
|
30061
30193
|
var init_transport_resolver = __esm({
|
|
30062
30194
|
"src/scripts/ai_council/transport_resolver.ts"() {
|
|
30063
30195
|
"use strict";
|
|
@@ -30071,6 +30203,50 @@ var init_transport_resolver = __esm({
|
|
|
30071
30203
|
]);
|
|
30072
30204
|
CLI_AUTH_SOURCES = /* @__PURE__ */ new Set(["cli-subscription", "cli-api-key"]);
|
|
30073
30205
|
KEY_AUTH_SOURCES = /* @__PURE__ */ new Set(["key-file", "env-key"]);
|
|
30206
|
+
FALLBACK_ELIGIBLE = /* @__PURE__ */ new Set([
|
|
30207
|
+
"binary_missing",
|
|
30208
|
+
"auth_rejected",
|
|
30209
|
+
"cli_unsupported",
|
|
30210
|
+
// `model_unservable` satisfies the same no-double-charge property in both
|
|
30211
|
+
// of its shapes: the pre-spend gate refuses before any subprocess exists,
|
|
30212
|
+
// and the call-time shape is a provider 400 — rejected at the request
|
|
30213
|
+
// boundary, no generation performed.
|
|
30214
|
+
"model_unservable"
|
|
30215
|
+
]);
|
|
30216
|
+
DEFAULT_FALLBACK_POLICY = { apiOnQuota: false };
|
|
30217
|
+
MidFlightFallback = class {
|
|
30218
|
+
used = /* @__PURE__ */ new Set();
|
|
30219
|
+
/** `'api'` to retry on the api rung, `'stop'` to surface the failure. */
|
|
30220
|
+
attempt(provider, failure, policy = DEFAULT_FALLBACK_POLICY) {
|
|
30221
|
+
if (!isFallbackEligibleUnder(failure, policy)) return "stop";
|
|
30222
|
+
if (this.used.has(provider)) return "stop";
|
|
30223
|
+
this.used.add(provider);
|
|
30224
|
+
return "api";
|
|
30225
|
+
}
|
|
30226
|
+
/**
|
|
30227
|
+
* Give a provider its one fallback back, because the twin never ran.
|
|
30228
|
+
*
|
|
30229
|
+
* R2 round 2, finding 8. `attempt` claims the slot at DECISION time, which
|
|
30230
|
+
* is correct — the claim is what stops a dead binary being retried once per
|
|
30231
|
+
* round. But a claim that is never CONSUMED must not stay spent: when the
|
|
30232
|
+
* projected-spend gate refuses the escalation, no api call happens, and
|
|
30233
|
+
* leaving the provider marked means the seat can never re-decide. Every
|
|
30234
|
+
* later round then re-spawns the dead cli binary and gets `'stop'`, which
|
|
30235
|
+
* is the exact per-round-ledger behaviour the invocation-scoped ledger was
|
|
30236
|
+
* chosen to avoid.
|
|
30237
|
+
*
|
|
30238
|
+
* Called ONLY on a path where the twin was built and then not called.
|
|
30239
|
+
* A provider that actually retried keeps its claim spent — that is the cap
|
|
30240
|
+
* working.
|
|
30241
|
+
*/
|
|
30242
|
+
release(provider) {
|
|
30243
|
+
this.used.delete(provider);
|
|
30244
|
+
}
|
|
30245
|
+
/** Providers that have already spent their one fallback. */
|
|
30246
|
+
spent() {
|
|
30247
|
+
return [...this.used].sort();
|
|
30248
|
+
}
|
|
30249
|
+
};
|
|
30074
30250
|
}
|
|
30075
30251
|
});
|
|
30076
30252
|
|
|
@@ -33615,12 +33791,12 @@ var init_cmd_doctor = __esm({
|
|
|
33615
33791
|
});
|
|
33616
33792
|
|
|
33617
33793
|
// src/install/txlog.ts
|
|
33618
|
-
import { createReadStream, createWriteStream, existsSync as existsSync25, readFileSync as
|
|
33794
|
+
import { createReadStream, createWriteStream, existsSync as existsSync25, readFileSync as readFileSync43, renameSync as renameSync8, statSync as statSync32, unlinkSync as unlinkSync7 } from "node:fs";
|
|
33619
33795
|
function readRecentEntries(logPath) {
|
|
33620
33796
|
if (!existsSync25(logPath)) {
|
|
33621
33797
|
return [];
|
|
33622
33798
|
}
|
|
33623
|
-
const raw =
|
|
33799
|
+
const raw = readFileSync43(logPath, "utf8");
|
|
33624
33800
|
const lines = raw.split("\n").filter((l) => l.length > 0);
|
|
33625
33801
|
const tail = lines.slice(-RECOVERY_DEPTH_CAP);
|
|
33626
33802
|
const out = [];
|
|
@@ -33655,7 +33831,7 @@ var init_txlog = __esm({
|
|
|
33655
33831
|
});
|
|
33656
33832
|
|
|
33657
33833
|
// src/install/detect.ts
|
|
33658
|
-
import { existsSync as existsSync26, readFileSync as
|
|
33834
|
+
import { existsSync as existsSync26, readFileSync as readFileSync44, readdirSync as readdirSync28, statSync as statSync33 } from "node:fs";
|
|
33659
33835
|
import { join as join49, resolve as resolve30 } from "node:path";
|
|
33660
33836
|
function detectToolPresence(root) {
|
|
33661
33837
|
return {
|
|
@@ -35233,12 +35409,22 @@ function untrackedNonDocFiles(cwd) {
|
|
|
35233
35409
|
}
|
|
35234
35410
|
function untrackedFileLineCount(cwd, relPath) {
|
|
35235
35411
|
try {
|
|
35236
|
-
const
|
|
35237
|
-
|
|
35238
|
-
|
|
35239
|
-
|
|
35240
|
-
|
|
35241
|
-
|
|
35412
|
+
const abs = path59.resolve(cwd, relPath);
|
|
35413
|
+
const size = fs58.statSync(abs).size;
|
|
35414
|
+
if (size === 0) return 0;
|
|
35415
|
+
if (size > UNTRACKED_FILE_READ_CAP_BYTES) {
|
|
35416
|
+
return MUTATION_LINE_THRESHOLD + 1;
|
|
35417
|
+
}
|
|
35418
|
+
const buf = fs58.readFileSync(abs);
|
|
35419
|
+
if (buf.length === 0) return 0;
|
|
35420
|
+
const probe = buf.subarray(0, Math.min(buf.length, BINARY_PROBE_BYTES));
|
|
35421
|
+
if (probe.includes(0)) return 0;
|
|
35422
|
+
let lines = 0;
|
|
35423
|
+
for (const byte of buf) {
|
|
35424
|
+
if (byte === 10) lines += 1;
|
|
35425
|
+
}
|
|
35426
|
+
if (buf[buf.length - 1] !== 10) lines += 1;
|
|
35427
|
+
return lines;
|
|
35242
35428
|
} catch {
|
|
35243
35429
|
return 0;
|
|
35244
35430
|
}
|
|
@@ -35421,7 +35607,7 @@ function _isCliEntry21() {
|
|
|
35421
35607
|
return false;
|
|
35422
35608
|
}
|
|
35423
35609
|
}
|
|
35424
|
-
var MUTATION_LINE_THRESHOLD, UNTRACKED_FILE_CAP, TRANSCRIPT_SCAN_MAX_BYTES, EXIT_WARN2, DOC_PATH_RE, DISPATCH_TOOL_RE, REVIEW_SHAPED_LABEL_RE, REVIEW_SHAPED_PROMPT_RE, REVIEW_SKILL_NAME_RE;
|
|
35610
|
+
var MUTATION_LINE_THRESHOLD, UNTRACKED_FILE_CAP, TRANSCRIPT_SCAN_MAX_BYTES, EXIT_WARN2, DOC_PATH_RE, BINARY_PROBE_BYTES, UNTRACKED_FILE_READ_CAP_BYTES, DISPATCH_TOOL_RE, REVIEW_SHAPED_LABEL_RE, REVIEW_SHAPED_PROMPT_RE, REVIEW_SKILL_NAME_RE;
|
|
35425
35611
|
var init_end_review_nudge_hook = __esm({
|
|
35426
35612
|
"src/scripts/hooks/end_review_nudge_hook.ts"() {
|
|
35427
35613
|
"use strict";
|
|
@@ -35434,6 +35620,8 @@ var init_end_review_nudge_hook = __esm({
|
|
|
35434
35620
|
TRANSCRIPT_SCAN_MAX_BYTES = 50 * 1024 * 1024;
|
|
35435
35621
|
EXIT_WARN2 = 2;
|
|
35436
35622
|
DOC_PATH_RE = /\.md$/i;
|
|
35623
|
+
BINARY_PROBE_BYTES = 8e3;
|
|
35624
|
+
UNTRACKED_FILE_READ_CAP_BYTES = 8 * 1024 * 1024;
|
|
35437
35625
|
DISPATCH_TOOL_RE = /^(agent|task)$/i;
|
|
35438
35626
|
REVIEW_SHAPED_LABEL_RE = /\b(review|judge|adversarial|critique|second[- ]opinion|blind\s+(pass|review)|cross-model)\b/i;
|
|
35439
35627
|
REVIEW_SHAPED_PROMPT_RE = /\b(code\s+review|neutral\s+review|adversarial|judge|critique|second[- ]opinion|blind\s+(pass|review)|cross-model)\b/i;
|
|
@@ -36364,8 +36552,11 @@ function main25() {
|
|
|
36364
36552
|
dispatchOpen ? null : detectPromissory(lastAssistant),
|
|
36365
36553
|
detectLanguage(lastAssistant, readLanguagePin(workspaceRoot)),
|
|
36366
36554
|
detectUnverifiedEdit(toolCalls),
|
|
36367
|
-
// Round 7 § Phase 1 — detector D
|
|
36368
|
-
//
|
|
36555
|
+
// Round 7 § Phase 1 — detector D. It is NOT unconditional, and this
|
|
36556
|
+
// comment said it was while sitting one line above the `dispatchOpen`
|
|
36557
|
+
// ternary that conditions it: A and D are both excused by an open
|
|
36558
|
+
// dispatch, per the note at the top of this loop. Corrected 2026-08-18.
|
|
36559
|
+
// It shipped with its own settings flag one commit earlier
|
|
36369
36560
|
// and that flag is gone: `hooks.turn_end_gate.*` was deleted on
|
|
36370
36561
|
// 2026-08-12 because a default-off safety gate is an absent one. Its
|
|
36371
36562
|
// gating is where the comment above says gating belongs — inside the
|
|
@@ -39503,12 +39694,21 @@ var init_cmd_conformance = __esm({
|
|
|
39503
39694
|
var settings_exports = {};
|
|
39504
39695
|
__export(settings_exports, {
|
|
39505
39696
|
ALLOWED_GRANULARITIES: () => ALLOWED_GRANULARITIES,
|
|
39697
|
+
ALLOWED_REMOTE_FLUSH: () => ALLOWED_REMOTE_FLUSH,
|
|
39506
39698
|
DEFAULT_GRANULARITY: () => DEFAULT_GRANULARITY,
|
|
39507
39699
|
DEFAULT_LOG_PATH: () => DEFAULT_LOG_PATH,
|
|
39700
|
+
DEFAULT_REMOTE_FLUSH: () => DEFAULT_REMOTE_FLUSH,
|
|
39701
|
+
DEFAULT_REMOTE_LOG_PATH: () => DEFAULT_REMOTE_LOG_PATH,
|
|
39702
|
+
DEFAULT_REMOTE_RETENTION: () => DEFAULT_REMOTE_RETENTION,
|
|
39508
39703
|
DEFAULT_TIER_USAGE_LOG_PATH: () => DEFAULT_TIER_USAGE_LOG_PATH,
|
|
39509
39704
|
DEFAULT_TIER_USAGE_RETIER: () => DEFAULT_TIER_USAGE_RETIER,
|
|
39705
|
+
MIN_RETENTION_MAX_AGE_DAYS: () => MIN_RETENTION_MAX_AGE_DAYS,
|
|
39706
|
+
MIN_RETENTION_MAX_BYTES: () => MIN_RETENTION_MAX_BYTES,
|
|
39707
|
+
REMOTE_REQUIRED_FIELDS: () => REMOTE_REQUIRED_FIELDS,
|
|
39708
|
+
RemoteTelemetrySettings: () => RemoteTelemetrySettings,
|
|
39510
39709
|
TelemetrySettings: () => TelemetrySettings,
|
|
39511
39710
|
TierUsageSettings: () => TierUsageSettings,
|
|
39711
|
+
read_remote_settings: () => read_remote_settings,
|
|
39512
39712
|
read_settings: () => read_settings,
|
|
39513
39713
|
read_tier_usage_settings: () => read_tier_usage_settings
|
|
39514
39714
|
});
|
|
@@ -39555,30 +39755,34 @@ function _isFile13(p) {
|
|
|
39555
39755
|
return false;
|
|
39556
39756
|
}
|
|
39557
39757
|
}
|
|
39558
|
-
function
|
|
39559
|
-
|
|
39560
|
-
|
|
39561
|
-
|
|
39562
|
-
|
|
39563
|
-
|
|
39564
|
-
|
|
39565
|
-
|
|
39566
|
-
raw = {};
|
|
39567
|
-
}
|
|
39568
|
-
} catch {
|
|
39758
|
+
function _read_telemetry_section(p, key) {
|
|
39759
|
+
if (!_isFile13(p)) {
|
|
39760
|
+
return { section: {}, present: false };
|
|
39761
|
+
}
|
|
39762
|
+
let raw = {};
|
|
39763
|
+
try {
|
|
39764
|
+
raw = YAML8.parse(fs69.readFileSync(p, "utf-8"), { version: "1.1" });
|
|
39765
|
+
if (raw === null || raw === void 0) {
|
|
39569
39766
|
raw = {};
|
|
39570
39767
|
}
|
|
39571
|
-
|
|
39572
|
-
|
|
39573
|
-
|
|
39574
|
-
|
|
39575
|
-
|
|
39576
|
-
|
|
39577
|
-
|
|
39578
|
-
|
|
39579
|
-
|
|
39580
|
-
}
|
|
39768
|
+
} catch {
|
|
39769
|
+
raw = {};
|
|
39770
|
+
}
|
|
39771
|
+
if (!_isPlainObject8(raw)) {
|
|
39772
|
+
return { section: {}, present: false };
|
|
39773
|
+
}
|
|
39774
|
+
const tele = raw["telemetry"];
|
|
39775
|
+
if (!_isPlainObject8(tele)) {
|
|
39776
|
+
return { section: {}, present: false };
|
|
39581
39777
|
}
|
|
39778
|
+
const sub = tele[key];
|
|
39779
|
+
if (!_isPlainObject8(sub)) {
|
|
39780
|
+
return { section: {}, present: false };
|
|
39781
|
+
}
|
|
39782
|
+
return { section: sub, present: true };
|
|
39783
|
+
}
|
|
39784
|
+
function read_settings(p) {
|
|
39785
|
+
const { section, present: section_present } = _read_telemetry_section(p, "artifact_engagement");
|
|
39582
39786
|
const record = _isPlainObject8(section["record"]) ? section["record"] : {};
|
|
39583
39787
|
const output = _isPlainObject8(section["output"]) ? section["output"] : {};
|
|
39584
39788
|
return new TelemetrySettings({
|
|
@@ -39591,27 +39795,7 @@ function read_settings(p) {
|
|
|
39591
39795
|
});
|
|
39592
39796
|
}
|
|
39593
39797
|
function read_tier_usage_settings(p) {
|
|
39594
|
-
|
|
39595
|
-
if (_isFile13(p)) {
|
|
39596
|
-
let raw = {};
|
|
39597
|
-
try {
|
|
39598
|
-
raw = YAML8.parse(fs69.readFileSync(p, "utf-8"), { version: "1.1" });
|
|
39599
|
-
if (raw === null || raw === void 0) {
|
|
39600
|
-
raw = {};
|
|
39601
|
-
}
|
|
39602
|
-
} catch {
|
|
39603
|
-
raw = {};
|
|
39604
|
-
}
|
|
39605
|
-
if (_isPlainObject8(raw)) {
|
|
39606
|
-
const tele = raw["telemetry"];
|
|
39607
|
-
if (_isPlainObject8(tele)) {
|
|
39608
|
-
const tu = tele["tier_usage"];
|
|
39609
|
-
if (_isPlainObject8(tu)) {
|
|
39610
|
-
section = tu;
|
|
39611
|
-
}
|
|
39612
|
-
}
|
|
39613
|
-
}
|
|
39614
|
-
}
|
|
39798
|
+
const { section } = _read_telemetry_section(p, "tier_usage");
|
|
39615
39799
|
const output = _isPlainObject8(section["output"]) ? section["output"] : {};
|
|
39616
39800
|
const retier = _isPlainObject8(section["retier"]) ? section["retier"] : {};
|
|
39617
39801
|
const defaults = DEFAULT_TIER_USAGE_RETIER;
|
|
@@ -39632,7 +39816,39 @@ function read_tier_usage_settings(p) {
|
|
|
39632
39816
|
min_distinct_users: _coerce_int(retier["min_distinct_users"], defaults.min_distinct_users)
|
|
39633
39817
|
});
|
|
39634
39818
|
}
|
|
39635
|
-
|
|
39819
|
+
function read_remote_settings(p) {
|
|
39820
|
+
const { section } = _read_telemetry_section(p, "remote");
|
|
39821
|
+
const output = _isPlainObject8(section["output"]) ? section["output"] : {};
|
|
39822
|
+
const retention = _isPlainObject8(section["retention"]) ? section["retention"] : {};
|
|
39823
|
+
const _coerce_bounded_int = (value, def, floor) => {
|
|
39824
|
+
if (typeof value === "boolean") {
|
|
39825
|
+
return def;
|
|
39826
|
+
}
|
|
39827
|
+
if (typeof value === "number" && Number.isInteger(value) && value >= floor) {
|
|
39828
|
+
return value;
|
|
39829
|
+
}
|
|
39830
|
+
return def;
|
|
39831
|
+
};
|
|
39832
|
+
return new RemoteTelemetrySettings({
|
|
39833
|
+
enabled: _coerce_bool(section["enabled"], false),
|
|
39834
|
+
endpoint: _coerce_str(section["endpoint"], ""),
|
|
39835
|
+
org_id: _coerce_str(section["org_id"], ""),
|
|
39836
|
+
salt: _coerce_str(section["salt"], ""),
|
|
39837
|
+
flush: _coerce_str(section["flush"], DEFAULT_REMOTE_FLUSH, ALLOWED_REMOTE_FLUSH),
|
|
39838
|
+
log_path: _coerce_path(output["path"], DEFAULT_REMOTE_LOG_PATH),
|
|
39839
|
+
retention_max_age_days: _coerce_bounded_int(
|
|
39840
|
+
retention["max_age_days"],
|
|
39841
|
+
DEFAULT_REMOTE_RETENTION.max_age_days,
|
|
39842
|
+
MIN_RETENTION_MAX_AGE_DAYS
|
|
39843
|
+
),
|
|
39844
|
+
retention_max_bytes: _coerce_bounded_int(
|
|
39845
|
+
retention["max_bytes"],
|
|
39846
|
+
DEFAULT_REMOTE_RETENTION.max_bytes,
|
|
39847
|
+
MIN_RETENTION_MAX_BYTES
|
|
39848
|
+
)
|
|
39849
|
+
});
|
|
39850
|
+
}
|
|
39851
|
+
var YAML8, DEFAULT_LOG_PATH, DEFAULT_GRANULARITY, ALLOWED_GRANULARITIES, DEFAULT_TIER_USAGE_LOG_PATH, DEFAULT_TIER_USAGE_RETIER, TelemetrySettings, TierUsageSettings, DEFAULT_REMOTE_LOG_PATH, DEFAULT_REMOTE_FLUSH, ALLOWED_REMOTE_FLUSH, DEFAULT_REMOTE_RETENTION, MIN_RETENTION_MAX_AGE_DAYS, MIN_RETENTION_MAX_BYTES, REMOTE_REQUIRED_FIELDS, RemoteTelemetrySettings;
|
|
39636
39852
|
var init_settings = __esm({
|
|
39637
39853
|
"src/agent-src/templates/scripts/telemetry/settings.ts"() {
|
|
39638
39854
|
"use strict";
|
|
@@ -39679,6 +39895,62 @@ var init_settings = __esm({
|
|
|
39679
39895
|
this.min_distinct_users = init2.min_distinct_users;
|
|
39680
39896
|
}
|
|
39681
39897
|
};
|
|
39898
|
+
DEFAULT_REMOTE_LOG_PATH = ".agent-telemetry.jsonl";
|
|
39899
|
+
DEFAULT_REMOTE_FLUSH = "session-end";
|
|
39900
|
+
ALLOWED_REMOTE_FLUSH = ["session-end", "never"];
|
|
39901
|
+
DEFAULT_REMOTE_RETENTION = {
|
|
39902
|
+
max_age_days: 90,
|
|
39903
|
+
max_bytes: 2 * 1024 * 1024
|
|
39904
|
+
};
|
|
39905
|
+
MIN_RETENTION_MAX_AGE_DAYS = 1;
|
|
39906
|
+
MIN_RETENTION_MAX_BYTES = 4096;
|
|
39907
|
+
REMOTE_REQUIRED_FIELDS = ["endpoint", "org_id", "salt"];
|
|
39908
|
+
RemoteTelemetrySettings = class {
|
|
39909
|
+
/** The raw `enabled:` value. NOT the switch — see `active`. */
|
|
39910
|
+
enabled;
|
|
39911
|
+
endpoint;
|
|
39912
|
+
org_id;
|
|
39913
|
+
/** Org-pack secret. Never written into a record, never logged. */
|
|
39914
|
+
salt;
|
|
39915
|
+
flush;
|
|
39916
|
+
log_path;
|
|
39917
|
+
/**
|
|
39918
|
+
* Growth budget for `log_path`. Always present — an install that
|
|
39919
|
+
* declares no `retention:` gets the defaults rather than no policy,
|
|
39920
|
+
* because "unbounded" is the state R-A7 forbids and a settings file is
|
|
39921
|
+
* not a place to opt back into it.
|
|
39922
|
+
*/
|
|
39923
|
+
retention_max_age_days;
|
|
39924
|
+
retention_max_bytes;
|
|
39925
|
+
constructor(init2) {
|
|
39926
|
+
this.enabled = init2.enabled;
|
|
39927
|
+
this.endpoint = init2.endpoint;
|
|
39928
|
+
this.org_id = init2.org_id;
|
|
39929
|
+
this.salt = init2.salt;
|
|
39930
|
+
this.flush = init2.flush;
|
|
39931
|
+
this.log_path = init2.log_path;
|
|
39932
|
+
this.retention_max_age_days = init2.retention_max_age_days;
|
|
39933
|
+
this.retention_max_bytes = init2.retention_max_bytes;
|
|
39934
|
+
}
|
|
39935
|
+
/**
|
|
39936
|
+
* Which required fields are absent. Empty array + `enabled` ⇒ `active`.
|
|
39937
|
+
* Exposed so a doctor command can say WHICH field is missing without
|
|
39938
|
+
* printing the salt, rather than reporting a bare "disabled".
|
|
39939
|
+
*/
|
|
39940
|
+
get missing() {
|
|
39941
|
+
const out = [];
|
|
39942
|
+
for (const field of REMOTE_REQUIRED_FIELDS) {
|
|
39943
|
+
if (!this[field]) {
|
|
39944
|
+
out.push(field);
|
|
39945
|
+
}
|
|
39946
|
+
}
|
|
39947
|
+
return out;
|
|
39948
|
+
}
|
|
39949
|
+
/** The real switch: opted in AND fully configured by the org pack. */
|
|
39950
|
+
get active() {
|
|
39951
|
+
return this.enabled && this.missing.length === 0;
|
|
39952
|
+
}
|
|
39953
|
+
};
|
|
39682
39954
|
}
|
|
39683
39955
|
});
|
|
39684
39956
|
|
|
@@ -42152,6 +42424,242 @@ var init_qualification_wiring = __esm({
|
|
|
42152
42424
|
}
|
|
42153
42425
|
});
|
|
42154
42426
|
|
|
42427
|
+
// src/scripts/_lib/map_to_object.ts
|
|
42428
|
+
function _mapToObject(m) {
|
|
42429
|
+
const out = {};
|
|
42430
|
+
for (const [k, v] of m) {
|
|
42431
|
+
out[k] = v;
|
|
42432
|
+
}
|
|
42433
|
+
return out;
|
|
42434
|
+
}
|
|
42435
|
+
var init_map_to_object = __esm({
|
|
42436
|
+
"src/scripts/_lib/map_to_object.ts"() {
|
|
42437
|
+
"use strict";
|
|
42438
|
+
}
|
|
42439
|
+
});
|
|
42440
|
+
|
|
42441
|
+
// src/scripts/_lib/council_settings_block.ts
|
|
42442
|
+
function synthesizeAiCouncilBlock(cfg) {
|
|
42443
|
+
const members = {};
|
|
42444
|
+
for (const [name, m] of cfg.members) {
|
|
42445
|
+
const entry = { enabled: m.enabled, model: m.model };
|
|
42446
|
+
if (m.api_key_ref !== null) {
|
|
42447
|
+
entry["api_key_ref"] = m.api_key_ref;
|
|
42448
|
+
}
|
|
42449
|
+
if (m.mode !== null) {
|
|
42450
|
+
entry["mode"] = m.mode;
|
|
42451
|
+
}
|
|
42452
|
+
if (m.binary !== null) {
|
|
42453
|
+
entry["binary"] = m.binary;
|
|
42454
|
+
}
|
|
42455
|
+
if (m.model_ladder && m.model_ladder.length > 0) {
|
|
42456
|
+
entry["model_ladder"] = [...m.model_ladder];
|
|
42457
|
+
}
|
|
42458
|
+
if (m.prompt_cache_ttl !== "5m") {
|
|
42459
|
+
entry["prompt_cache_ttl"] = m.prompt_cache_ttl;
|
|
42460
|
+
}
|
|
42461
|
+
members[name] = entry;
|
|
42462
|
+
}
|
|
42463
|
+
const advisors = {};
|
|
42464
|
+
for (const [name, a] of cfg.advisors) {
|
|
42465
|
+
const entry = {
|
|
42466
|
+
enabled: a.enabled,
|
|
42467
|
+
member: a.member,
|
|
42468
|
+
persona: a.persona
|
|
42469
|
+
};
|
|
42470
|
+
if (a.model !== null) {
|
|
42471
|
+
entry["model"] = a.model;
|
|
42472
|
+
}
|
|
42473
|
+
advisors[name] = entry;
|
|
42474
|
+
}
|
|
42475
|
+
const lensCostDisclosure = {};
|
|
42476
|
+
for (const [lens, cd] of cfg.lens_overrides.cost_disclosure) {
|
|
42477
|
+
lensCostDisclosure[lens] = {
|
|
42478
|
+
mode: cd.mode,
|
|
42479
|
+
threshold_usd: cd.threshold_usd,
|
|
42480
|
+
show_per_member: cd.show_per_member
|
|
42481
|
+
};
|
|
42482
|
+
}
|
|
42483
|
+
const lensModelDowngrade = {};
|
|
42484
|
+
for (const [lens, md] of cfg.lens_overrides.model_downgrade) {
|
|
42485
|
+
lensModelDowngrade[lens] = { enabled: md.enabled, auto_apply: md.auto_apply };
|
|
42486
|
+
}
|
|
42487
|
+
return {
|
|
42488
|
+
enabled: cfg.enabled,
|
|
42489
|
+
mode: cfg.defaults.mode,
|
|
42490
|
+
min_rounds: cfg.defaults.min_rounds,
|
|
42491
|
+
deep_min_rounds: cfg.defaults.deep_min_rounds,
|
|
42492
|
+
max_output_tokens: cfg.defaults.max_output_tokens,
|
|
42493
|
+
session_retention_days: cfg.defaults.session_retention_days,
|
|
42494
|
+
debate_max_rounds: cfg.defaults.debate_max_rounds,
|
|
42495
|
+
cost_budget: {
|
|
42496
|
+
max_input_tokens: cfg.cost_budget.max_input_tokens,
|
|
42497
|
+
max_output_tokens: cfg.cost_budget.max_output_tokens,
|
|
42498
|
+
max_calls: cfg.cost_budget.max_calls,
|
|
42499
|
+
max_total_usd: cfg.cost_budget.max_total_usd,
|
|
42500
|
+
daily_limit_usd: cfg.cost_budget.daily_limit_usd
|
|
42501
|
+
},
|
|
42502
|
+
consensus_scoring: {
|
|
42503
|
+
enabled: cfg.consensus_scoring.enabled,
|
|
42504
|
+
strong_threshold: cfg.consensus_scoring.strong_threshold,
|
|
42505
|
+
minority_threshold: cfg.consensus_scoring.minority_threshold,
|
|
42506
|
+
lenses: [...cfg.consensus_scoring.lenses]
|
|
42507
|
+
},
|
|
42508
|
+
cli_call_budget: {
|
|
42509
|
+
max_calls_per_day: _mapToObject(cfg.cli_call_budget.max_calls_per_day),
|
|
42510
|
+
warn_at: cfg.cli_call_budget.warn_at
|
|
42511
|
+
},
|
|
42512
|
+
// Phase 3.3 (road-to-always-on-orchestration): was validated by
|
|
42513
|
+
// `_build_config`/`_build_quorum` but never forwarded into the
|
|
42514
|
+
// synthesized block, so `build_members` always saw `undefined` and
|
|
42515
|
+
// silently fell back to `'majority'` regardless of the user's
|
|
42516
|
+
// configured `quorum: <k>`. Additive key — callers that never read
|
|
42517
|
+
// it observe no change.
|
|
42518
|
+
quorum: cfg.quorum,
|
|
42519
|
+
// Forwarded for the same reason `quorum` above had to be: a key that
|
|
42520
|
+
// `_build_config` validates and this block drops is a key the loader
|
|
42521
|
+
// enforces and the runtime never sees. That defect shipped once here
|
|
42522
|
+
// already; repeating it for the shadow floor would silently pin every
|
|
42523
|
+
// `floor_would_hold` to the default no matter what the operator set.
|
|
42524
|
+
quorum_min_present: cfg.quorum_min_present,
|
|
42525
|
+
// Third instance of the same defect the two comments above describe,
|
|
42526
|
+
// and the most expensive of the three: `build_members` reads
|
|
42527
|
+
// `ai_council.fallback.api_on_quota` off THIS block, so before the key
|
|
42528
|
+
// was forwarded no config file could turn quota fall-through on. The
|
|
42529
|
+
// documentation, the contract section and the tests all described a
|
|
42530
|
+
// switch that production could not flip.
|
|
42531
|
+
fallback: { api_on_quota: cfg.fallback.api_on_quota },
|
|
42532
|
+
necessity_classifier: {
|
|
42533
|
+
enabled: cfg.necessity_classifier.enabled,
|
|
42534
|
+
mode: cfg.necessity_classifier.mode,
|
|
42535
|
+
user_explicit_mode: cfg.necessity_classifier.user_explicit_mode
|
|
42536
|
+
},
|
|
42537
|
+
model_downgrade: {
|
|
42538
|
+
enabled: cfg.model_downgrade.enabled,
|
|
42539
|
+
auto_apply: cfg.model_downgrade.auto_apply
|
|
42540
|
+
},
|
|
42541
|
+
debate: {
|
|
42542
|
+
max_cost_usd: cfg.debate.max_cost_usd,
|
|
42543
|
+
cost_disclosure: {
|
|
42544
|
+
mode: cfg.debate.cost_disclosure.mode,
|
|
42545
|
+
threshold_usd: cfg.debate.cost_disclosure.threshold_usd,
|
|
42546
|
+
show_per_member: cfg.debate.cost_disclosure.show_per_member
|
|
42547
|
+
}
|
|
42548
|
+
},
|
|
42549
|
+
lens_overrides: {
|
|
42550
|
+
necessity_classifier_mode: _mapToObject(
|
|
42551
|
+
cfg.lens_overrides.necessity_classifier_mode
|
|
42552
|
+
),
|
|
42553
|
+
necessity_classifier_user_explicit_mode: _mapToObject(
|
|
42554
|
+
cfg.lens_overrides.necessity_classifier_user_explicit_mode
|
|
42555
|
+
),
|
|
42556
|
+
model_downgrade: lensModelDowngrade,
|
|
42557
|
+
cost_disclosure: lensCostDisclosure
|
|
42558
|
+
},
|
|
42559
|
+
members,
|
|
42560
|
+
advisors
|
|
42561
|
+
};
|
|
42562
|
+
}
|
|
42563
|
+
var init_council_settings_block = __esm({
|
|
42564
|
+
"src/scripts/_lib/council_settings_block.ts"() {
|
|
42565
|
+
"use strict";
|
|
42566
|
+
init_map_to_object();
|
|
42567
|
+
}
|
|
42568
|
+
});
|
|
42569
|
+
|
|
42570
|
+
// src/scripts/_lib/council_fallback_posture.ts
|
|
42571
|
+
function fallbackPostureFor(input) {
|
|
42572
|
+
if (input.transport !== "cli") return "n/a";
|
|
42573
|
+
if (!input.hasApiRung) return "none";
|
|
42574
|
+
if (input.apiKeyRef !== null) return input.refResolves === true ? "api" : "none";
|
|
42575
|
+
if (input.keylessResolves === void 0) return "none";
|
|
42576
|
+
try {
|
|
42577
|
+
return input.keylessResolves() ? "api" : "none";
|
|
42578
|
+
} catch {
|
|
42579
|
+
return "none";
|
|
42580
|
+
}
|
|
42581
|
+
}
|
|
42582
|
+
function renderPostureLines(postures, apiOnQuota) {
|
|
42583
|
+
const live = postures.filter(([, p]) => p !== "n/a");
|
|
42584
|
+
if (live.length === 0) return [];
|
|
42585
|
+
const lines = live.map(
|
|
42586
|
+
([name, p]) => ` fallback ${name}: ` + (p === "api" ? "would fall back to api" : "no api rung \u2014 a lost cli transport loses the seat")
|
|
42587
|
+
);
|
|
42588
|
+
lines.push(
|
|
42589
|
+
` fallback quota api_on_quota: ${apiOnQuota ? "on" : "off"} \u2014 an exhausted cli quota ${apiOnQuota ? "MAY" : "may not"} retry on the metered rung`
|
|
42590
|
+
);
|
|
42591
|
+
return lines;
|
|
42592
|
+
}
|
|
42593
|
+
var init_council_fallback_posture = __esm({
|
|
42594
|
+
"src/scripts/_lib/council_fallback_posture.ts"() {
|
|
42595
|
+
"use strict";
|
|
42596
|
+
}
|
|
42597
|
+
});
|
|
42598
|
+
|
|
42599
|
+
// src/scripts/_lib/council_fallback_wiring.ts
|
|
42600
|
+
function isRefusal(exc) {
|
|
42601
|
+
if (exc instanceof CouncilConfigError) return true;
|
|
42602
|
+
return exc instanceof Error && REFUSAL_NAMES.has(exc.constructor.name);
|
|
42603
|
+
}
|
|
42604
|
+
function buildFallbackOptions(deps) {
|
|
42605
|
+
return {
|
|
42606
|
+
api_on_quota: deps.apiOnQuota,
|
|
42607
|
+
// The orchestrator is a pure library and holds no sink; this is it.
|
|
42608
|
+
// One line per establishing escalation, so attendance analysis can
|
|
42609
|
+
// tell a seat SAVED by the fallback from one that was natively api.
|
|
42610
|
+
on_event: (e) => {
|
|
42611
|
+
try {
|
|
42612
|
+
deps.emit({
|
|
42613
|
+
action: "transport_fallback",
|
|
42614
|
+
provider: e.provider,
|
|
42615
|
+
failure_class: e.failure,
|
|
42616
|
+
outcome: e.outcome,
|
|
42617
|
+
api_on_quota: e.api_on_quota
|
|
42618
|
+
});
|
|
42619
|
+
} catch {
|
|
42620
|
+
}
|
|
42621
|
+
},
|
|
42622
|
+
construct: (provider) => {
|
|
42623
|
+
if (!deps.hasApiRung(provider)) return null;
|
|
42624
|
+
const cfg = deps.memberConfig(provider);
|
|
42625
|
+
const model = deps.modelOverride(provider) ?? cfg["model"] ?? null;
|
|
42626
|
+
try {
|
|
42627
|
+
return deps.constructApi(provider, model, {
|
|
42628
|
+
api_key_ref: cfg["api_key_ref"] ?? null,
|
|
42629
|
+
enable_prompt_cache: cfg["prompt_cache"] !== false,
|
|
42630
|
+
prompt_cache_ttl: cfg["prompt_cache_ttl"]
|
|
42631
|
+
});
|
|
42632
|
+
} catch (exc) {
|
|
42633
|
+
if (isRefusal(exc)) return null;
|
|
42634
|
+
throw exc;
|
|
42635
|
+
}
|
|
42636
|
+
}
|
|
42637
|
+
};
|
|
42638
|
+
}
|
|
42639
|
+
var REFUSAL_NAMES;
|
|
42640
|
+
var init_council_fallback_wiring = __esm({
|
|
42641
|
+
"src/scripts/_lib/council_fallback_wiring.ts"() {
|
|
42642
|
+
"use strict";
|
|
42643
|
+
init_config();
|
|
42644
|
+
REFUSAL_NAMES = /* @__PURE__ */ new Set([
|
|
42645
|
+
"CouncilDisabledError",
|
|
42646
|
+
"CliClientError",
|
|
42647
|
+
"CouncilConfigError",
|
|
42648
|
+
// R2 round 6, critical finding 1 — and the docblock above already told the
|
|
42649
|
+
// story one name short. `KeyGateError` is what an api-twin construction
|
|
42650
|
+
// raises when the provider key is absent or violates the 0600 contract,
|
|
42651
|
+
// which is the ORDINARY shape of the very configuration this fallback
|
|
42652
|
+
// targets: a cli member under subscription auth, no `api_key_ref`, no
|
|
42653
|
+
// local key. It escaped `construct()`, escaped `consult()`, and is not in
|
|
42654
|
+
// `main`'s catch list — so instead of losing one seat, the whole pass died
|
|
42655
|
+
// with an unhandled exception. A mechanism that turns a recoverable seat
|
|
42656
|
+
// loss into a total loss is worse than no mechanism, which is the sentence
|
|
42657
|
+
// directly above this list.
|
|
42658
|
+
"KeyGateError"
|
|
42659
|
+
]);
|
|
42660
|
+
}
|
|
42661
|
+
});
|
|
42662
|
+
|
|
42155
42663
|
// src/scripts/ai_council/low_impact_corpus.ts
|
|
42156
42664
|
var low_impact_corpus_exports = {};
|
|
42157
42665
|
__export(low_impact_corpus_exports, {
|
|
@@ -44190,6 +44698,293 @@ var init_stance_tally = __esm({
|
|
|
44190
44698
|
}
|
|
44191
44699
|
});
|
|
44192
44700
|
|
|
44701
|
+
// src/scripts/ai_council/mid_flight_fallback.ts
|
|
44702
|
+
function establishTwin(input) {
|
|
44703
|
+
const { member, error, fallback, ledger } = input;
|
|
44704
|
+
const failure = classifyCliFailure(error);
|
|
44705
|
+
const policy = { apiOnQuota: fallback.api_on_quota };
|
|
44706
|
+
if (!isFallbackEligibleUnder(failure, policy)) return null;
|
|
44707
|
+
if (ledger.attempt(member.name, failure, policy) !== "api") return null;
|
|
44708
|
+
const twin = fallback.construct(member.name);
|
|
44709
|
+
if (twin === null) {
|
|
44710
|
+
fallback.on_event?.({
|
|
44711
|
+
provider: member.name,
|
|
44712
|
+
failure,
|
|
44713
|
+
outcome: "no_twin",
|
|
44714
|
+
api_on_quota: fallback.api_on_quota
|
|
44715
|
+
});
|
|
44716
|
+
return null;
|
|
44717
|
+
}
|
|
44718
|
+
return { client: twin, reason: failure, original_error: error };
|
|
44719
|
+
}
|
|
44720
|
+
function emitOutcome(fallback, provider, twin, outcome) {
|
|
44721
|
+
fallback.on_event?.({
|
|
44722
|
+
provider,
|
|
44723
|
+
failure: twin.reason,
|
|
44724
|
+
outcome,
|
|
44725
|
+
api_on_quota: fallback.api_on_quota
|
|
44726
|
+
});
|
|
44727
|
+
}
|
|
44728
|
+
function stampFallback(response, twin, sticky) {
|
|
44729
|
+
response.metadata = {
|
|
44730
|
+
...response.metadata ?? {},
|
|
44731
|
+
fallback_from: "cli",
|
|
44732
|
+
fallback_reason: twin.reason,
|
|
44733
|
+
fallback_original_error: twin.original_error,
|
|
44734
|
+
...sticky ? { fallback_sticky: true } : {}
|
|
44735
|
+
};
|
|
44736
|
+
}
|
|
44737
|
+
function isFailedCliCall(member, error, transport) {
|
|
44738
|
+
return error !== null && String(error) !== "" && transport === "cli";
|
|
44739
|
+
}
|
|
44740
|
+
function runGatedRetry(original, member, twin, fallback, deps, ledger = null) {
|
|
44741
|
+
if (!deps.gate(twin.client)) {
|
|
44742
|
+
original.metadata = { ...original.metadata ?? {}, fallback_skipped: "cost_budget" };
|
|
44743
|
+
emitOutcome(fallback, member.name, twin, "cost_budget");
|
|
44744
|
+
ledger?.release(member.name);
|
|
44745
|
+
return { response: original, effective: member, retried: false };
|
|
44746
|
+
}
|
|
44747
|
+
const response = deps.call(twin.client);
|
|
44748
|
+
stampFallback(response, twin, false);
|
|
44749
|
+
emitOutcome(fallback, member.name, twin, "retried");
|
|
44750
|
+
return { response, effective: twin.client, retried: true };
|
|
44751
|
+
}
|
|
44752
|
+
function escalateUnmetered(member, response, transport, fallback, ledger) {
|
|
44753
|
+
if (fallback === null || ledger === null) return null;
|
|
44754
|
+
if (!isFailedCliCall(member, response.error, transport)) return null;
|
|
44755
|
+
const twin = establishTwin({
|
|
44756
|
+
member,
|
|
44757
|
+
error: String(response.error),
|
|
44758
|
+
fallback,
|
|
44759
|
+
ledger
|
|
44760
|
+
});
|
|
44761
|
+
if (twin === null) return null;
|
|
44762
|
+
return twin;
|
|
44763
|
+
}
|
|
44764
|
+
function refuseUnmeteredEscalation(args) {
|
|
44765
|
+
const { original, declared, twin, fallback, ledger, twins } = args;
|
|
44766
|
+
original.metadata = { ...original.metadata ?? {}, fallback_skipped: "cost_budget" };
|
|
44767
|
+
if (fallback !== null) emitOutcome(fallback, declared.name, twin, "cost_budget");
|
|
44768
|
+
twins?.delete(declared.name);
|
|
44769
|
+
ledger?.release(declared.name);
|
|
44770
|
+
return original;
|
|
44771
|
+
}
|
|
44772
|
+
var init_mid_flight_fallback = __esm({
|
|
44773
|
+
"src/scripts/ai_council/mid_flight_fallback.ts"() {
|
|
44774
|
+
"use strict";
|
|
44775
|
+
init_transport_resolver();
|
|
44776
|
+
}
|
|
44777
|
+
});
|
|
44778
|
+
|
|
44779
|
+
// src/scripts/ai_council/spend_gate.ts
|
|
44780
|
+
function _total_usd(e) {
|
|
44781
|
+
return e.input_usd + e.output_usd;
|
|
44782
|
+
}
|
|
44783
|
+
function _breach(est, spent, budget) {
|
|
44784
|
+
const usd = est ? _total_usd(est) : 0;
|
|
44785
|
+
if (spent.input + (est ? est.input_tokens : 0) > budget.max_input_tokens || spent.output + (est ? est.output_tokens : 0) > budget.max_output_tokens) {
|
|
44786
|
+
return "tokens";
|
|
44787
|
+
}
|
|
44788
|
+
if (budget.daily_limit_usd > 0 && would_exceed(budget.daily_limit_usd, usd)) {
|
|
44789
|
+
return "daily";
|
|
44790
|
+
}
|
|
44791
|
+
if (budget.max_total_usd > 0 && spent.usd + usd > budget.max_total_usd) return "session";
|
|
44792
|
+
return null;
|
|
44793
|
+
}
|
|
44794
|
+
var CostBudget, OverrunEvent;
|
|
44795
|
+
var init_spend_gate = __esm({
|
|
44796
|
+
"src/scripts/ai_council/spend_gate.ts"() {
|
|
44797
|
+
"use strict";
|
|
44798
|
+
init_budget_guard();
|
|
44799
|
+
CostBudget = class {
|
|
44800
|
+
max_input_tokens;
|
|
44801
|
+
max_output_tokens;
|
|
44802
|
+
max_calls;
|
|
44803
|
+
max_total_usd;
|
|
44804
|
+
// 0 = USD ceiling disabled (token caps still apply)
|
|
44805
|
+
daily_limit_usd;
|
|
44806
|
+
// 0 = rolling 24h cap disabled (D3)
|
|
44807
|
+
constructor(args = {}) {
|
|
44808
|
+
this.max_input_tokens = args.max_input_tokens ?? 5e4;
|
|
44809
|
+
this.max_output_tokens = args.max_output_tokens ?? 2e4;
|
|
44810
|
+
this.max_calls = args.max_calls ?? 10;
|
|
44811
|
+
this.max_total_usd = args.max_total_usd ?? 0;
|
|
44812
|
+
this.daily_limit_usd = args.daily_limit_usd ?? 0;
|
|
44813
|
+
}
|
|
44814
|
+
};
|
|
44815
|
+
OverrunEvent = class {
|
|
44816
|
+
member_index;
|
|
44817
|
+
member;
|
|
44818
|
+
next_estimate;
|
|
44819
|
+
// this member's projected cost
|
|
44820
|
+
spent_input_tokens;
|
|
44821
|
+
// already-billed totals BEFORE this member
|
|
44822
|
+
spent_output_tokens;
|
|
44823
|
+
spent_usd;
|
|
44824
|
+
projected_total_usd;
|
|
44825
|
+
// spent_usd + next_estimate.total_usd
|
|
44826
|
+
daily_spent_usd;
|
|
44827
|
+
// rolling 24h spend BEFORE this member (D3)
|
|
44828
|
+
daily_limit_usd;
|
|
44829
|
+
// the configured daily cap (0 = disabled)
|
|
44830
|
+
breach_kind;
|
|
44831
|
+
// "session" | "daily" | "tokens"
|
|
44832
|
+
constructor(args) {
|
|
44833
|
+
this.member_index = args.member_index;
|
|
44834
|
+
this.member = args.member;
|
|
44835
|
+
this.next_estimate = args.next_estimate;
|
|
44836
|
+
this.spent_input_tokens = args.spent_input_tokens;
|
|
44837
|
+
this.spent_output_tokens = args.spent_output_tokens;
|
|
44838
|
+
this.spent_usd = args.spent_usd;
|
|
44839
|
+
this.projected_total_usd = args.projected_total_usd;
|
|
44840
|
+
this.daily_spent_usd = args.daily_spent_usd ?? 0;
|
|
44841
|
+
this.daily_limit_usd = args.daily_limit_usd ?? 0;
|
|
44842
|
+
this.breach_kind = args.breach_kind ?? "session";
|
|
44843
|
+
}
|
|
44844
|
+
};
|
|
44845
|
+
}
|
|
44846
|
+
});
|
|
44847
|
+
|
|
44848
|
+
// src/scripts/ai_council/py_parity.ts
|
|
44849
|
+
function _pyInt5(x) {
|
|
44850
|
+
return Math.trunc(x);
|
|
44851
|
+
}
|
|
44852
|
+
function _pyReprInt(x) {
|
|
44853
|
+
return String(x);
|
|
44854
|
+
}
|
|
44855
|
+
function _excTag(exc) {
|
|
44856
|
+
if (exc instanceof Error) {
|
|
44857
|
+
return `${exc.name}: ${exc.message}`;
|
|
44858
|
+
}
|
|
44859
|
+
return `Error: ${String(exc)}`;
|
|
44860
|
+
}
|
|
44861
|
+
function _setdefault(obj, key, value) {
|
|
44862
|
+
if (!(key in obj)) {
|
|
44863
|
+
obj[key] = value;
|
|
44864
|
+
}
|
|
44865
|
+
}
|
|
44866
|
+
function _metaGet(obj, key, fallback) {
|
|
44867
|
+
return key in obj ? obj[key] : fallback;
|
|
44868
|
+
}
|
|
44869
|
+
function _pyLStrip(s) {
|
|
44870
|
+
return s.replace(/^\s+/, "");
|
|
44871
|
+
}
|
|
44872
|
+
function _pyRStrip2(s) {
|
|
44873
|
+
return s.replace(/\s+$/, "");
|
|
44874
|
+
}
|
|
44875
|
+
function _pyLen5(s) {
|
|
44876
|
+
let n = 0;
|
|
44877
|
+
for (const _ of s) {
|
|
44878
|
+
n += 1;
|
|
44879
|
+
}
|
|
44880
|
+
return n;
|
|
44881
|
+
}
|
|
44882
|
+
function _pySlice(s, start, end) {
|
|
44883
|
+
return [...s].slice(start, end).join("");
|
|
44884
|
+
}
|
|
44885
|
+
function _pyFixed3(x, ndigits) {
|
|
44886
|
+
if (!Number.isFinite(x)) {
|
|
44887
|
+
return String(x);
|
|
44888
|
+
}
|
|
44889
|
+
const neg = x < 0 || Object.is(x, -0);
|
|
44890
|
+
const abs = Math.abs(x);
|
|
44891
|
+
const factor = Math.pow(10, ndigits);
|
|
44892
|
+
const scaled = abs * factor;
|
|
44893
|
+
const floor = Math.floor(scaled);
|
|
44894
|
+
const frac = scaled - floor;
|
|
44895
|
+
const tol = Math.max(Math.abs(scaled), 1) * 2 ** -40;
|
|
44896
|
+
let rounded;
|
|
44897
|
+
if (Math.abs(frac - 0.5) <= tol) {
|
|
44898
|
+
rounded = floor % 2 === 0 ? floor : floor + 1;
|
|
44899
|
+
} else {
|
|
44900
|
+
rounded = Math.round(scaled);
|
|
44901
|
+
}
|
|
44902
|
+
let intStr = String(rounded);
|
|
44903
|
+
let result;
|
|
44904
|
+
if (ndigits === 0) {
|
|
44905
|
+
result = intStr;
|
|
44906
|
+
} else {
|
|
44907
|
+
if (intStr.length <= ndigits) {
|
|
44908
|
+
intStr = "0".repeat(ndigits - intStr.length + 1) + intStr;
|
|
44909
|
+
}
|
|
44910
|
+
const whole = intStr.slice(0, intStr.length - ndigits);
|
|
44911
|
+
const dec = intStr.slice(intStr.length - ndigits);
|
|
44912
|
+
result = `${whole}.${dec}`;
|
|
44913
|
+
}
|
|
44914
|
+
return neg ? `-${result}` : result;
|
|
44915
|
+
}
|
|
44916
|
+
function _pyStrip5(s) {
|
|
44917
|
+
return s.trim();
|
|
44918
|
+
}
|
|
44919
|
+
function _pySplitWhitespace(s) {
|
|
44920
|
+
const trimmed = s.trim();
|
|
44921
|
+
if (trimmed === "") {
|
|
44922
|
+
return [];
|
|
44923
|
+
}
|
|
44924
|
+
return trimmed.split(/\s+/);
|
|
44925
|
+
}
|
|
44926
|
+
var init_py_parity = __esm({
|
|
44927
|
+
"src/scripts/ai_council/py_parity.ts"() {
|
|
44928
|
+
"use strict";
|
|
44929
|
+
}
|
|
44930
|
+
});
|
|
44931
|
+
|
|
44932
|
+
// src/scripts/ai_council/response_render.ts
|
|
44933
|
+
function renderResponseMeta(r, deps) {
|
|
44934
|
+
const meta_dict = r.metadata ?? {};
|
|
44935
|
+
const billable = Boolean(_metaGet(meta_dict, "billable", true));
|
|
44936
|
+
const estimated = Boolean(_metaGet(meta_dict, "tokens_estimated", false));
|
|
44937
|
+
const parts = [];
|
|
44938
|
+
if (!billable) {
|
|
44939
|
+
const label = _metaGet(meta_dict, "subscription_label", null) || "flat-rate";
|
|
44940
|
+
parts.push(`cost: subscription (${label})`);
|
|
44941
|
+
} else {
|
|
44942
|
+
const cost_usd = _metaGet(meta_dict, "cost_usd", void 0);
|
|
44943
|
+
if (typeof cost_usd === "number" && !(typeof cost_usd === "boolean")) {
|
|
44944
|
+
parts.push(`cost: $${deps.pyFixed(cost_usd, 4)}`);
|
|
44945
|
+
}
|
|
44946
|
+
const prefix = estimated ? "~" : "";
|
|
44947
|
+
parts.push(
|
|
44948
|
+
`tokens: ${prefix}${r.input_tokens} in / ${prefix}${r.output_tokens} out`
|
|
44949
|
+
);
|
|
44950
|
+
}
|
|
44951
|
+
parts.push(`${r.latency_ms} ms`);
|
|
44952
|
+
const fallback_from = _metaGet(meta_dict, "fallback_from", null);
|
|
44953
|
+
if (typeof fallback_from === "string" && fallback_from !== "") {
|
|
44954
|
+
const reason = _metaGet(meta_dict, "fallback_reason", null);
|
|
44955
|
+
const sticky = _metaGet(meta_dict, "fallback_sticky", false) === true;
|
|
44956
|
+
const why = typeof reason === "string" && reason !== "" ? `: ${reason}` : "";
|
|
44957
|
+
parts.push(
|
|
44958
|
+
sticky ? `transport: api (${fallback_from} lost earlier this pass${why})` : `transport: api (fell back from ${fallback_from}${why})`
|
|
44959
|
+
);
|
|
44960
|
+
}
|
|
44961
|
+
return `*${parts.join(" \xB7 ")}*`;
|
|
44962
|
+
}
|
|
44963
|
+
function callMember(client, question, opts, systemFor, excTag) {
|
|
44964
|
+
try {
|
|
44965
|
+
return opts.split ? client.ask_split(
|
|
44966
|
+
systemFor(client),
|
|
44967
|
+
opts.split.stable,
|
|
44968
|
+
opts.split.suffix,
|
|
44969
|
+
question.max_tokens
|
|
44970
|
+
) : client.ask(systemFor(client), question.user_prompt, question.max_tokens);
|
|
44971
|
+
} catch (exc) {
|
|
44972
|
+
return new CouncilResponse({
|
|
44973
|
+
provider: client.name,
|
|
44974
|
+
model: client.model,
|
|
44975
|
+
text: "",
|
|
44976
|
+
error: excTag(exc)
|
|
44977
|
+
});
|
|
44978
|
+
}
|
|
44979
|
+
}
|
|
44980
|
+
var init_response_render = __esm({
|
|
44981
|
+
"src/scripts/ai_council/response_render.ts"() {
|
|
44982
|
+
"use strict";
|
|
44983
|
+
init_clients();
|
|
44984
|
+
init_py_parity();
|
|
44985
|
+
}
|
|
44986
|
+
});
|
|
44987
|
+
|
|
44193
44988
|
// src/scripts/ai_council/blind_review.ts
|
|
44194
44989
|
import { createHash as createHash12 } from "node:crypto";
|
|
44195
44990
|
function _sha256_hex(s) {
|
|
@@ -44345,6 +45140,8 @@ __export(orchestrator_exports, {
|
|
|
44345
45140
|
DebateCostEstimate: () => DebateCostEstimate,
|
|
44346
45141
|
OverrunEvent: () => OverrunEvent,
|
|
44347
45142
|
PeerReviewResult: () => PeerReviewResult,
|
|
45143
|
+
_breach: () => _breach,
|
|
45144
|
+
_total_usd: () => _total_usd,
|
|
44348
45145
|
consult: () => consult,
|
|
44349
45146
|
estimate: () => estimate,
|
|
44350
45147
|
estimate_debate_cost: () => estimate_debate_cost,
|
|
@@ -44353,47 +45150,6 @@ __export(orchestrator_exports, {
|
|
|
44353
45150
|
run_debate: () => run_debate,
|
|
44354
45151
|
run_peer_review: () => run_peer_review
|
|
44355
45152
|
});
|
|
44356
|
-
function _pyFixed3(x, ndigits) {
|
|
44357
|
-
if (!Number.isFinite(x)) {
|
|
44358
|
-
return String(x);
|
|
44359
|
-
}
|
|
44360
|
-
const neg = x < 0 || Object.is(x, -0);
|
|
44361
|
-
const abs = Math.abs(x);
|
|
44362
|
-
const factor = Math.pow(10, ndigits);
|
|
44363
|
-
const scaled = abs * factor;
|
|
44364
|
-
const floor = Math.floor(scaled);
|
|
44365
|
-
const frac = scaled - floor;
|
|
44366
|
-
const tol = Math.max(Math.abs(scaled), 1) * 2 ** -40;
|
|
44367
|
-
let rounded;
|
|
44368
|
-
if (Math.abs(frac - 0.5) <= tol) {
|
|
44369
|
-
rounded = floor % 2 === 0 ? floor : floor + 1;
|
|
44370
|
-
} else {
|
|
44371
|
-
rounded = Math.round(scaled);
|
|
44372
|
-
}
|
|
44373
|
-
let intStr = String(rounded);
|
|
44374
|
-
let result;
|
|
44375
|
-
if (ndigits === 0) {
|
|
44376
|
-
result = intStr;
|
|
44377
|
-
} else {
|
|
44378
|
-
if (intStr.length <= ndigits) {
|
|
44379
|
-
intStr = "0".repeat(ndigits - intStr.length + 1) + intStr;
|
|
44380
|
-
}
|
|
44381
|
-
const whole = intStr.slice(0, intStr.length - ndigits);
|
|
44382
|
-
const dec = intStr.slice(intStr.length - ndigits);
|
|
44383
|
-
result = `${whole}.${dec}`;
|
|
44384
|
-
}
|
|
44385
|
-
return neg ? `-${result}` : result;
|
|
44386
|
-
}
|
|
44387
|
-
function _pyStrip5(s) {
|
|
44388
|
-
return s.trim();
|
|
44389
|
-
}
|
|
44390
|
-
function _pySplitWhitespace(s) {
|
|
44391
|
-
const trimmed = s.trim();
|
|
44392
|
-
if (trimmed === "") {
|
|
44393
|
-
return [];
|
|
44394
|
-
}
|
|
44395
|
-
return trimmed.split(/\s+/);
|
|
44396
|
-
}
|
|
44397
45153
|
function _getattr2(obj, name, fallback) {
|
|
44398
45154
|
if (obj === null || obj === void 0) {
|
|
44399
45155
|
return fallback;
|
|
@@ -44457,9 +45213,6 @@ function estimate_debate_cost(question, members, table, opts) {
|
|
|
44457
45213
|
subscription_members: sub_members
|
|
44458
45214
|
});
|
|
44459
45215
|
}
|
|
44460
|
-
function _total_usd(e) {
|
|
44461
|
-
return e.input_usd + e.output_usd;
|
|
44462
|
-
}
|
|
44463
45216
|
function estimate(question, members, table, opts = {}) {
|
|
44464
45217
|
const project = opts.project ?? null;
|
|
44465
45218
|
const original_ask = opts.original_ask ?? "";
|
|
@@ -44508,6 +45261,9 @@ function consult(members, question, budget = null, opts = {}) {
|
|
|
44508
45261
|
);
|
|
44509
45262
|
}
|
|
44510
45263
|
const spent = { input: 0, output: 0, usd: 0 };
|
|
45264
|
+
const cli_fallback = opts.cli_fallback ?? null;
|
|
45265
|
+
const fallback_ledger = cli_fallback !== null ? new MidFlightFallback() : null;
|
|
45266
|
+
const fallback_twins = cli_fallback !== null ? /* @__PURE__ */ new Map() : null;
|
|
44511
45267
|
let last_results = [];
|
|
44512
45268
|
let current_suffix = "";
|
|
44513
45269
|
const stance_tally = opts.stance_tally ?? false;
|
|
@@ -44530,6 +45286,9 @@ ${STANCE_LINE_CONTRACT}` : current_suffix;
|
|
|
44530
45286
|
project,
|
|
44531
45287
|
original_ask,
|
|
44532
45288
|
advisor_plans,
|
|
45289
|
+
cli_fallback,
|
|
45290
|
+
fallback_ledger,
|
|
45291
|
+
fallback_twins,
|
|
44533
45292
|
member_prompt_suffix: opts.member_prompt_suffix ?? null,
|
|
44534
45293
|
no_project_context_members: opts.no_project_context_members ?? null,
|
|
44535
45294
|
split: suffix_for_round ? { stable: question.user_prompt, suffix: suffix_for_round } : null
|
|
@@ -44564,7 +45323,10 @@ ${STANCE_LINE_CONTRACT}`,
|
|
|
44564
45323
|
on_overrun,
|
|
44565
45324
|
project,
|
|
44566
45325
|
original_ask,
|
|
44567
|
-
advisor_plans
|
|
45326
|
+
advisor_plans,
|
|
45327
|
+
cli_fallback,
|
|
45328
|
+
fallback_ledger,
|
|
45329
|
+
fallback_twins
|
|
44568
45330
|
});
|
|
44569
45331
|
const rep = rr[0];
|
|
44570
45332
|
if (rep !== void 0) {
|
|
@@ -44611,55 +45373,78 @@ ${suffix}` : base;
|
|
|
44611
45373
|
original_ask,
|
|
44612
45374
|
advisor_plans: opts.advisor_plans ?? null
|
|
44613
45375
|
}) : null;
|
|
45376
|
+
const twins = opts.fallback_twins ?? null;
|
|
44614
45377
|
for (let idx = 0; idx < members.length; idx++) {
|
|
44615
|
-
const
|
|
45378
|
+
const declared = members[idx];
|
|
45379
|
+
let established = twins?.get(declared.name) ?? null;
|
|
45380
|
+
const substituted_on_entry = established !== null;
|
|
45381
|
+
let member = established !== null ? established.client : declared;
|
|
45382
|
+
let unmetered_original = null;
|
|
45383
|
+
let unmetered_twin = null;
|
|
44616
45384
|
if (!_getattr2(member, "billable", true)) {
|
|
44617
|
-
let response2;
|
|
44618
|
-
|
|
44619
|
-
|
|
44620
|
-
|
|
44621
|
-
|
|
44622
|
-
|
|
44623
|
-
|
|
44624
|
-
|
|
44625
|
-
|
|
44626
|
-
|
|
44627
|
-
|
|
44628
|
-
);
|
|
44629
|
-
|
|
44630
|
-
|
|
44631
|
-
|
|
44632
|
-
|
|
44633
|
-
|
|
44634
|
-
|
|
44635
|
-
|
|
45385
|
+
let response2 = callMember(member, question, opts, _system_prompt_for_member, _excTag);
|
|
45386
|
+
const nb_twin = escalateUnmetered(
|
|
45387
|
+
member,
|
|
45388
|
+
response2,
|
|
45389
|
+
_getattr2(member, "transport", "api"),
|
|
45390
|
+
opts.cli_fallback ?? null,
|
|
45391
|
+
opts.fallback_ledger ?? null
|
|
45392
|
+
);
|
|
45393
|
+
const escalated = nb_twin !== null;
|
|
45394
|
+
if (nb_twin !== null) {
|
|
45395
|
+
established = nb_twin;
|
|
45396
|
+
twins?.set(member.name, nb_twin);
|
|
45397
|
+
member = nb_twin.client;
|
|
45398
|
+
unmetered_original = response2;
|
|
45399
|
+
unmetered_twin = nb_twin;
|
|
45400
|
+
}
|
|
45401
|
+
if (!escalated) {
|
|
45402
|
+
_stamp_transport_metadata(response2, member);
|
|
45403
|
+
results.push(response2);
|
|
45404
|
+
spent.input += response2.input_tokens;
|
|
45405
|
+
spent.output += response2.output_tokens;
|
|
45406
|
+
continue;
|
|
44636
45407
|
}
|
|
44637
|
-
|
|
44638
|
-
|
|
44639
|
-
|
|
44640
|
-
|
|
44641
|
-
|
|
44642
|
-
}
|
|
44643
|
-
const
|
|
44644
|
-
|
|
44645
|
-
|
|
44646
|
-
const proj_usd = spent.usd + (est ? _total_usd(est) : 0);
|
|
44647
|
-
const next_call_usd = est ? _total_usd(est) : 0;
|
|
44648
|
-
const breaches_tokens = proj_input > budget.max_input_tokens || proj_output > budget.max_output_tokens;
|
|
44649
|
-
const breaches_usd = budget.max_total_usd > 0 && proj_usd > budget.max_total_usd;
|
|
44650
|
-
const breaches_daily = budget.daily_limit_usd > 0 && would_exceed(budget.daily_limit_usd, next_call_usd);
|
|
44651
|
-
if (breaches_tokens || breaches_usd || breaches_daily) {
|
|
44652
|
-
const breach_kind = breaches_tokens ? "tokens" : breaches_daily ? "daily" : "session";
|
|
45408
|
+
}
|
|
45409
|
+
const est = established !== null && table !== null ? estimate(question, [member], table, {
|
|
45410
|
+
project,
|
|
45411
|
+
original_ask,
|
|
45412
|
+
advisor_plans: opts.advisor_plans ?? null
|
|
45413
|
+
})[0] : estimates ? estimates[idx] : null;
|
|
45414
|
+
const breach = _breach(est, spent, budget);
|
|
45415
|
+
if (breach !== null) {
|
|
45416
|
+
const breach_kind = breach;
|
|
44653
45417
|
const error_tag = breach_kind === "daily" ? "daily_budget_exceeded" : "cost_budget_exceeded";
|
|
45418
|
+
if (unmetered_original !== null && unmetered_twin !== null) {
|
|
45419
|
+
const refused = refuseUnmeteredEscalation({
|
|
45420
|
+
original: unmetered_original,
|
|
45421
|
+
declared,
|
|
45422
|
+
twin: unmetered_twin,
|
|
45423
|
+
fallback: opts.cli_fallback ?? null,
|
|
45424
|
+
ledger: opts.fallback_ledger ?? null,
|
|
45425
|
+
twins
|
|
45426
|
+
});
|
|
45427
|
+
_stamp_transport_metadata(refused, declared);
|
|
45428
|
+
results.push(refused);
|
|
45429
|
+
spent.input += refused.input_tokens;
|
|
45430
|
+
spent.output += refused.output_tokens;
|
|
45431
|
+
continue;
|
|
45432
|
+
}
|
|
44654
45433
|
if (on_overrun !== null && estimates !== null) {
|
|
44655
45434
|
const event = new OverrunEvent({
|
|
44656
45435
|
member_index: idx,
|
|
44657
45436
|
member,
|
|
44658
|
-
|
|
45437
|
+
// `est`, not `estimates[idx]`. The breach decision two
|
|
45438
|
+
// lines up was already re-priced for a substituted twin;
|
|
45439
|
+
// the event that ASKS the operator to approve it showed
|
|
45440
|
+
// the pre-loop row for the unmetered DECLARED seat, i.e. a
|
|
45441
|
+
// ~$0 next-call estimate for the very call the gate just
|
|
45442
|
+
// refused as over budget. R2 review, finding 8.
|
|
45443
|
+
next_estimate: est ?? estimates[idx],
|
|
44659
45444
|
spent_input_tokens: _pyInt5(spent.input),
|
|
44660
45445
|
spent_output_tokens: _pyInt5(spent.output),
|
|
44661
45446
|
spent_usd: spent.usd,
|
|
44662
|
-
projected_total_usd:
|
|
45447
|
+
projected_total_usd: spent.usd + (est ? _total_usd(est) : 0),
|
|
44663
45448
|
daily_spent_usd: budget.daily_limit_usd > 0 ? today_spend_usd() : 0,
|
|
44664
45449
|
daily_limit_usd: budget.daily_limit_usd,
|
|
44665
45450
|
breach_kind
|
|
@@ -44675,34 +45460,48 @@ ${suffix}` : base;
|
|
|
44675
45460
|
return results;
|
|
44676
45461
|
}
|
|
44677
45462
|
}
|
|
44678
|
-
|
|
44679
|
-
|
|
44680
|
-
|
|
44681
|
-
|
|
44682
|
-
|
|
44683
|
-
|
|
44684
|
-
|
|
44685
|
-
|
|
44686
|
-
|
|
44687
|
-
|
|
44688
|
-
|
|
44689
|
-
|
|
44690
|
-
|
|
44691
|
-
|
|
44692
|
-
provider: member.name,
|
|
44693
|
-
model: member.model,
|
|
44694
|
-
text: "",
|
|
44695
|
-
error: _excTag(exc)
|
|
45463
|
+
if (unmetered_twin !== null) {
|
|
45464
|
+
const fb = opts.cli_fallback ?? null;
|
|
45465
|
+
if (fb !== null) emitOutcome(fb, declared.name, unmetered_twin, "retried");
|
|
45466
|
+
}
|
|
45467
|
+
let response = callMember(member, question, opts, _system_prompt_for_member, _excTag);
|
|
45468
|
+
let effective = member;
|
|
45469
|
+
const fallback = opts.cli_fallback ?? null;
|
|
45470
|
+
const ledger = opts.fallback_ledger ?? null;
|
|
45471
|
+
if (fallback !== null && ledger !== null && isFailedCliCall(member, response.error, _getattr2(member, "transport", "api"))) {
|
|
45472
|
+
const twin = establishTwin({
|
|
45473
|
+
member,
|
|
45474
|
+
error: String(response.error),
|
|
45475
|
+
fallback,
|
|
45476
|
+
ledger
|
|
44696
45477
|
});
|
|
44697
|
-
|
|
45478
|
+
if (twin !== null) {
|
|
45479
|
+
const out = runGatedRetry(response, member, twin, fallback, {
|
|
45480
|
+
gate: (client) => table === null || _breach(
|
|
45481
|
+
estimate(question, [client], table, {
|
|
45482
|
+
project,
|
|
45483
|
+
original_ask,
|
|
45484
|
+
advisor_plans: opts.advisor_plans ?? null
|
|
45485
|
+
})[0],
|
|
45486
|
+
spent,
|
|
45487
|
+
budget
|
|
45488
|
+
) === null,
|
|
45489
|
+
call: (client) => callMember(client, question, opts, _system_prompt_for_member, _excTag)
|
|
45490
|
+
}, ledger);
|
|
45491
|
+
response = out.response;
|
|
45492
|
+
effective = out.effective;
|
|
45493
|
+
if (out.retried) twins?.set(member.name, twin);
|
|
45494
|
+
}
|
|
45495
|
+
}
|
|
45496
|
+
if (established !== null) stampFallback(response, established, substituted_on_entry);
|
|
44698
45497
|
results.push(response);
|
|
44699
45498
|
spent.input += response.input_tokens;
|
|
44700
45499
|
spent.output += response.output_tokens;
|
|
44701
45500
|
let actual_usd = null;
|
|
44702
45501
|
if (estimates !== null && table !== null) {
|
|
44703
45502
|
const actual = reprice_with_cache(
|
|
44704
|
-
|
|
44705
|
-
|
|
45503
|
+
effective.name,
|
|
45504
|
+
effective.model,
|
|
44706
45505
|
{
|
|
44707
45506
|
input_tokens: response.input_tokens,
|
|
44708
45507
|
cache_read_input_tokens: response.cache_read_input_tokens,
|
|
@@ -44715,14 +45514,14 @@ ${suffix}` : base;
|
|
|
44715
45514
|
actual_usd = _total_usd(actual);
|
|
44716
45515
|
spent.usd += _total_usd(actual);
|
|
44717
45516
|
if (budget.daily_limit_usd > 0 && !response.error) {
|
|
44718
|
-
record_spend(_total_usd(actual),
|
|
45517
|
+
record_spend(_total_usd(actual), effective.name, effective.model, {
|
|
44719
45518
|
cache_read_input_tokens: response.cache_read_input_tokens,
|
|
44720
45519
|
cache_creation_input_tokens: response.cache_creation_input_tokens,
|
|
44721
45520
|
cache_ttl: "5m"
|
|
44722
45521
|
});
|
|
44723
45522
|
}
|
|
44724
45523
|
}
|
|
44725
|
-
_stamp_transport_metadata(response,
|
|
45524
|
+
_stamp_transport_metadata(response, effective, actual_usd);
|
|
44726
45525
|
}
|
|
44727
45526
|
return results;
|
|
44728
45527
|
}
|
|
@@ -44902,6 +45701,9 @@ function run_debate(members, question, opts = {}) {
|
|
|
44902
45701
|
);
|
|
44903
45702
|
}
|
|
44904
45703
|
const spent = { input: 0, output: 0, usd: 0 };
|
|
45704
|
+
const cli_fallback = opts.cli_fallback ?? null;
|
|
45705
|
+
const fallback_ledger = cli_fallback !== null ? new MidFlightFallback() : null;
|
|
45706
|
+
const fallback_twins = cli_fallback !== null ? /* @__PURE__ */ new Map() : null;
|
|
44905
45707
|
const all_rounds = [];
|
|
44906
45708
|
let current_suffix = "";
|
|
44907
45709
|
let current_user_prompt = question.user_prompt;
|
|
@@ -44921,7 +45723,10 @@ ${question.user_prompt}`,
|
|
|
44921
45723
|
on_overrun,
|
|
44922
45724
|
project,
|
|
44923
45725
|
original_ask,
|
|
44924
|
-
advisor_plans
|
|
45726
|
+
advisor_plans,
|
|
45727
|
+
cli_fallback,
|
|
45728
|
+
fallback_ledger,
|
|
45729
|
+
fallback_twins
|
|
44925
45730
|
});
|
|
44926
45731
|
opts.on_restate?.(restated);
|
|
44927
45732
|
}
|
|
@@ -44944,6 +45749,9 @@ ${question.user_prompt}`,
|
|
|
44944
45749
|
project,
|
|
44945
45750
|
original_ask,
|
|
44946
45751
|
advisor_plans,
|
|
45752
|
+
cli_fallback,
|
|
45753
|
+
fallback_ledger,
|
|
45754
|
+
fallback_twins,
|
|
44947
45755
|
split: current_suffix ? { stable: question.user_prompt, suffix: current_suffix } : null
|
|
44948
45756
|
});
|
|
44949
45757
|
}
|
|
@@ -44960,7 +45768,16 @@ ${question.user_prompt}`,
|
|
|
44960
45768
|
}),
|
|
44961
45769
|
budget,
|
|
44962
45770
|
spent,
|
|
44963
|
-
{
|
|
45771
|
+
{
|
|
45772
|
+
table,
|
|
45773
|
+
on_overrun,
|
|
45774
|
+
project,
|
|
45775
|
+
original_ask,
|
|
45776
|
+
advisor_plans,
|
|
45777
|
+
cli_fallback,
|
|
45778
|
+
fallback_ledger,
|
|
45779
|
+
fallback_twins
|
|
45780
|
+
},
|
|
44964
45781
|
opts.on_repair ?? null
|
|
44965
45782
|
);
|
|
44966
45783
|
}
|
|
@@ -45209,27 +46026,6 @@ function run_consensus_scoring(members, deliberation_responses, opts = {}) {
|
|
|
45209
46026
|
scoring_responses
|
|
45210
46027
|
});
|
|
45211
46028
|
}
|
|
45212
|
-
function _render_response_meta(r) {
|
|
45213
|
-
const meta_dict = r.metadata ?? {};
|
|
45214
|
-
const billable = Boolean(_metaGet(meta_dict, "billable", true));
|
|
45215
|
-
const estimated = Boolean(_metaGet(meta_dict, "tokens_estimated", false));
|
|
45216
|
-
const parts = [];
|
|
45217
|
-
if (!billable) {
|
|
45218
|
-
const label = _metaGet(meta_dict, "subscription_label", null) || "flat-rate";
|
|
45219
|
-
parts.push(`cost: subscription (${label})`);
|
|
45220
|
-
} else {
|
|
45221
|
-
const cost_usd = _metaGet(meta_dict, "cost_usd", void 0);
|
|
45222
|
-
if (typeof cost_usd === "number" && !(typeof cost_usd === "boolean")) {
|
|
45223
|
-
parts.push(`cost: $${_pyFixed3(cost_usd, 4)}`);
|
|
45224
|
-
}
|
|
45225
|
-
const prefix = estimated ? "~" : "";
|
|
45226
|
-
parts.push(
|
|
45227
|
-
`tokens: ${prefix}${r.input_tokens} in / ${prefix}${r.output_tokens} out`
|
|
45228
|
-
);
|
|
45229
|
-
}
|
|
45230
|
-
parts.push(`${r.latency_ms} ms`);
|
|
45231
|
-
return `*${parts.join(" \xB7 ")}*`;
|
|
45232
|
-
}
|
|
45233
46029
|
function _default_explain_confidence(mode) {
|
|
45234
46030
|
if (mode === null) {
|
|
45235
46031
|
return true;
|
|
@@ -45260,7 +46056,7 @@ function render7(responses, opts = {}) {
|
|
|
45260
46056
|
*ERROR:* \`${r.error}\``);
|
|
45261
46057
|
continue;
|
|
45262
46058
|
}
|
|
45263
|
-
const meta =
|
|
46059
|
+
const meta = renderResponseMeta(r, { pyFixed: _pyFixed3 });
|
|
45264
46060
|
blocks.push(`${header}
|
|
45265
46061
|
|
|
45266
46062
|
${meta}
|
|
@@ -45452,43 +46248,7 @@ function _render_bucket(items, explain = true) {
|
|
|
45452
46248
|
}
|
|
45453
46249
|
return lines.join("\n");
|
|
45454
46250
|
}
|
|
45455
|
-
|
|
45456
|
-
return Math.trunc(x);
|
|
45457
|
-
}
|
|
45458
|
-
function _pyReprInt(x) {
|
|
45459
|
-
return String(x);
|
|
45460
|
-
}
|
|
45461
|
-
function _excTag(exc) {
|
|
45462
|
-
if (exc instanceof Error) {
|
|
45463
|
-
return `${exc.name}: ${exc.message}`;
|
|
45464
|
-
}
|
|
45465
|
-
return `Error: ${String(exc)}`;
|
|
45466
|
-
}
|
|
45467
|
-
function _setdefault(obj, key, value) {
|
|
45468
|
-
if (!(key in obj)) {
|
|
45469
|
-
obj[key] = value;
|
|
45470
|
-
}
|
|
45471
|
-
}
|
|
45472
|
-
function _metaGet(obj, key, fallback) {
|
|
45473
|
-
return key in obj ? obj[key] : fallback;
|
|
45474
|
-
}
|
|
45475
|
-
function _pyLStrip(s) {
|
|
45476
|
-
return s.replace(/^\s+/, "");
|
|
45477
|
-
}
|
|
45478
|
-
function _pyRStrip2(s) {
|
|
45479
|
-
return s.replace(/\s+$/, "");
|
|
45480
|
-
}
|
|
45481
|
-
function _pyLen5(s) {
|
|
45482
|
-
let n = 0;
|
|
45483
|
-
for (const _ of s) {
|
|
45484
|
-
n += 1;
|
|
45485
|
-
}
|
|
45486
|
-
return n;
|
|
45487
|
-
}
|
|
45488
|
-
function _pySlice(s, start, end) {
|
|
45489
|
-
return [...s].slice(start, end).join("");
|
|
45490
|
-
}
|
|
45491
|
-
var CostBudget, CouncilQuestion, OverrunEvent, DebateCostEstimate, DebateCheckpoint, DebateCapExceeded, PeerReviewResult, ConsensusResult, _DEFAULT_EXPLAIN_LENSES;
|
|
46251
|
+
var CouncilQuestion, DebateCostEstimate, DebateCheckpoint, DebateCapExceeded, PeerReviewResult, ConsensusResult, _DEFAULT_EXPLAIN_LENSES;
|
|
45492
46252
|
var init_orchestrator = __esm({
|
|
45493
46253
|
"src/scripts/ai_council/orchestrator.ts"() {
|
|
45494
46254
|
"use strict";
|
|
@@ -45499,25 +46259,15 @@ var init_orchestrator = __esm({
|
|
|
45499
46259
|
init_prompts2();
|
|
45500
46260
|
init_debate_gates();
|
|
45501
46261
|
init_stance_tally();
|
|
46262
|
+
init_transport_resolver();
|
|
46263
|
+
init_mid_flight_fallback();
|
|
46264
|
+
init_spend_gate();
|
|
46265
|
+
init_spend_gate();
|
|
46266
|
+
init_response_render();
|
|
46267
|
+
init_py_parity();
|
|
45502
46268
|
init_blind_review();
|
|
45503
46269
|
init_quorum();
|
|
45504
46270
|
init_handoff();
|
|
45505
|
-
CostBudget = class {
|
|
45506
|
-
max_input_tokens;
|
|
45507
|
-
max_output_tokens;
|
|
45508
|
-
max_calls;
|
|
45509
|
-
max_total_usd;
|
|
45510
|
-
// 0 = USD ceiling disabled (token caps still apply)
|
|
45511
|
-
daily_limit_usd;
|
|
45512
|
-
// 0 = rolling 24h cap disabled (D3)
|
|
45513
|
-
constructor(args = {}) {
|
|
45514
|
-
this.max_input_tokens = args.max_input_tokens ?? 5e4;
|
|
45515
|
-
this.max_output_tokens = args.max_output_tokens ?? 2e4;
|
|
45516
|
-
this.max_calls = args.max_calls ?? 10;
|
|
45517
|
-
this.max_total_usd = args.max_total_usd ?? 0;
|
|
45518
|
-
this.daily_limit_usd = args.daily_limit_usd ?? 0;
|
|
45519
|
-
}
|
|
45520
|
-
};
|
|
45521
46271
|
CouncilQuestion = class {
|
|
45522
46272
|
mode;
|
|
45523
46273
|
// one of: prompt, roadmap, diff, files
|
|
@@ -45530,36 +46280,6 @@ var init_orchestrator = __esm({
|
|
|
45530
46280
|
this.max_tokens = args.max_tokens ?? DEFAULT_MAX_TOKENS;
|
|
45531
46281
|
}
|
|
45532
46282
|
};
|
|
45533
|
-
OverrunEvent = class {
|
|
45534
|
-
member_index;
|
|
45535
|
-
member;
|
|
45536
|
-
next_estimate;
|
|
45537
|
-
// this member's projected cost
|
|
45538
|
-
spent_input_tokens;
|
|
45539
|
-
// already-billed totals BEFORE this member
|
|
45540
|
-
spent_output_tokens;
|
|
45541
|
-
spent_usd;
|
|
45542
|
-
projected_total_usd;
|
|
45543
|
-
// spent_usd + next_estimate.total_usd
|
|
45544
|
-
daily_spent_usd;
|
|
45545
|
-
// rolling 24h spend BEFORE this member (D3)
|
|
45546
|
-
daily_limit_usd;
|
|
45547
|
-
// the configured daily cap (0 = disabled)
|
|
45548
|
-
breach_kind;
|
|
45549
|
-
// "session" | "daily" | "tokens"
|
|
45550
|
-
constructor(args) {
|
|
45551
|
-
this.member_index = args.member_index;
|
|
45552
|
-
this.member = args.member;
|
|
45553
|
-
this.next_estimate = args.next_estimate;
|
|
45554
|
-
this.spent_input_tokens = args.spent_input_tokens;
|
|
45555
|
-
this.spent_output_tokens = args.spent_output_tokens;
|
|
45556
|
-
this.spent_usd = args.spent_usd;
|
|
45557
|
-
this.projected_total_usd = args.projected_total_usd;
|
|
45558
|
-
this.daily_spent_usd = args.daily_spent_usd ?? 0;
|
|
45559
|
-
this.daily_limit_usd = args.daily_limit_usd ?? 0;
|
|
45560
|
-
this.breach_kind = args.breach_kind ?? "session";
|
|
45561
|
-
}
|
|
45562
|
-
};
|
|
45563
46283
|
DebateCostEstimate = class {
|
|
45564
46284
|
rounds;
|
|
45565
46285
|
low_usd;
|
|
@@ -47091,7 +47811,7 @@ __export(council_cli_exports, {
|
|
|
47091
47811
|
_parse_model_overrides: () => _parse_model_overrides,
|
|
47092
47812
|
_parse_siblings_overrides: () => _parse_siblings_overrides,
|
|
47093
47813
|
_postRunQuorum: () => _postRunQuorum,
|
|
47094
|
-
_synthesize_ai_council_block: () =>
|
|
47814
|
+
_synthesize_ai_council_block: () => synthesizeAiCouncilBlock,
|
|
47095
47815
|
build_members: () => build_members,
|
|
47096
47816
|
build_question: () => build_question,
|
|
47097
47817
|
cmd_debate: () => cmd_debate,
|
|
@@ -47318,131 +48038,10 @@ function load_settings(p = SETTINGS_FILE2, opts = {}) {
|
|
|
47318
48038
|
const settings = load_agent_settings({ project_path: p });
|
|
47319
48039
|
if (fs78.existsSync(ai_council_path)) {
|
|
47320
48040
|
const cfg = load_council_config(ai_council_path);
|
|
47321
|
-
settings["ai_council"] =
|
|
48041
|
+
settings["ai_council"] = synthesizeAiCouncilBlock(cfg);
|
|
47322
48042
|
}
|
|
47323
48043
|
return settings;
|
|
47324
48044
|
}
|
|
47325
|
-
function _synthesize_ai_council_block(cfg) {
|
|
47326
|
-
const members = {};
|
|
47327
|
-
for (const [name, m] of cfg.members) {
|
|
47328
|
-
const entry = { enabled: m.enabled, model: m.model };
|
|
47329
|
-
if (m.api_key_ref !== null) {
|
|
47330
|
-
entry["api_key_ref"] = m.api_key_ref;
|
|
47331
|
-
}
|
|
47332
|
-
if (m.mode !== null) {
|
|
47333
|
-
entry["mode"] = m.mode;
|
|
47334
|
-
}
|
|
47335
|
-
if (m.binary !== null) {
|
|
47336
|
-
entry["binary"] = m.binary;
|
|
47337
|
-
}
|
|
47338
|
-
if (m.model_ladder && m.model_ladder.length > 0) {
|
|
47339
|
-
entry["model_ladder"] = [...m.model_ladder];
|
|
47340
|
-
}
|
|
47341
|
-
if (m.prompt_cache_ttl !== "5m") {
|
|
47342
|
-
entry["prompt_cache_ttl"] = m.prompt_cache_ttl;
|
|
47343
|
-
}
|
|
47344
|
-
members[name] = entry;
|
|
47345
|
-
}
|
|
47346
|
-
const advisors = {};
|
|
47347
|
-
for (const [name, a] of cfg.advisors) {
|
|
47348
|
-
const entry = {
|
|
47349
|
-
enabled: a.enabled,
|
|
47350
|
-
member: a.member,
|
|
47351
|
-
persona: a.persona
|
|
47352
|
-
};
|
|
47353
|
-
if (a.model !== null) {
|
|
47354
|
-
entry["model"] = a.model;
|
|
47355
|
-
}
|
|
47356
|
-
advisors[name] = entry;
|
|
47357
|
-
}
|
|
47358
|
-
const lensCostDisclosure = {};
|
|
47359
|
-
for (const [lens, cd] of cfg.lens_overrides.cost_disclosure) {
|
|
47360
|
-
lensCostDisclosure[lens] = {
|
|
47361
|
-
mode: cd.mode,
|
|
47362
|
-
threshold_usd: cd.threshold_usd,
|
|
47363
|
-
show_per_member: cd.show_per_member
|
|
47364
|
-
};
|
|
47365
|
-
}
|
|
47366
|
-
const lensModelDowngrade = {};
|
|
47367
|
-
for (const [lens, md] of cfg.lens_overrides.model_downgrade) {
|
|
47368
|
-
lensModelDowngrade[lens] = { enabled: md.enabled, auto_apply: md.auto_apply };
|
|
47369
|
-
}
|
|
47370
|
-
return {
|
|
47371
|
-
enabled: cfg.enabled,
|
|
47372
|
-
mode: cfg.defaults.mode,
|
|
47373
|
-
min_rounds: cfg.defaults.min_rounds,
|
|
47374
|
-
deep_min_rounds: cfg.defaults.deep_min_rounds,
|
|
47375
|
-
max_output_tokens: cfg.defaults.max_output_tokens,
|
|
47376
|
-
session_retention_days: cfg.defaults.session_retention_days,
|
|
47377
|
-
debate_max_rounds: cfg.defaults.debate_max_rounds,
|
|
47378
|
-
cost_budget: {
|
|
47379
|
-
max_input_tokens: cfg.cost_budget.max_input_tokens,
|
|
47380
|
-
max_output_tokens: cfg.cost_budget.max_output_tokens,
|
|
47381
|
-
max_calls: cfg.cost_budget.max_calls,
|
|
47382
|
-
max_total_usd: cfg.cost_budget.max_total_usd,
|
|
47383
|
-
daily_limit_usd: cfg.cost_budget.daily_limit_usd
|
|
47384
|
-
},
|
|
47385
|
-
consensus_scoring: {
|
|
47386
|
-
enabled: cfg.consensus_scoring.enabled,
|
|
47387
|
-
strong_threshold: cfg.consensus_scoring.strong_threshold,
|
|
47388
|
-
minority_threshold: cfg.consensus_scoring.minority_threshold,
|
|
47389
|
-
lenses: [...cfg.consensus_scoring.lenses]
|
|
47390
|
-
},
|
|
47391
|
-
cli_call_budget: {
|
|
47392
|
-
max_calls_per_day: _mapToObject(cfg.cli_call_budget.max_calls_per_day),
|
|
47393
|
-
warn_at: cfg.cli_call_budget.warn_at
|
|
47394
|
-
},
|
|
47395
|
-
// Phase 3.3 (road-to-always-on-orchestration): was validated by
|
|
47396
|
-
// `_build_config`/`_build_quorum` but never forwarded into the
|
|
47397
|
-
// synthesized block, so `build_members` always saw `undefined` and
|
|
47398
|
-
// silently fell back to `'majority'` regardless of the user's
|
|
47399
|
-
// configured `quorum: <k>`. Additive key — callers that never read
|
|
47400
|
-
// it observe no change.
|
|
47401
|
-
quorum: cfg.quorum,
|
|
47402
|
-
// Forwarded for the same reason `quorum` above had to be: a key that
|
|
47403
|
-
// `_build_config` validates and this block drops is a key the loader
|
|
47404
|
-
// enforces and the runtime never sees. That defect shipped once here
|
|
47405
|
-
// already; repeating it for the shadow floor would silently pin every
|
|
47406
|
-
// `floor_would_hold` to the default no matter what the operator set.
|
|
47407
|
-
quorum_min_present: cfg.quorum_min_present,
|
|
47408
|
-
necessity_classifier: {
|
|
47409
|
-
enabled: cfg.necessity_classifier.enabled,
|
|
47410
|
-
mode: cfg.necessity_classifier.mode,
|
|
47411
|
-
user_explicit_mode: cfg.necessity_classifier.user_explicit_mode
|
|
47412
|
-
},
|
|
47413
|
-
model_downgrade: {
|
|
47414
|
-
enabled: cfg.model_downgrade.enabled,
|
|
47415
|
-
auto_apply: cfg.model_downgrade.auto_apply
|
|
47416
|
-
},
|
|
47417
|
-
debate: {
|
|
47418
|
-
max_cost_usd: cfg.debate.max_cost_usd,
|
|
47419
|
-
cost_disclosure: {
|
|
47420
|
-
mode: cfg.debate.cost_disclosure.mode,
|
|
47421
|
-
threshold_usd: cfg.debate.cost_disclosure.threshold_usd,
|
|
47422
|
-
show_per_member: cfg.debate.cost_disclosure.show_per_member
|
|
47423
|
-
}
|
|
47424
|
-
},
|
|
47425
|
-
lens_overrides: {
|
|
47426
|
-
necessity_classifier_mode: _mapToObject(
|
|
47427
|
-
cfg.lens_overrides.necessity_classifier_mode
|
|
47428
|
-
),
|
|
47429
|
-
necessity_classifier_user_explicit_mode: _mapToObject(
|
|
47430
|
-
cfg.lens_overrides.necessity_classifier_user_explicit_mode
|
|
47431
|
-
),
|
|
47432
|
-
model_downgrade: lensModelDowngrade,
|
|
47433
|
-
cost_disclosure: lensCostDisclosure
|
|
47434
|
-
},
|
|
47435
|
-
members,
|
|
47436
|
-
advisors
|
|
47437
|
-
};
|
|
47438
|
-
}
|
|
47439
|
-
function _mapToObject(m) {
|
|
47440
|
-
const out = {};
|
|
47441
|
-
for (const [k, v] of m) {
|
|
47442
|
-
out[k] = v;
|
|
47443
|
-
}
|
|
47444
|
-
return out;
|
|
47445
|
-
}
|
|
47446
48045
|
function _member_api_key_present(cfg) {
|
|
47447
48046
|
const ref = cfg["api_key_ref"];
|
|
47448
48047
|
if (typeof ref !== "string" || ref.trim() === "") {
|
|
@@ -47463,6 +48062,7 @@ function build_members(settings, opts = {}) {
|
|
|
47463
48062
|
const quorum_out = opts.quorum_out ?? null;
|
|
47464
48063
|
const probe_store = opts.probe_store ?? null;
|
|
47465
48064
|
const qualification_out = opts.qualification_out ?? null;
|
|
48065
|
+
const fallback_out = opts.fallback_out ?? null;
|
|
47466
48066
|
const qualifications = [];
|
|
47467
48067
|
const report2 = opts.environment_report ?? detectEnvironment();
|
|
47468
48068
|
const ai = _isDict3(settings) ? settings["ai_council"] || {} : {};
|
|
@@ -47667,6 +48267,17 @@ function build_members(settings, opts = {}) {
|
|
|
47667
48267
|
`no council member has \`enabled: true\` \u2014 enable at least one under members.* in ${COUNCIL_CONFIG_USER_GLOBAL_REL} (user-global root; never the project tree, ADR-104). \`agent-config council:status\` prints the resolved path.`
|
|
47668
48268
|
);
|
|
47669
48269
|
}
|
|
48270
|
+
if (fallback_out !== null) {
|
|
48271
|
+
const fallback_cfg = _isDict3(ai["fallback"]) ? ai["fallback"] : {};
|
|
48272
|
+
fallback_out.options = buildFallbackOptions({
|
|
48273
|
+
apiOnQuota: _pyBool2(fallback_cfg["api_on_quota"]),
|
|
48274
|
+
hasApiRung: (p) => _API_PROVIDERS.has(p),
|
|
48275
|
+
memberConfig: (p) => members_cfg[p] || {},
|
|
48276
|
+
modelOverride: (p) => overrides[p] ?? null,
|
|
48277
|
+
constructApi: _construct_api_member,
|
|
48278
|
+
emit: appendEvent
|
|
48279
|
+
});
|
|
48280
|
+
}
|
|
47670
48281
|
return members;
|
|
47671
48282
|
}
|
|
47672
48283
|
function _setDifference(items, known) {
|
|
@@ -47968,7 +48579,7 @@ function _peer_review_cost_delta(ai_cfg, args, estimates, n_billable) {
|
|
|
47968
48579
|
const extra_usd = estimates.reduce((acc, e) => acc + _total_usd2(e), 0);
|
|
47969
48580
|
return [extra_calls, extra_usd];
|
|
47970
48581
|
}
|
|
47971
|
-
function _maybe_run_chairman(ai_cfg, question, members, responses, budget, table, project, args) {
|
|
48582
|
+
function _maybe_run_chairman(ai_cfg, question, members, responses, budget, table, project, args, cli_fallback = null) {
|
|
47972
48583
|
const ch = (_isDict3(ai_cfg) ? ai_cfg["chairman"] : null) || {};
|
|
47973
48584
|
const mode = typeof ch["mode"] === "string" ? ch["mode"] : "host";
|
|
47974
48585
|
if (mode === "host") {
|
|
@@ -48037,7 +48648,8 @@ ${transcript}`;
|
|
|
48037
48648
|
const out = consult([client], synthQ, budget, {
|
|
48038
48649
|
table,
|
|
48039
48650
|
project,
|
|
48040
|
-
original_ask: args.original_ask
|
|
48651
|
+
original_ask: args.original_ask,
|
|
48652
|
+
cli_fallback
|
|
48041
48653
|
});
|
|
48042
48654
|
const r = out[0] ?? null;
|
|
48043
48655
|
if (r === null || r.error !== null || r.text.trim() === "") {
|
|
@@ -48624,6 +49236,20 @@ function _resolvedTransportFor(name, member, report2) {
|
|
|
48624
49236
|
binaryOverride: member.binary
|
|
48625
49237
|
});
|
|
48626
49238
|
}
|
|
49239
|
+
function _posture(name, member) {
|
|
49240
|
+
const t = _resolvedTransportFor(name, member);
|
|
49241
|
+
const keyless = {
|
|
49242
|
+
anthropic: () => Boolean(load_anthropic_key()),
|
|
49243
|
+
openai: () => Boolean(load_openai_key())
|
|
49244
|
+
};
|
|
49245
|
+
return fallbackPostureFor({
|
|
49246
|
+
transport: t.available ? t.transport : null,
|
|
49247
|
+
hasApiRung: _API_PROVIDERS.has(name),
|
|
49248
|
+
apiKeyRef: member.api_key_ref,
|
|
49249
|
+
refResolves: member.api_key_ref === null ? void 0 : _member_api_key_present({ api_key_ref: member.api_key_ref }),
|
|
49250
|
+
keylessResolves: keyless[name]
|
|
49251
|
+
});
|
|
49252
|
+
}
|
|
48627
49253
|
function cmd_status(args, opts = {}) {
|
|
48628
49254
|
const env = opts.env ?? process.env;
|
|
48629
49255
|
const override = env[COUNCIL_CONFIG_ENV];
|
|
@@ -48670,6 +49296,12 @@ function cmd_status(args, opts = {}) {
|
|
|
48670
49296
|
];
|
|
48671
49297
|
})
|
|
48672
49298
|
),
|
|
49299
|
+
fallback: {
|
|
49300
|
+
api_on_quota: cfg?.fallback.api_on_quota ?? false,
|
|
49301
|
+
posture: Object.fromEntries(
|
|
49302
|
+
enabledMembers.map(([n, m]) => [n, _posture(n, m)])
|
|
49303
|
+
)
|
|
49304
|
+
},
|
|
48673
49305
|
ignored_transport_keys: cfg?.ignored_transport_keys ?? [],
|
|
48674
49306
|
qualification: qualificationJson(qualifications),
|
|
48675
49307
|
qualified_members: countableSeats(qualifications),
|
|
@@ -48710,6 +49342,13 @@ function cmd_status(args, opts = {}) {
|
|
|
48710
49342
|
const billing = t.available ? ` \xB7 ${t.billing}` : "";
|
|
48711
49343
|
const detail = t.available ? t.transport : `unavailable \u2014 ${t.reason ?? "no usable transport"}`;
|
|
48712
49344
|
_stdout2(` transport ${name}: ${detail}${billing}
|
|
49345
|
+
`);
|
|
49346
|
+
}
|
|
49347
|
+
for (const line of renderPostureLines(
|
|
49348
|
+
enabledMembers.map(([n, m]) => [n, _posture(n, m)]),
|
|
49349
|
+
cfg.fallback.api_on_quota
|
|
49350
|
+
)) {
|
|
49351
|
+
_stdout2(`${line}
|
|
48713
49352
|
`);
|
|
48714
49353
|
}
|
|
48715
49354
|
for (const line of qualificationStatusLines(qualifications)) {
|
|
@@ -48799,6 +49438,7 @@ function cmd_run(args, opts = {}) {
|
|
|
48799
49438
|
const explicit_overrides = _parse_model_overrides(_getattr3(args, "model", null));
|
|
48800
49439
|
const skipped = [];
|
|
48801
49440
|
const quorum_out = { result: null };
|
|
49441
|
+
const fallback_out = { options: null };
|
|
48802
49442
|
if (members === null) {
|
|
48803
49443
|
members = build_members(settings, {
|
|
48804
49444
|
invocation_mode: args.mode_override,
|
|
@@ -48806,7 +49446,8 @@ function cmd_run(args, opts = {}) {
|
|
|
48806
49446
|
siblings_overrides: _parse_siblings_overrides(_getattr3(args, "siblings", null)),
|
|
48807
49447
|
skipped,
|
|
48808
49448
|
quorum_out,
|
|
48809
|
-
probe_store: readProbeStore(REPO_ROOT11)
|
|
49449
|
+
probe_store: readProbeStore(REPO_ROOT11),
|
|
49450
|
+
fallback_out
|
|
48810
49451
|
});
|
|
48811
49452
|
}
|
|
48812
49453
|
const roster_before_dispatch = members.length;
|
|
@@ -48939,6 +49580,10 @@ function cmd_run(args, opts = {}) {
|
|
|
48939
49580
|
stance_tally: stance_tally_on,
|
|
48940
49581
|
member_prompt_suffix,
|
|
48941
49582
|
no_project_context_members,
|
|
49583
|
+
// Mid-flight cli→api fallback (ai-council-config.md § failure-class-
|
|
49584
|
+
// gated). `null` when the caller injected `members` directly — a
|
|
49585
|
+
// pre-built roster carries no config to derive the factory from.
|
|
49586
|
+
cli_fallback: fallback_out.options,
|
|
48942
49587
|
// Interactive one-line confirm (cmd_run has no --auto-continue); the
|
|
48943
49588
|
// repaired-call cost is collected so cost_usd_actual stays honest.
|
|
48944
49589
|
on_stance_repair: stance_tally_on ? (member) => _make_repair_confirm(false)(member, "missing stance line") : null,
|
|
@@ -48982,7 +49627,17 @@ function cmd_run(args, opts = {}) {
|
|
|
48982
49627
|
{ persona_labels }
|
|
48983
49628
|
);
|
|
48984
49629
|
const consensus = _maybe_run_consensus(ai_cfg, question, members, responses, budget, table, project, args);
|
|
48985
|
-
const chairman = _maybe_run_chairman(
|
|
49630
|
+
const chairman = _maybe_run_chairman(
|
|
49631
|
+
ai_cfg,
|
|
49632
|
+
question,
|
|
49633
|
+
members,
|
|
49634
|
+
responses,
|
|
49635
|
+
budget,
|
|
49636
|
+
table,
|
|
49637
|
+
project,
|
|
49638
|
+
args,
|
|
49639
|
+
fallback_out.options
|
|
49640
|
+
);
|
|
48986
49641
|
const blind_chairman_on = args.blind_chairman === true;
|
|
48987
49642
|
const chairman_fields_on = args.chairman_fields === true;
|
|
48988
49643
|
let blind_review_map = null;
|
|
@@ -49176,6 +49831,7 @@ function cmd_debate(args, opts = {}) {
|
|
|
49176
49831
|
const explicit_overrides = _parse_model_overrides(_getattr3(args, "model", null));
|
|
49177
49832
|
const skipped = [];
|
|
49178
49833
|
const quorum_out = { result: null };
|
|
49834
|
+
const fallback_out = { options: null };
|
|
49179
49835
|
if (members === null) {
|
|
49180
49836
|
members = build_members(settings, {
|
|
49181
49837
|
invocation_mode: args.mode_override,
|
|
@@ -49184,7 +49840,8 @@ function cmd_debate(args, opts = {}) {
|
|
|
49184
49840
|
skipped,
|
|
49185
49841
|
quorum_out,
|
|
49186
49842
|
probe_store: readProbeStore(REPO_ROOT11),
|
|
49187
|
-
command: "debate"
|
|
49843
|
+
command: "debate",
|
|
49844
|
+
fallback_out
|
|
49188
49845
|
});
|
|
49189
49846
|
}
|
|
49190
49847
|
if (table === null) {
|
|
@@ -49355,7 +50012,8 @@ ${blocks.join("\n\n")}
|
|
|
49355
50012
|
restate: restate_on,
|
|
49356
50013
|
on_restate: restate_on ? on_restate : null,
|
|
49357
50014
|
advisor_plans,
|
|
49358
|
-
seed_round_1: seed
|
|
50015
|
+
seed_round_1: seed,
|
|
50016
|
+
cli_fallback: fallback_out.options
|
|
49359
50017
|
});
|
|
49360
50018
|
} catch (exc) {
|
|
49361
50019
|
if (exc instanceof DebateCapExceeded) {
|
|
@@ -49976,6 +50634,10 @@ var init_council_cli = __esm({
|
|
|
49976
50634
|
init_qualification_wiring();
|
|
49977
50635
|
init_probe_store();
|
|
49978
50636
|
init_events_log();
|
|
50637
|
+
init_map_to_object();
|
|
50638
|
+
init_council_settings_block();
|
|
50639
|
+
init_council_fallback_posture();
|
|
50640
|
+
init_council_fallback_wiring();
|
|
49979
50641
|
init_necessity();
|
|
49980
50642
|
init_orchestrator();
|
|
49981
50643
|
init_pricing();
|