@azure-id/orc 1.9.0 → 1.9.2
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/CHANGELOG.md +202 -0
- package/README-id.md +57 -59
- package/README.md +53 -54
- package/bin/build-agents.js +109 -109
- package/bin/cli.js +262 -58
- package/bin/graph-audit.js +235 -0
- package/bin/graph-extract.js +308 -3
- package/bin/graph-gain.js +23 -3
- package/bin/graph-map.js +9 -1
- package/bin/graph-query.js +152 -10
- package/bin/graph-shard.js +6 -1
- package/bin/graph-signals.js +287 -4
- package/bin/graph.js +717 -658
- package/bin/onboarding-content.js +4 -4
- package/bin/pricing.json +207 -200
- package/bin/verify-contracts.js +117 -2
- package/bin/verify-package.js +11 -7
- package/bin/webui/css/04-motion.css +162 -152
- package/bin/webui/css/panels/knowledge.css +563 -116
- package/bin/webui/fixtures/extra.js +2036 -2036
- package/bin/webui/fixtures/hookui.js +5 -5
- package/bin/webui/fixtures/knowledge.js +21 -4
- package/bin/webui/fixtures/settings.js +305 -305
- package/bin/webui/i18n/en/knowledge.json +122 -4
- package/bin/webui/i18n/id/knowledge.json +122 -4
- package/bin/webui/js/panels/knowledge.js +573 -9
- package/bin/webui/js/panels/overview.js +13 -4
- package/mock-run/context-combiner.md +100 -100
- package/mock-run/orc-budget.md +534 -534
- package/mock-run/orc-challenge-council.md +262 -262
- package/mock-run/orc-ultra.md +103 -103
- package/package.json +1 -1
- package/templates/agents/MODEL-MAPPING.md +43 -43
- package/templates/agents/orc-advisor-opus-5-xhigh.md +56 -56
- package/templates/agents/orc-analyze-mini-opus-5-med.md +60 -60
- package/templates/agents/orc-analyze-mini-sonnet-5-high.md +58 -58
- package/templates/agents/orc-challenge-advisor-opus-5-med.md +75 -75
- package/templates/agents/orc-challenge-contrarian-opus-5-high.md +110 -110
- package/templates/agents/orc-challenge-executor-opus-5-med.md +114 -114
- package/templates/agents/orc-challenge-expansionist-opus-5-med.md +112 -112
- package/templates/agents/orc-challenge-judge-opus-5-high.md +132 -132
- package/templates/agents/orc-challenge-outsider-opus-5-low.md +109 -109
- package/templates/agents/orc-challenge-principles-opus-5-high.md +109 -109
- package/templates/agents/orc-challenge-reader-opus-5-low.md +90 -90
- package/templates/agents/orc-claude-writer-opus-5-med.md +55 -55
- package/templates/agents/orc-context-combiner-opus-5-high.md +88 -88
- package/templates/agents/orc-doc-checker-opus-5-low.md +108 -108
- package/templates/agents/orc-doc-writer-opus-5-med.md +134 -134
- package/templates/agents/orc-executor-haiku-4-5.md +2 -1
- package/templates/agents/orc-executor-opus-4-7-high.md +2 -1
- package/templates/agents/orc-executor-opus-4-7-med.md +2 -1
- package/templates/agents/orc-executor-opus-4-8-high.md +2 -1
- package/templates/agents/orc-executor-opus-5-high.md +4 -3
- package/templates/agents/orc-executor-opus-5-low.md +4 -3
- package/templates/agents/orc-executor-opus-5-med.md +4 -3
- package/templates/agents/orc-executor-sonnet-4-6-high.md +2 -1
- package/templates/agents/orc-executor-sonnet-4-6-med.md +2 -1
- package/templates/agents/orc-executor-sonnet-5-high.md +2 -1
- package/templates/agents/orc-graph-noter-sonnet-4-6-med.md +1 -1
- package/templates/agents/orc-judge-opus-5-xhigh.md +85 -85
- package/templates/agents/orc-learn-writer-opus-5-low.md +73 -73
- package/templates/agents/orc-pattern-codifier-opus-5-med.md +65 -65
- package/templates/agents/orc-planner-mini-opus-5-med.md +4 -4
- package/templates/agents/orc-planner-mini-sonnet-5-high.md +1 -1
- package/templates/agents/orc-planner-opus-5-med.md +160 -160
- package/templates/agents/orc-recon-opus-5-low.md +18 -8
- package/templates/agents/orc-recon-sonnet-4-6-med.md +15 -5
- package/templates/agents/orc-retro-opus-5-med.md +3 -3
- package/templates/agents/orc-reviewer-opus-5-med.md +60 -60
- package/templates/agents/orc-scout-opus-5-low.md +40 -40
- package/templates/agents/orc-system-analyst-opus-5-high.md +120 -120
- package/templates/agents/orc-test-author-opus-5-med.md +71 -71
- package/templates/agents/orc-test-designer-opus-5-high.md +158 -158
- package/templates/agents/orc-test-interpreter-opus-5-low.md +130 -130
- package/templates/agents/orc-verifier-opus-5-med.md +69 -69
- package/templates/agents/orc-wiki-scanner-opus-5-med.md +81 -81
- package/templates/commands/orc-ultra.md +17 -17
- package/templates/commands/orc-verify.md +11 -11
- package/templates/hooks/README.md +13 -3
- package/templates/hooks/orc-effort-guard.js +178 -178
- package/templates/hooks/orc-graph-hook.js +53 -7
- package/templates/hooks/orc-statusline.js +6 -6
- package/templates/skills/_shared/code-graph.md +57 -18
- package/templates/skills/_shared/config-precedence.md +198 -198
- package/templates/skills/_shared/extra-dispatch.md +1346 -1346
- package/templates/skills/_shared/opus5-only.md +8 -8
- package/templates/skills/_shared/phases/analyst-gates.md +136 -136
- package/templates/skills/_shared/phases/execution.md +4 -4
- package/templates/skills/_shared/phases/planning.md +3 -3
- package/templates/skills/_shared/phases/preflight.md +1 -1
- package/templates/skills/_shared/phases/review.md +4 -2
- package/templates/skills/_shared/phases/ship.md +1 -1
- package/templates/skills/_shared/phases/trace.md +3 -2
- package/templates/skills/_shared/read-ladder.md +14 -1
- package/templates/skills/_shared/return-validation.md +1 -1
- package/templates/skills/context-combiner/SKILL.md +1 -1
- package/templates/skills/context-combiner/schemas/combined-report.md +78 -78
- package/templates/skills/orc/README.md +2 -2
- package/templates/skills/orc/SKILL.md +8 -8
- package/templates/skills/orc/config.md +9 -9
- package/templates/skills/orc/examples/full-run-mock.md +73 -73
- package/templates/skills/orc/references/effort-and-mode.md +222 -222
- package/templates/skills/orc/references/preflight-report.md +2 -2
- package/templates/skills/orc/references/ultra-mode.md +3 -3
- package/templates/skills/orc/subskills/orc-planner/SKILL.md +2 -2
- package/templates/skills/orc/subskills/orc-planner-mini/SKILL.md +121 -121
- package/templates/skills/orc/subskills/orc-review-verify/SKILL.md +76 -76
- package/templates/skills/orc/subskills/orc-testgen/SKILL.md +45 -45
- package/templates/skills/orc-analyze/SKILL.md +2 -2
- package/templates/skills/orc-analyze/examples/analyze-mock.md +42 -42
- package/templates/skills/orc-analyze/schemas/report-audit.md +83 -83
- package/templates/skills/orc-analyze/schemas/report-prose.md +63 -63
- package/templates/skills/orc-analyze/schemas/report-requirement.md +78 -78
- package/templates/skills/orc-challenge/README.md +142 -142
- package/templates/skills/orc-challenge/examples/council-full-roster.md +273 -273
- package/templates/skills/orc-challenge/references/council.md +315 -315
- package/templates/skills/orc-challenge/references/intake.md +171 -171
- package/templates/skills/orc-claude/SKILL.md +14 -14
- package/templates/skills/orc-diy/README.md +143 -143
- package/templates/skills/orc-diy/references/flow-schema.md +1 -1
- package/templates/skills/orc-doc/README.md +229 -229
- package/templates/skills/orc-doc/examples/orc-doc-prd-run.md +325 -325
- package/templates/skills/orc-doc/references/chunking.md +527 -527
- package/templates/skills/orc-fast/SKILL.md +4 -4
- package/templates/skills/orc-learn/SKILL.md +14 -14
- package/templates/skills/orc-learn/examples/learn-run-mock.md +61 -61
- package/templates/skills/orc-mini/SKILL.md +16 -20
- package/templates/skills/orc-mini/references/complexity.md +25 -11
- package/templates/skills/orc-quick/SKILL.md +12 -13
- package/templates/skills/orc-quick/references/gh-mode.md +1 -1
- package/templates/skills/orc-quick/references/look.md +5 -5
- package/templates/skills/orc-verify/SKILL.md +15 -15
- package/templates/skills/orc-verify/examples/verify-mock.md +33 -33
- package/templates/skills/orc-wiki/references/extra.md +1 -1
package/bin/cli.js
CHANGED
|
@@ -180,8 +180,10 @@ function writeStdoutSync(str) {
|
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
// Print the object and (optionally) exit with the human path's code.
|
|
183
|
-
|
|
184
|
-
|
|
183
|
+
// `compact` (v1.9.1 B1) writes the answer with no indentation: a `--brief`
|
|
184
|
+
// answer is read by a model, and the card inside it carries its own newlines.
|
|
185
|
+
function emitJson(obj, exitCode, compact) {
|
|
186
|
+
writeStdoutSync((compact ? JSON.stringify(obj) : JSON.stringify(obj, null, 2)) + "\n");
|
|
185
187
|
if (exitCode !== undefined) process.exit(exitCode);
|
|
186
188
|
}
|
|
187
189
|
|
|
@@ -1065,6 +1067,8 @@ function upgrade() {
|
|
|
1065
1067
|
// ---------------------------------------------------------------------------
|
|
1066
1068
|
|
|
1067
1069
|
const KNOWN_MODELS = [
|
|
1070
|
+
"claude-opus-5-5",
|
|
1071
|
+
// Kept so a config written before v1.9.2 still validates.
|
|
1068
1072
|
"claude-opus-5",
|
|
1069
1073
|
"claude-opus-4-8",
|
|
1070
1074
|
"claude-opus-4-7",
|
|
@@ -1251,7 +1255,7 @@ const CONFIG_FAMILIES = {
|
|
|
1251
1255
|
// without being a CONFIG_META key, because where it sits in the
|
|
1252
1256
|
// precedence is a fact even though `orc config set` refuses to write it.
|
|
1253
1257
|
registry_less: true,
|
|
1254
|
-
shadow_note: "shadowed by {by} — executors use the fixed 2-band Opus 5 ladder",
|
|
1258
|
+
shadow_note: "shadowed by {by} — executors use the fixed 2-band Opus 5.5 ladder",
|
|
1255
1259
|
},
|
|
1256
1260
|
{ prio: "P3", key: null, terminal: "the shipped score→model table" },
|
|
1257
1261
|
],
|
|
@@ -1438,7 +1442,7 @@ const CONFIG_META = [
|
|
|
1438
1442
|
// decision with a recorded reason (the /orc-pact retirement rule).
|
|
1439
1443
|
{ key: "extra_demote_after", def: 2, tier: "common", answers: [{ family: "extra", prio: "P2", mode: "replace" }], gated_by: "extra_enabled", lanes: [], validate: vInt(0), options: [0, 2, 3, 5], desc: "Consecutive `stalled` dispatches on ONE profile, inside one run, before that profile is DEMOTED to the bottom of the ladder for the rest of the run — so `opus5_only` (or the shipped score table) becomes the effective P0 and the work stays on Claude. Only `stalled` counts: a 401 or a rate limit has its own answer (`extra_on_failure`, the vault, `extra_resume`), and demoting on one would hide a credential problem behind a routing change. A resume of the same stalled attempt is the SAME stall, never a second one. A demotion is RUN state — it never writes your config — it is ANNOUNCED before the next dispatch, and it is never auto-promoted back: `orc extra promote <run> --reason \"<why>\"`. 0 turns this clock off and leaves only extra_demote_stale_min." },
|
|
1440
1444
|
{ key: "extra_demote_stale_min", def: 20, tier: "common", answers: [{ family: "extra", prio: "P2", mode: "replace" }], gated_by: "extra_enabled", lanes: [], validate: vInt(0), options: [0, 10, 20, 45], desc: "Minutes a LIVE foreign attempt may show no observable progress before its profile is demoted. This is a different question from `extra_stall_s`, which stops ONE dispatch after 180s of silence: this clock is about the RUN — two workers in flight, both quiet, and a wave that is going nowhere — so the two have their own budgets and their own off values and neither is a simplification of the other. It reads the journal's own progress file on disk, never a remembered fact. 0 turns this clock off and leaves only extra_demote_after." },
|
|
1441
|
-
{ key: "opus5_only", def: false, tier: "common", answers: [{ family: "executor-band", prio: "P1", mode: "replace" }, { family: "fixed-role-model", prio: "P1", mode: "replace" }], lanes: ["orc", "orc-analyze", "orc-challenge", "orc-claude", "orc-diy", "orc-doc", "orc-fast", "orc-mini", "orc-pattern", "orc-quick", "orc-retro", "orc-wiki"], validate: vEnum("true", "false"), options: ["true", "false"], desc: "EVERY dispatched role uses ONE model — Opus 5 — with EFFORT as the cost dial (executors: [0,40) low · [40,80) medium · [80,100] high; each fixed role its own pinned effort). Deep SWE-benchmark work on cost vs efficiency across Claude models finds a single Opus 5 agent with the effort ladder the most efficient setup. It FORCES: while on it outranks a hand-written rubric_bands_override. Needs an Opus 5 main session or EVERY dispatch silently downgrades. Excludes the Haiku trace writer and orc-diy (compile-owned)." },
|
|
1445
|
+
{ key: "opus5_only", def: false, tier: "common", answers: [{ family: "executor-band", prio: "P1", mode: "replace" }, { family: "fixed-role-model", prio: "P1", mode: "replace" }], lanes: ["orc", "orc-analyze", "orc-challenge", "orc-claude", "orc-diy", "orc-doc", "orc-fast", "orc-mini", "orc-pattern", "orc-quick", "orc-retro", "orc-wiki"], validate: vEnum("true", "false"), options: ["true", "false"], desc: "EVERY dispatched role uses ONE model — Opus 5.5 — with EFFORT as the cost dial (executors: [0,40) low · [40,80) medium · [80,100] high; each fixed role its own pinned effort). Deep SWE-benchmark work on cost vs efficiency across Claude models finds a single Opus 5.5 agent with the effort ladder the most efficient setup. It FORCES: while on it outranks a hand-written rubric_bands_override. Needs an Opus 5.5 main session or EVERY dispatch silently downgrades. Excludes the Haiku trace writer and orc-diy (compile-owned)." },
|
|
1442
1446
|
// --- v0.46.0 — the six new lanes ------------------------------------------
|
|
1443
1447
|
{ key: "pact_gate", def: "warn", tier: "common", answers: [{ family: "pact", prio: "P2", mode: "replace" }], lanes: ["orc", "orc-pact"], validate: vEnum("off", "warn"), options: ["off", "warn"], desc: "Invariant ledger at Phase 1 + planning: warn = print the one pact line and inject a DRIFTED/BROKEN promise whose anchors intersect the plan's declared files as a planner constraint; off = nothing. NEVER blocks — a promise is advice with a receipt, not a gate. See /orc-pact." },
|
|
1444
1448
|
{ key: "pact_recheck_on_verify", def: "true", tier: "common", answers: [{ family: "pact", prio: "P2", mode: "replace" }], lanes: ["orc", "orc-pact"], validate: vEnum("true", "false"), options: ["true", "false"], desc: "Phase 6: re-run the cheap checks for ONLY the invariants the change touched (`orc pact check`), so a promise that just leaked is caught in the run that broke it." },
|
|
@@ -1521,7 +1525,7 @@ const LEGACY_KEYS = {
|
|
|
1521
1525
|
// So `config list` prints them, `config list --json` carries them, and
|
|
1522
1526
|
// `config set` refuses them BY NAME instead of with a generic unknown-key list.
|
|
1523
1527
|
const RETIRED_KEYS = {
|
|
1524
|
-
fable5_enabled: { removed_in: "1.0.0", why: "the Fable 5 role override was removed — every role dispatches its shipped Claude agent, or the Opus 5 variant under opus5_only" },
|
|
1528
|
+
fable5_enabled: { removed_in: "1.0.0", why: "the Fable 5 role override was removed — every role dispatches its shipped Claude agent, or the Opus 5.5 variant under opus5_only" },
|
|
1525
1529
|
fable5_roles: { removed_in: "1.0.0", why: "the Fable 5 role override was removed" },
|
|
1526
1530
|
fable5_effort: { removed_in: "1.0.0", why: "the Fable 5 role override was removed" },
|
|
1527
1531
|
};
|
|
@@ -2080,7 +2084,7 @@ function shadowReason(key, map, claudeDir) {
|
|
|
2080
2084
|
//
|
|
2081
2085
|
// v1.0.0 W4 — TWO BANDS, not three, and the same 90 edge as the default table's
|
|
2082
2086
|
// top two rows (D13). That symmetry is the point: once the default table's high
|
|
2083
|
-
// end is already Opus 5 with effort as the dial, the forcing mode differs from
|
|
2087
|
+
// end is already Opus 5.5 with effort as the dial, the forcing mode differs from
|
|
2084
2088
|
// it only BELOW 65, so a third band here would be a distinction the default
|
|
2085
2089
|
// table stopped making.
|
|
2086
2090
|
//
|
|
@@ -2126,7 +2130,7 @@ function scoreTableJson(map, claudeDir) {
|
|
|
2126
2130
|
// > the default 6-band table
|
|
2127
2131
|
//
|
|
2128
2132
|
// Extra is an OVERLAY, not a replacement, which is what makes "cheap grunt
|
|
2129
|
-
// work goes to DeepSeek, hard work stays on Opus 5" a two-command setup
|
|
2133
|
+
// work goes to DeepSeek, hard work stays on Opus 5.5" a two-command setup
|
|
2130
2134
|
// rather than a full table rewrite. `active` can therefore read as a
|
|
2131
2135
|
// COMPOSITE — because the truth is a composite, and a single word would be
|
|
2132
2136
|
// a lie about what the next dispatch will do.
|
|
@@ -2371,7 +2375,7 @@ function extraLegacyRoleWarn(value) {
|
|
|
2371
2375
|
|
|
2372
2376
|
// A shadowed setting must never be silent — the v0.36.0 rule, applied to a
|
|
2373
2377
|
// shadow that runs BOTH WAYS. Turning on opus5_only while route rows exist
|
|
2374
|
-
// does not give you the Opus 5 ladder everywhere, and turning on Extra does
|
|
2378
|
+
// does not give you the Opus 5.5 ladder everywhere, and turning on Extra does
|
|
2375
2379
|
// not take the Claude table away; saying either would be wrong. So name the
|
|
2376
2380
|
// ranges, which is the only statement that is true from both sides.
|
|
2377
2381
|
function extraShadowNotice(claudeDir) {
|
|
@@ -2432,17 +2436,17 @@ function opus5Notice(on, claudeDir) {
|
|
|
2432
2436
|
console.log(
|
|
2433
2437
|
"\n " + ui.color.bold("Opus-5-only dispatch is now ACTIVE — for EVERY role, not just executors.") + "\n" +
|
|
2434
2438
|
"\n Why: deep SWE-benchmark work on cost vs efficiency across Claude models finds a\n" +
|
|
2435
|
-
" single Opus 5 agent, with the EFFORT ladder as the cost dial, the most efficient\n" +
|
|
2439
|
+
" single Opus 5.5 agent, with the EFFORT ladder as the cost dial, the most efficient\n" +
|
|
2436
2440
|
" configuration. You trade model-class variety for effort variety.\n" +
|
|
2437
2441
|
"\n Scored executors (/orc + /orc-ultra):\n\n" +
|
|
2438
2442
|
ladderTable(OPUS5_SCORE_TABLE) +
|
|
2439
2443
|
"\n Fixed roles now dispatched instead of their defaults:\n\n" + roleRows + "\n" +
|
|
2440
|
-
"\n Already Opus 5, unchanged: analyst · planner · reviewer · verifier · test-author\n" +
|
|
2444
|
+
"\n Already Opus 5.5, unchanged: analyst · planner · reviewer · verifier · test-author\n" +
|
|
2441
2445
|
" · combiner · learn-writer · advisor · judge.\n" +
|
|
2442
2446
|
" NEVER forced: orc-trace-writer-haiku-4-5 (it transcribes a packet, no reasoning)\n" +
|
|
2443
2447
|
" and orc-diy (its table is compile-owned — re-run `orc diy compile` to change it).\n" +
|
|
2444
2448
|
"\n " + ui.mark.warn("Tier requirement — read this one:") + "\n" +
|
|
2445
|
-
" Today only the [90,100] executor band needs an Opus 5 main session. With this ON,\n" +
|
|
2449
|
+
" Today only the [90,100] executor band needs an Opus 5.5 main session. With this ON,\n" +
|
|
2446
2450
|
" EVERY dispatch does. A subagent can never outrank the main session, so on a lower\n" +
|
|
2447
2451
|
" session every role silently falls back to the session model and the tier-honesty\n" +
|
|
2448
2452
|
" rule reports a downgrade on EVERY return instead of occasionally. Hooks cannot\n" +
|
|
@@ -2858,17 +2862,17 @@ const LANE_INERT = {
|
|
|
2858
2862
|
{ key: "extra_fallback_agent", reason: "re-opening the gate IS the ask, so a second menu composed from a config key would be the same question twice in different words" },
|
|
2859
2863
|
],
|
|
2860
2864
|
"orc-challenge": [
|
|
2861
|
-
{ key: "opus5_only", reason: "every agent in this lane is already claude-opus-5, so this is a no-op — the lane is unaffected, not exempt" },
|
|
2865
|
+
{ key: "opus5_only", reason: "every agent in this lane is already claude-opus-5-5, so this is a no-op — the lane is unaffected, not exempt" },
|
|
2862
2866
|
],
|
|
2863
2867
|
"orc-doc": [
|
|
2864
|
-
{ key: "opus5_only", reason: "both agents in this lane are already claude-opus-5, so this is a no-op — the lane is unaffected, not exempt" },
|
|
2868
|
+
{ key: "opus5_only", reason: "both agents in this lane are already claude-opus-5-5, so this is a no-op — the lane is unaffected, not exempt" },
|
|
2865
2869
|
],
|
|
2866
|
-
// v1.5.0 — both agents in this lane ship as claude-opus-5, and the
|
|
2870
|
+
// v1.5.0 — both agents in this lane ship as claude-opus-5-5, and the
|
|
2867
2871
|
// interpreter's `low` is a MEASUREMENT choice rather than a cost one: a
|
|
2868
2872
|
// harder-thinking interpreter reasons its way to why a leaked stack trace is
|
|
2869
2873
|
// probably fine in staging, which is exactly the gap it exists to find.
|
|
2870
2874
|
"orc-test": [
|
|
2871
|
-
{ key: "opus5_only", reason: "both agents in this lane are already claude-opus-5, so this is a no-op — the lane is unaffected, not exempt" },
|
|
2875
|
+
{ key: "opus5_only", reason: "both agents in this lane are already claude-opus-5-5, so this is a no-op — the lane is unaffected, not exempt" },
|
|
2872
2876
|
],
|
|
2873
2877
|
// v1.1.0 W2 — this lane DISPATCHES NOTHING. A detached command does the
|
|
2874
2878
|
// waiting, so every family that answers "which model runs this" has no work
|
|
@@ -3143,7 +3147,7 @@ function laneAnnounce(lane, map, claudeDir, families) {
|
|
|
3143
3147
|
out.push(
|
|
3144
3148
|
off
|
|
3145
3149
|
? `opus5_only: ON, and INERT in this lane — ${off.reason}`
|
|
3146
|
-
: "opus5_only: ON — every dispatched role uses Opus 5, with effort as the only cost dial"
|
|
3150
|
+
: "opus5_only: ON — every dispatched role uses Opus 5.5, with effort as the only cost dial"
|
|
3147
3151
|
);
|
|
3148
3152
|
}
|
|
3149
3153
|
if (isTrue(map.extra_enabled)) {
|
|
@@ -3182,9 +3186,10 @@ function laneAnnounce(lane, map, claudeDir, families) {
|
|
|
3182
3186
|
const graphOn = String(Object.prototype.hasOwnProperty.call(map, "code_graph") ? map.code_graph : metaFor("code_graph").def) === "on";
|
|
3183
3187
|
if (graphOn && LANE_CALLS["graph-status"].lanes.includes(lane))
|
|
3184
3188
|
out.push(
|
|
3185
|
-
"graph: on — use the code-graph cache: (1) now: `orc graph status --if-enabled --heal --json` (builds or updates it); " +
|
|
3186
|
-
"(2) every code-writing slice: `orc graph ctx <declared files> --if-enabled --json` cards; " +
|
|
3187
|
-
"(3) after every code change: `orc graph update --if-enabled --json` (keeps it for the next run).
|
|
3189
|
+
"graph: on — use the code-graph cache: (1) now: `orc graph status --if-enabled --heal --json --brief` (builds or updates it); " +
|
|
3190
|
+
"(2) every code-writing slice: `orc graph ctx <declared files> --if-enabled --json --brief` cards; " +
|
|
3191
|
+
"(3) after every code change: `orc graph update --if-enabled --json --brief` (keeps it for the next run). " +
|
|
3192
|
+
"Copy each `line` and `trace` verbatim; `--brief` drops the rows you never print"
|
|
3188
3193
|
);
|
|
3189
3194
|
// A shadowed setting must never be silent, and neither must an inert one.
|
|
3190
3195
|
const shadowed = [];
|
|
@@ -3480,7 +3485,24 @@ const LANE_CALLS = {
|
|
|
3480
3485
|
on_absent: "exit 4 is an ANSWER, not a miss — plan exactly as before",
|
|
3481
3486
|
canonical: "_shared/code-graph.md",
|
|
3482
3487
|
never: "never read a co-change as a DEPENDENCY — it says what people changed together, never what needs what",
|
|
3483
|
-
|
|
3488
|
+
// v1.9.1: mini no longer calls it. `impact --complexity` answers the same
|
|
3489
|
+
// question inside the SAME process, against the same per-HEAD cache.
|
|
3490
|
+
lanes: ["orc", "orc-diy"],
|
|
3491
|
+
},
|
|
3492
|
+
// v1.9.1 A2 — a USER command. `lanes: []` is the contract: nothing a lane
|
|
3493
|
+
// does is made better by an audit, and a lane that ran one would pay for an
|
|
3494
|
+
// answer about the PARSER in a context that is about the code.
|
|
3495
|
+
"graph-audit": {
|
|
3496
|
+
cmd: "orc graph audit [--top=N] --if-enabled [--json]",
|
|
3497
|
+
what: "WHY the map is thin — density by language, which extractor read each one, the files the parser read as EMPTY longest first, and what their first declaration looks like",
|
|
3498
|
+
exits: { 0: "answered", 1: "no index yet", 3: "off — `code_graph` is off" },
|
|
3499
|
+
states: null,
|
|
3500
|
+
cost: "free",
|
|
3501
|
+
when: "by hand, after `orc graph status` says THIN — never in a lane",
|
|
3502
|
+
on_absent: "exit 1 means there is no graph to audit; build one first",
|
|
3503
|
+
canonical: "_shared/code-graph.md",
|
|
3504
|
+
never: "never read an empty file as a defect — a component with no named function is a file the parser read correctly; only a shape marked `parser gap` is worth an issue",
|
|
3505
|
+
lanes: [],
|
|
3484
3506
|
},
|
|
3485
3507
|
"graph-gain": {
|
|
3486
3508
|
cmd: "orc graph gain --run <trace name> --if-enabled [--json]",
|
|
@@ -4962,7 +4984,7 @@ const sha256 = (s) => crypto.createHash("sha256").update(s).digest("hex");
|
|
|
4962
4984
|
// The tier-clip roster. It must contain EVERY agent the default table names —
|
|
4963
4985
|
// `diyScoreTable()` looks each row's agent up here, so a table row naming an
|
|
4964
4986
|
// agent this map does not know is a crash, not a fallback. v1.0.0 W4 added the
|
|
4965
|
-
// two Opus 5 rows for exactly that reason.
|
|
4987
|
+
// two Opus 5.5 rows for exactly that reason.
|
|
4966
4988
|
//
|
|
4967
4989
|
// It also feeds `fixed_executor`'s option list, so every entry here is offerable
|
|
4968
4990
|
// — which is what keeps the four agents no band names reachable (D14).
|
|
@@ -4994,10 +5016,10 @@ const DIY_TIERS = {
|
|
|
4994
5016
|
"opus-4-8-high": { model: 5, effort: 2, modelId: "claude-opus-4-8", effortName: "high" },
|
|
4995
5017
|
"opus-4-8-xhigh": { model: 5, effort: 3, modelId: "claude-opus-4-8", effortName: "xhigh" },
|
|
4996
5018
|
"opus-4-8-max": { model: 5, effort: 4, modelId: "claude-opus-4-8", effortName: "max" },
|
|
4997
|
-
"opus-5-med": { model: 6, effort: 1, modelId: "claude-opus-5", effortName: "medium" },
|
|
4998
|
-
"opus-5-high": { model: 6, effort: 2, modelId: "claude-opus-5", effortName: "high" },
|
|
4999
|
-
"opus-5-xhigh": { model: 6, effort: 3, modelId: "claude-opus-5", effortName: "xhigh" },
|
|
5000
|
-
"opus-5-max": { model: 6, effort: 4, modelId: "claude-opus-5", effortName: "max" },
|
|
5019
|
+
"opus-5-med": { model: 6, effort: 1, modelId: "claude-opus-5-5", effortName: "medium" },
|
|
5020
|
+
"opus-5-high": { model: 6, effort: 2, modelId: "claude-opus-5-5", effortName: "high" },
|
|
5021
|
+
"opus-5-xhigh": { model: 6, effort: 3, modelId: "claude-opus-5-5", effortName: "xhigh" },
|
|
5022
|
+
"opus-5-max": { model: 6, effort: 4, modelId: "claude-opus-5-5", effortName: "max" },
|
|
5001
5023
|
"fable-5-med": { model: 7, effort: 1, modelId: "claude-fable-5", effortName: "medium" },
|
|
5002
5024
|
"fable-5-high": { model: 7, effort: 2, modelId: "claude-fable-5", effortName: "high" },
|
|
5003
5025
|
"fable-5-xhigh": { model: 7, effort: 3, modelId: "claude-fable-5", effortName: "xhigh" },
|
|
@@ -5234,15 +5256,15 @@ function diyValidate(cfg) {
|
|
|
5234
5256
|
if (cfg.autonomy === "hands-off" && (cfg.ship_mode === "commit" || cfg.ship_mode === "pr")) {
|
|
5235
5257
|
warnings.push(`hands-off + ship_mode ${cfg.ship_mode}: git actions will run fully unattended`);
|
|
5236
5258
|
}
|
|
5237
|
-
// The pinned reviewer/verifier moved to claude-opus-5 (model rank 6) in
|
|
5259
|
+
// The pinned reviewer/verifier moved to claude-opus-5-5 (model rank 6) in
|
|
5238
5260
|
// v0.34.0 — anything below that tier silently runs them at the session model.
|
|
5239
5261
|
if (tier && tier.model < 6 && (cfg.review !== "off" || cfg.verify !== "off")) {
|
|
5240
5262
|
// Careful wording (v0.34.7): `session_tier` is a DECLARATION, not the real
|
|
5241
5263
|
// session model — a hook cannot read the model, only the effort. On a
|
|
5242
|
-
// session that actually outranks the declared tier the pinned Opus 5 roles
|
|
5264
|
+
// session that actually outranks the declared tier the pinned Opus 5.5 roles
|
|
5243
5265
|
// run at FULL pin (observed), so asserting they "will" downgrade is a false
|
|
5244
5266
|
// alarm; what is certain is only that a LOWER real session caps them.
|
|
5245
|
-
warnings.push(`session_tier ${cfg.session_tier} is below the pinned Opus 5 reviewer/verifier: if the REAL session is also below Opus 5 they run capped at it (the tier-honesty rule reports the actual model). A session above this tier runs them at full pin — but your executor table stays clipped to ${cfg.session_tier}; recompile to use the full ladder`);
|
|
5267
|
+
warnings.push(`session_tier ${cfg.session_tier} is below the pinned Opus 5.5 reviewer/verifier: if the REAL session is also below Opus 5.5 they run capped at it (the tier-honesty rule reports the actual model). A session above this tier runs them at full pin — but your executor table stays clipped to ${cfg.session_tier}; recompile to use the full ladder`);
|
|
5246
5268
|
}
|
|
5247
5269
|
return { errors, warnings };
|
|
5248
5270
|
}
|
|
@@ -7626,7 +7648,7 @@ const WIKI_TIER_LADDER = [
|
|
|
7626
7648
|
{ id: "small-delta", tier: "light", why: "small delta, no new surface" },
|
|
7627
7649
|
];
|
|
7628
7650
|
|
|
7629
|
-
// The POSITION each tier resolves to (v0.55.0). Two slots and ONE Opus 5 agent
|
|
7651
|
+
// The POSITION each tier resolves to (v0.55.0). Two slots and ONE Opus 5.5 agent
|
|
7630
7652
|
// is not a contradiction: a slot names the POSITION, not the model, and the
|
|
7631
7653
|
// ladder already collapses both tiers onto that agent while `opus5_only` is on.
|
|
7632
7654
|
const WIKI_TIER_SLOT = { deep: "wiki-scanner-deep", light: "wiki-scanner-light" };
|
|
@@ -8742,6 +8764,14 @@ function gainRowFor(sub, Q, model, operands, r, ms, forSlice) {
|
|
|
8742
8764
|
paid.source = K.tok(r.source.text);
|
|
8743
8765
|
paid.card = Math.max(0, paid.card - paid.source);
|
|
8744
8766
|
}
|
|
8767
|
+
// R1 (v1.9.1): the callers' blocks are source the same way — exactly the
|
|
8768
|
+
// lines a range read of each caller would have returned.
|
|
8769
|
+
const callerBlocks = Array.isArray(r.callers_source) ? r.callers_source : [];
|
|
8770
|
+
if (callerBlocks.length) {
|
|
8771
|
+
const t = callerBlocks.reduce((a, b) => a + K.tok(b.text || ""), 0);
|
|
8772
|
+
paid.source += t;
|
|
8773
|
+
paid.card = Math.max(0, paid.card - t);
|
|
8774
|
+
}
|
|
8745
8775
|
const base = { cmd: sub, targets: operands.slice(0, 5), gen, ms, paid };
|
|
8746
8776
|
|
|
8747
8777
|
if (sub === "impact" || (sub === "ctx" && forSlice)) {
|
|
@@ -8773,6 +8803,7 @@ function gainRowFor(sub, Q, model, operands, r, ms, forSlice) {
|
|
|
8773
8803
|
const hits = Q.nameHits(model, r.target.qname);
|
|
8774
8804
|
const c = K.ctxSymbol(model, r.target, hits, (r.callers || []).map((x) => x.file));
|
|
8775
8805
|
if (r.source) c.avoided = addAvoided(c.avoided, K.sourceAvoided(model, r.source.file, r.source.from, r.source.to));
|
|
8806
|
+
for (const b of callerBlocks) c.avoided = addAvoided(c.avoided, K.sourceAvoided(model, b.file, b.from, b.to));
|
|
8776
8807
|
return { ...base, ...c };
|
|
8777
8808
|
}
|
|
8778
8809
|
return { ...base, avoided: { low: 0, high: 0, calls_low: 0, calls_high: 0 }, basis: { files: [], grep_hits: 0 } };
|
|
@@ -8815,23 +8846,79 @@ function graphGainAppend(claudeDir, row) {
|
|
|
8815
8846
|
// A thin router. The engine is `bin/graph.js`; this function resolves the
|
|
8816
8847
|
// config (the engine never reads it) and owns the human lines. The exit code is
|
|
8817
8848
|
// the same on the human path and the `--json` path (S7).
|
|
8849
|
+
// ── B1 (v1.9.1): the BRIEF answer ─────────────────────────────────────────
|
|
8850
|
+
// The orchestrator reads a graph answer on the main-session surface, where it
|
|
8851
|
+
// is re-sent on every later turn — and it prints the `card`, never the rows.
|
|
8852
|
+
// Measured on this tree the rows are 4 to 8 times the card. `--brief` keeps
|
|
8853
|
+
// every fact a lane prints and drops every row array it does not.
|
|
8854
|
+
//
|
|
8855
|
+
// Two rules, in this order:
|
|
8856
|
+
// 1. an array NAMED here is dropped (`calls[]` and `names[]` are strings, and
|
|
8857
|
+
// they are still rows);
|
|
8858
|
+
// 2. any other array OF OBJECTS is dropped, unless it IS the answer
|
|
8859
|
+
// (`nearest[]` and `candidates[]` on an exit-4; `cards[]` on a multi-target
|
|
8860
|
+
// `ctx`, whose rows are three scalars each).
|
|
8861
|
+
// Every drop leaves its COUNT behind, at the level it was dropped from, except
|
|
8862
|
+
// where the answer already carries that count under another name.
|
|
8863
|
+
const GRAPH_BRIEF_DROP = new Set(["callers", "calls", "effects", "symbols", "imports", "importers", "blocks", "names", "rows", "chain", "waiting"]);
|
|
8864
|
+
const GRAPH_BRIEF_KEEP = new Set(["nearest", "candidates", "cards"]);
|
|
8865
|
+
// V2/V3 answers that ARE the answer: `complexity` and `facts` are ten rows at
|
|
8866
|
+
// most, and they are the whole reason the call was made. They pass through
|
|
8867
|
+
// whole, never walked.
|
|
8868
|
+
const GRAPH_BRIEF_WHOLE = new Set(["complexity", "facts"]);
|
|
8869
|
+
const GRAPH_BRIEF_NO_COUNT = { impact: ["callers"], map: ["files"], changes: ["symbols"] };
|
|
8870
|
+
|
|
8871
|
+
function briefOf(sub, obj) {
|
|
8872
|
+
const noCount = new Set(GRAPH_BRIEF_NO_COUNT[sub] || []);
|
|
8873
|
+
const walk = (o) => {
|
|
8874
|
+
const out = {};
|
|
8875
|
+
const counts = {};
|
|
8876
|
+
for (const [k, v] of Object.entries(o)) {
|
|
8877
|
+
if (Array.isArray(v)) {
|
|
8878
|
+
const rows = GRAPH_BRIEF_DROP.has(k) || (!GRAPH_BRIEF_KEEP.has(k) && v.length > 0 && v[0] !== null && typeof v[0] === "object");
|
|
8879
|
+
if (!rows) out[k] = v;
|
|
8880
|
+
else if (!noCount.has(k)) counts[k] = v.length;
|
|
8881
|
+
continue;
|
|
8882
|
+
}
|
|
8883
|
+
if (k === "source" && v && typeof v === "object") {
|
|
8884
|
+
const from = Number(v.from);
|
|
8885
|
+
const to = Number(v.to);
|
|
8886
|
+
counts.source_lines = Number.isFinite(from) && Number.isFinite(to) ? Math.max(0, to - from + 1) : 0;
|
|
8887
|
+
continue;
|
|
8888
|
+
}
|
|
8889
|
+
out[k] = v && typeof v === "object" && !GRAPH_BRIEF_WHOLE.has(k) ? walk(v) : v;
|
|
8890
|
+
}
|
|
8891
|
+
if (Object.keys(counts).length) out.counts = { ...(out.counts || {}), ...counts };
|
|
8892
|
+
return out;
|
|
8893
|
+
};
|
|
8894
|
+
return walk(obj);
|
|
8895
|
+
}
|
|
8896
|
+
|
|
8818
8897
|
function graphCmd() {
|
|
8819
8898
|
const usage =
|
|
8820
|
-
"Usage: orc graph status [--heal] | update [--notes-pending --files <a,b>] | gc\n" +
|
|
8821
|
-
" orc graph ctx <symbol|file[:line]>… [--source [N]] | ctx --for-slice <file…> | impact <file…> | path <from> <to>\n" +
|
|
8822
|
-
" orc graph coverage <file…> | changes [--base <ref>] | cochange <file>\n" +
|
|
8899
|
+
"Usage: orc graph status [--heal] | update [--notes-pending --files <a,b>] | gc | audit [--top=N]\n" +
|
|
8900
|
+
" orc graph ctx <symbol|file[:line]>… [--source [N]] [--callers-source] | ctx --for-slice <file…> | impact <file…> | path <from> <to>\n" +
|
|
8901
|
+
" orc graph coverage <file…> | changes [--base <ref>] [--files=<a,b>] | cochange <file>\n" +
|
|
8823
8902
|
" orc graph map [--focus <file|name,…>] [--budget N]\n" +
|
|
8824
8903
|
" orc graph gain [--run <name>] [--since 7d] [--history [--limit 40]] [--measured] [--reset --yes]\n" +
|
|
8825
8904
|
" orc graph notes pending --files <a,b> [--cap 40] [--min 5] [--with-source] | notes apply <file|->\n" +
|
|
8826
|
-
" [--if-enabled] [--depth N] [--budget TOKENS] [--format prose|tree] [--offset N] [--json] [--dir <path>]\n" +
|
|
8905
|
+
" [--if-enabled] [--depth N] [--budget TOKENS] [--format prose|tree] [--offset N] [--json] [--brief] [--dir <path>]\n" +
|
|
8906
|
+
" --brief with --json: the card, the line, the trace, every scalar and every count — and none of the row\n" +
|
|
8907
|
+
" arrays a lane never prints. Compact output. Without --brief, --json is unchanged.\n" +
|
|
8827
8908
|
" status exit 0 FRESH · 1 NONE · 2 DRIFTED · 3 OFF (--heal builds or updates a NONE/DRIFTED graph first)\n" +
|
|
8828
8909
|
" update exit 0 done · 1 unavailable or locked · 3 off (with --if-enabled)\n" +
|
|
8829
8910
|
" --notes-pending adds the `notes pending` answer to the SAME call (one process, one lock)\n" +
|
|
8830
8911
|
" gc exit 0 done · 1 no index or locked\n" +
|
|
8912
|
+
" audit exit 0 answered · 1 no index · 3 off (with --if-enabled) WHY the map is thin: density by language,\n" +
|
|
8913
|
+
" the files the parser read as EMPTY, longest first, and what their first declaration looks like\n" +
|
|
8831
8914
|
" ctx exit 0 found · 1 no graph · 3 off (with --if-enabled) · 4 not found or ambiguous\n" +
|
|
8832
8915
|
" --source [N] appends the target's own lines (default 80, cap 200), charged to the same budget\n" +
|
|
8916
|
+
" --callers-source appends 6 lines around each CONFIDENT call site (≤ 5, never the target's own\n" +
|
|
8917
|
+
" file), charged to the same budget after everything else; symbol cards only\n" +
|
|
8833
8918
|
" --for-slice prints only the OUTSIDE view of each declared file — no symbol table\n" +
|
|
8834
8919
|
" impact exit 0 found · 1 no graph · 3 off (with --if-enabled) · 4 none of the files is in the graph\n" +
|
|
8920
|
+
" --complexity [--risk=<class>[@<file:line>],…] adds the ONE line that says whether this change\n" +
|
|
8921
|
+
" fits one executor, with the numbers behind it — impact and co-change in ONE call\n" +
|
|
8835
8922
|
" path exit 0 found · 1 no graph · 3 off (with --if-enabled) · 4 no confident path, or an unknown end\n" +
|
|
8836
8923
|
" map exit 0 always when a graph exists · 1 no graph · 3 off (with --if-enabled) the files by RANK, most\n" +
|
|
8837
8924
|
" connected first, each with its top symbols; --focus re-ranks the repository around those files or names\n" +
|
|
@@ -8852,6 +8939,16 @@ function graphCmd() {
|
|
|
8852
8939
|
const root = repoRootOf(claudeDir);
|
|
8853
8940
|
const sub = positionals()[1];
|
|
8854
8941
|
const asJson = wantsJson();
|
|
8942
|
+
// B1: a BARE switch, read from `args`. `flag()` reads the next word as a
|
|
8943
|
+
// value, so `--brief` there would swallow the first operand.
|
|
8944
|
+
let briefOn = args.includes("--brief");
|
|
8945
|
+
// Every flag this release adds that carries a VALUE is written
|
|
8946
|
+
// `--name=value`, for the same reason: one word, so a CLI that does not
|
|
8947
|
+
// know the flag skips it whole instead of losing an operand behind it.
|
|
8948
|
+
const eqFlag = (name) => {
|
|
8949
|
+
const hit = args.find((a) => a.startsWith(name + "="));
|
|
8950
|
+
return hit === undefined ? undefined : hit.slice(name.length + 1);
|
|
8951
|
+
};
|
|
8855
8952
|
const ovr = readOverride(claudeDir).map;
|
|
8856
8953
|
const cfg = (k) => (Object.prototype.hasOwnProperty.call(ovr, k) ? ovr[k] : metaFor(k).def);
|
|
8857
8954
|
const enabled = String(cfg("code_graph")) === "on";
|
|
@@ -8930,7 +9027,12 @@ function graphCmd() {
|
|
|
8930
9027
|
return null;
|
|
8931
9028
|
}
|
|
8932
9029
|
};
|
|
8933
|
-
|
|
9030
|
+
// B3 (v1.9.1): the ledger append moved INSIDE `finish`, because the one
|
|
9031
|
+
// number the meter called EXACT — the card — was 4 to 8 times too small. The
|
|
9032
|
+
// ENVELOPE is everything the answer carries beyond its card, and it can only
|
|
9033
|
+
// be counted once the text that will be written exists. The append is still
|
|
9034
|
+
// fail-quiet and still happens after the answer is built, never before it.
|
|
9035
|
+
const finish = (r, line, trace, jsonLine = true, gainRow = null) => {
|
|
8934
9036
|
const { exit, ...obj } = r;
|
|
8935
9037
|
if (obj.generation === undefined) {
|
|
8936
9038
|
const m = metaNow();
|
|
@@ -8939,7 +9041,19 @@ function graphCmd() {
|
|
|
8939
9041
|
obj.gen_id = m.gen_id || null;
|
|
8940
9042
|
}
|
|
8941
9043
|
}
|
|
8942
|
-
|
|
9044
|
+
const full = { ...obj, ...(line && jsonLine ? { line } : {}), ...(trace ? { trace } : {}) };
|
|
9045
|
+
const payload = asJson && briefOn ? briefOf(sub, full) : full;
|
|
9046
|
+
if (gainRow) {
|
|
9047
|
+
try {
|
|
9048
|
+
const K = require("./graph-gain.js");
|
|
9049
|
+
const text = asJson ? (briefOn ? JSON.stringify(payload) : JSON.stringify(payload, null, 2)) : String(line || "");
|
|
9050
|
+
if (gainRow.paid) gainRow.paid.envelope = Math.max(0, K.tok(text) - K.tok(obj.card || line || ""));
|
|
9051
|
+
graphGainAppend(claudeDir, gainRow);
|
|
9052
|
+
} catch (_) {
|
|
9053
|
+
// K6: the meter is never allowed to fail the read it is measuring.
|
|
9054
|
+
}
|
|
9055
|
+
}
|
|
9056
|
+
if (asJson) emitJson(payload, exit, briefOn);
|
|
8943
9057
|
if (line) console.log(line);
|
|
8944
9058
|
process.exit(exit);
|
|
8945
9059
|
};
|
|
@@ -8962,6 +9076,32 @@ function graphCmd() {
|
|
|
8962
9076
|
r.auto_update = autoUpdate;
|
|
8963
9077
|
r.notes = String(cfg("code_graph_notes"));
|
|
8964
9078
|
if (healed) r.healed = healed;
|
|
9079
|
+
// A1 (v1.9.1): the density, and the BACKFILL for a store built before
|
|
9080
|
+
// this release. A FRESH store never updates, so waiting for the next real
|
|
9081
|
+
// update would leave a long-lived graph without the line forever. It runs
|
|
9082
|
+
// under `--heal` only, once, and it is bounded by the same cap every heal
|
|
9083
|
+
// obeys — the index did not change, so `generation` and `gen_id` do not.
|
|
9084
|
+
const SIGD = require("./graph-signals.js");
|
|
9085
|
+
let meta = metaNow();
|
|
9086
|
+
if (flag("--heal") === true && enabled && meta && !meta.density && r.exists) {
|
|
9087
|
+
const capMs = Number(cfg("code_graph_heal_ms")) || 0;
|
|
9088
|
+
if (!capMs || !meta.update_ms || meta.update_ms <= capMs) {
|
|
9089
|
+
try {
|
|
9090
|
+
const p = G.graphPaths(claudeDir);
|
|
9091
|
+
const idx = JSON.parse(fs.readFileSync(p.index, "utf8"));
|
|
9092
|
+
const fl = JSON.parse(fs.readFileSync(p.files, "utf8"));
|
|
9093
|
+
meta.density = G.densityOf(idx, fl);
|
|
9094
|
+
G.atomicWrite(p.meta, JSON.stringify(meta, null, 2) + "\n");
|
|
9095
|
+
r.density_backfilled = true;
|
|
9096
|
+
} catch (_) {
|
|
9097
|
+
meta = metaNow();
|
|
9098
|
+
}
|
|
9099
|
+
}
|
|
9100
|
+
}
|
|
9101
|
+
if (meta && meta.density) {
|
|
9102
|
+
r.density = meta.density;
|
|
9103
|
+
r.thin = SIGD.isThin(meta.density, r.files);
|
|
9104
|
+
}
|
|
8965
9105
|
const b = r.behind || {};
|
|
8966
9106
|
const lines = {
|
|
8967
9107
|
off: "graph: off",
|
|
@@ -8975,6 +9115,12 @@ function graphCmd() {
|
|
|
8975
9115
|
};
|
|
8976
9116
|
let line = lines[r.state];
|
|
8977
9117
|
let consult = r.state;
|
|
9118
|
+
// The density rides on the line a lane already prints, never on a line of
|
|
9119
|
+
// its own: a second line is a second thing to skip.
|
|
9120
|
+
const densityText = r.density
|
|
9121
|
+
? ` · ${r.density.symbols_per_file} symbols/file` +
|
|
9122
|
+
(r.thin ? ` · THIN (${Math.round(r.density.zero_share * 100)} % of files have no symbol) — run: orc graph audit` : "")
|
|
9123
|
+
: "";
|
|
8978
9124
|
if (healed && healed.parsed !== undefined) {
|
|
8979
9125
|
const moved = healed.added + healed.changed + healed.deleted;
|
|
8980
9126
|
const size = `${plural(r.files, "file")} · ${plural(r.symbols, "symbol")}`;
|
|
@@ -8986,7 +9132,15 @@ function graphCmd() {
|
|
|
8986
9132
|
? `graph: index upgraded to the new engine → updated (${healed.ms} ms) — ${size}`
|
|
8987
9133
|
: `graph: ${plural(moved, "file")} changed outside ORC → updated (${healed.ms} ms) — ${size}`;
|
|
8988
9134
|
} else if (healed) line += ` · could not heal: ${healed.reason}`;
|
|
8989
|
-
|
|
9135
|
+
if (densityText && ["fresh", "drifted", "built", "updated"].includes(consult)) line += densityText;
|
|
9136
|
+
return finish(
|
|
9137
|
+
r,
|
|
9138
|
+
line,
|
|
9139
|
+
consult === "off"
|
|
9140
|
+
? "GRAPH-CONSULT off"
|
|
9141
|
+
: `GRAPH-CONSULT ${consult} :: files=${r.files} symbols=${r.symbols} gen=${r.generation}` +
|
|
9142
|
+
(r.density ? ` density=${r.density.symbols_per_file}${r.thin ? " thin=1" : ""}` : "")
|
|
9143
|
+
);
|
|
8990
9144
|
}
|
|
8991
9145
|
|
|
8992
9146
|
if (sub === "update") {
|
|
@@ -9150,8 +9304,11 @@ function graphCmd() {
|
|
|
9150
9304
|
const SIG = require("./graph-signals.js");
|
|
9151
9305
|
if (sub === "changes") {
|
|
9152
9306
|
const base = typeof flag("--base") === "string" ? flag("--base") : null;
|
|
9307
|
+
// V1: the lane hands the files it just wrote, and the rows for every
|
|
9308
|
+
// other file never leave this process.
|
|
9309
|
+
const onlyFiles = String(eqFlag("--files") || "").split(",").map((x) => x.trim()).filter(Boolean);
|
|
9153
9310
|
const healed = healOnRead(SIG.changedPaths(root, base));
|
|
9154
|
-
const r = SIG.graphChanges(claudeDir, root, { base });
|
|
9311
|
+
const r = SIG.graphChanges(claudeDir, root, { base, files: onlyFiles });
|
|
9155
9312
|
if (healed) r.healed = healed;
|
|
9156
9313
|
if (r.exit !== 0) return finish(r, r.reason === "no-index" ? "graph: none — no index yet (run: orc graph update)" : `graph: unavailable — ${r.reason}`);
|
|
9157
9314
|
const c = r.counts;
|
|
@@ -9163,6 +9320,7 @@ function graphCmd() {
|
|
|
9163
9320
|
: `graph changes vs ${r.base} — no indexed symbol was touched${r.not_in_graph.length ? ` (changed, but not in the graph: ${r.not_in_graph.join(", ")})` : ""}`;
|
|
9164
9321
|
// K1/K2: `changes` avoids one Grep per touched symbol. The diff itself
|
|
9165
9322
|
// is NOT counted — the reviewer reads it either way.
|
|
9323
|
+
let gainRow = null;
|
|
9166
9324
|
if (r.symbols.length) {
|
|
9167
9325
|
try {
|
|
9168
9326
|
const K = require("./graph-gain.js");
|
|
@@ -9171,11 +9329,11 @@ function graphCmd() {
|
|
|
9171
9329
|
if (m) {
|
|
9172
9330
|
const hits = r.symbols.reduce((a, x) => a + Q.nameHits(m, x.qname), 0);
|
|
9173
9331
|
const callerFiles = r.symbols.flatMap((x) => (x.callers || []).map((cc) => cc.file || cc));
|
|
9174
|
-
|
|
9332
|
+
gainRow = { cmd: "changes", targets: [r.base], gen: r.generation, ms: r.ms || 0, paid: { card: K.tok(line), source: 0, hints: 0 }, ...K.changesCost(m, r.symbols.length, hits, callerFiles) };
|
|
9175
9333
|
}
|
|
9176
9334
|
} catch (_) {}
|
|
9177
9335
|
}
|
|
9178
|
-
return finish(r, line, `GRAPH-CHANGES ${r.symbols.length ? "found" : "none"} :: symbols=${r.symbols.length} high=${c.high} medium=${c.medium} low=${c.low} gen=${r.generation}
|
|
9336
|
+
return finish(r, line, `GRAPH-CHANGES ${r.symbols.length ? "found" : "none"} :: symbols=${r.symbols.length} high=${c.high} medium=${c.medium} low=${c.low} gen=${r.generation}`, true, gainRow);
|
|
9179
9337
|
}
|
|
9180
9338
|
const file = plain[2];
|
|
9181
9339
|
if (!file) return finish({ ok: false, reason: "missing-operand", usage, exit: 1 }, usage);
|
|
@@ -9190,6 +9348,18 @@ function graphCmd() {
|
|
|
9190
9348
|
return finish(r, line, `GRAPH-COCHANGE ${r.rows.length ? "found" : "none"} :: rows=${r.rows.length} commits=${r.commits}`);
|
|
9191
9349
|
}
|
|
9192
9350
|
|
|
9351
|
+
// A2 (v1.9.1) — `orc graph audit`. A THIN line says the map is thin; this
|
|
9352
|
+
// says WHY, and it is a USER command: no lane runs it (`LANE_CALLS` pins
|
|
9353
|
+
// `lanes: []`). It reads the index, the file table and the first lines of
|
|
9354
|
+
// each empty file. It never parses, never writes, and costs no model tokens.
|
|
9355
|
+
if (sub === "audit") {
|
|
9356
|
+
if (!enabled && flag("--if-enabled") === true) return finish({ ok: true, enabled: false, state: "off", exit: 3 }, "graph: off");
|
|
9357
|
+
const A = require("./graph-audit.js");
|
|
9358
|
+
const r = A.audit(claudeDir, root, { top: eqFlag("--top") });
|
|
9359
|
+
if (r.exit === 1) return finish(r, "graph: none — no index yet (run: orc graph update)");
|
|
9360
|
+
return finish(r, r.line, r.trace, false);
|
|
9361
|
+
}
|
|
9362
|
+
|
|
9193
9363
|
if (sub === "gc") {
|
|
9194
9364
|
const r = G.graphGc(claudeDir);
|
|
9195
9365
|
const line =
|
|
@@ -9289,16 +9459,21 @@ function graphCmd() {
|
|
|
9289
9459
|
if (flag("--history") !== undefined) {
|
|
9290
9460
|
const r = K.history(claudeDir, { limit: flag("--limit") });
|
|
9291
9461
|
if (!r.ok) return finish(r, "graph gain: no calls recorded yet");
|
|
9462
|
+
// `--history` IS its rows. Dropping them would leave an answer with
|
|
9463
|
+
// nothing in it, so the switch is refused here — out loud.
|
|
9464
|
+
const briefAsked = briefOn;
|
|
9465
|
+
briefOn = false;
|
|
9292
9466
|
const line =
|
|
9293
9467
|
`graph gain — last ${r.rows.length} of ${r.total} call(s), newest first\n` +
|
|
9294
9468
|
r.rows
|
|
9295
9469
|
.map(
|
|
9296
9470
|
(x) =>
|
|
9297
9471
|
` ${x.at} ${String(x.cmd).padEnd(10)} ${String((x.targets || []).join(",")).slice(0, 40).padEnd(40)}` +
|
|
9298
|
-
` paid ${String(x.paid.card + x.paid.source + x.paid.hints).padStart(6)} avoided ~${rng(x.avoided.low, x.avoided.high)}`
|
|
9472
|
+
` paid ${String(x.paid.card + x.paid.source + x.paid.hints + (x.paid.envelope || 0)).padStart(6)} avoided ~${rng(x.avoided.low, x.avoided.high)}`
|
|
9299
9473
|
)
|
|
9300
9474
|
.join("\n") +
|
|
9301
|
-
"\n `avoided` is an ESTIMATE of retrieval the ladder would have paid for — never a bill"
|
|
9475
|
+
"\n `avoided` is an ESTIMATE of retrieval the ladder would have paid for — never a bill" +
|
|
9476
|
+
(briefAsked ? " (--brief ignored on --history)" : "");
|
|
9302
9477
|
return finish(r, line);
|
|
9303
9478
|
}
|
|
9304
9479
|
|
|
@@ -9318,11 +9493,21 @@ function graphCmd() {
|
|
|
9318
9493
|
const scope = r.run ? `run ${r.run}` : r.since ? `last ${r.since}` : "this project";
|
|
9319
9494
|
const line =
|
|
9320
9495
|
U.header(`graph gain — ${scope} · ${plural(r.calls_recorded, "call")} · ${plural(r.runs, "run")}${g ? ` · gen ${g[0]}${g[1] !== g[0] ? `–${g[1]}` : ""}` : ""}`) +
|
|
9321
|
-
`\n paid ${kTok(r.paid.total).padStart(10)} tokens (cards ${kTok(r.paid.card)} · source ${kTok(r.paid.source)} · hints ${kTok(r.paid.hints)})` +
|
|
9496
|
+
`\n paid ${kTok(r.paid.total).padStart(10)} tokens (cards ${kTok(r.paid.card)} · source ${kTok(r.paid.source)} · hints ${kTok(r.paid.hints)} · envelope ${kTok(r.paid.envelope)})` +
|
|
9322
9497
|
`\n avoided ~${rng(r.avoided.low, r.avoided.high)} tokens (estimate — the read ladder done well … done badly)` +
|
|
9323
9498
|
`\n net ~${rng(r.net.low, r.net.high)} tokens · ~${r.calls.low} – ${r.calls.high} tool calls` +
|
|
9324
9499
|
(byCmd ? `\n by command ${byCmd}` : "") +
|
|
9325
9500
|
`\n hints ${r.hints.injected} injected · ${r.hints.read_notes} read notes · ${r.hints.updates} hook updates` +
|
|
9501
|
+
// R2 (v1.9.1): the reads the `on,read` hint would have named ranges for.
|
|
9502
|
+
// A COUNT, printed only when there is one — it is the data DE-8 waits
|
|
9503
|
+
// for, and nothing changes a setting because of it.
|
|
9504
|
+
(r.hints.wide_unhinted
|
|
9505
|
+
? `\n wide reads ${r.hints.wide_unhinted} whole-file reads of files with ${require("./graph-resolve.js").WIDE_MIN}+ symbols were not hinted — \`code_graph_hooks: on,read\` names their ranges`
|
|
9506
|
+
: "") +
|
|
9507
|
+
// M2: a read nobody made is a fact about this project, printed with no
|
|
9508
|
+
// advice after it. The graph is not wrong for holding an answer nobody
|
|
9509
|
+
// asked for, and the meter does not tell anyone to start asking.
|
|
9510
|
+
(r.never_called && r.never_called.length ? `\n never called ${r.never_called.join(" · ")}` : "") +
|
|
9326
9511
|
(r.unsized ? `
|
|
9327
9512
|
${plural(r.unsized, "row")} answered from SHARDS, where the size of the search replaced cannot be known — their estimate leaves it out` : "") +
|
|
9328
9513
|
"\n an estimate of avoided RETRIEVAL, never a bill — searches are a fraction of a percent of a session" +
|
|
@@ -9365,8 +9550,8 @@ function graphCmd() {
|
|
|
9365
9550
|
// gets it too. Appending it here would have shown it only to a human.
|
|
9366
9551
|
const line = r.card;
|
|
9367
9552
|
const trace = `GRAPH-MAP ${focus.length ? "focused" : "repo"} :: files=${r.shown}/${r.total_files}${focus.length ? ` focus=${r.focus.join(",")}` : ""} gen=${r.generation}`;
|
|
9368
|
-
|
|
9369
|
-
return finish(r, line, trace, false);
|
|
9553
|
+
const gainRow = r.exit === 0 ? gainRowFor("map", Q, model, focus, r, Date.now() - t0, false) : null;
|
|
9554
|
+
return finish(r, line, trace, false, gainRow);
|
|
9370
9555
|
}
|
|
9371
9556
|
|
|
9372
9557
|
if (sub === "ctx" || sub === "impact" || sub === "path") {
|
|
@@ -9391,6 +9576,8 @@ function graphCmd() {
|
|
|
9391
9576
|
// D2 is a SWITCH, so it is read from `args` — `flag()` would read the first
|
|
9392
9577
|
// declared file as its value.
|
|
9393
9578
|
const forSlice = args.includes("--for-slice");
|
|
9579
|
+
// R1 (v1.9.1): a SWITCH too — six lines around each confident call site.
|
|
9580
|
+
const callersSource = args.includes("--callers-source");
|
|
9394
9581
|
// `path` names two symbols, not files, so it has nothing cheap to check —
|
|
9395
9582
|
// it reads whatever generation is on disk, like every other command did
|
|
9396
9583
|
// before EW3.
|
|
@@ -9411,7 +9598,7 @@ function graphCmd() {
|
|
|
9411
9598
|
let fast = null;
|
|
9412
9599
|
if (sub === "ctx" && !forSlice && operands.length === 1) {
|
|
9413
9600
|
try {
|
|
9414
|
-
fast = require("./graph-shard.js").fastModel(claudeDir, root, operands[0]);
|
|
9601
|
+
fast = require("./graph-shard.js").fastModel(claudeDir, root, operands[0], { callersSource });
|
|
9415
9602
|
} catch (_) {
|
|
9416
9603
|
fast = null;
|
|
9417
9604
|
}
|
|
@@ -9439,6 +9626,7 @@ function graphCmd() {
|
|
|
9439
9626
|
format: String(flag("--format") || "prose") === "tree" ? "tree" : "prose",
|
|
9440
9627
|
offset: flag("--offset"),
|
|
9441
9628
|
source: sourceLines,
|
|
9629
|
+
callersSource,
|
|
9442
9630
|
wikiDocsFor,
|
|
9443
9631
|
};
|
|
9444
9632
|
let r;
|
|
@@ -9498,11 +9686,22 @@ function graphCmd() {
|
|
|
9498
9686
|
} else if (sub === "impact") {
|
|
9499
9687
|
if (!operands.length) return finish({ ok: false, reason: "missing-operand", usage, exit: 1 }, usage);
|
|
9500
9688
|
r = Q.impact(model, operands, opts);
|
|
9689
|
+
// V2/V3 (v1.9.1): the complexity read, and the `graph_facts` the
|
|
9690
|
+
// planner pastes — computed here, in ONE process, from the model this
|
|
9691
|
+
// call already loaded. Mini used to run `impact` plus one `cochange`
|
|
9692
|
+
// per declared file and count the rows in its own context.
|
|
9693
|
+
if (args.includes("--complexity") && r.exit === 0) {
|
|
9694
|
+
const SIG = require("./graph-signals.js");
|
|
9695
|
+
const cx = SIG.complexityOf(claudeDir, root, model, r.files, { risk: eqFlag("--risk"), tests: r.tests });
|
|
9696
|
+
r.complexity = { verdict: cx.verdict, why: cx.why, numbers: cx.numbers, line: cx.line, thresholds: cx.thresholds };
|
|
9697
|
+
r.facts = cx.facts;
|
|
9698
|
+
}
|
|
9501
9699
|
} else {
|
|
9502
9700
|
if (operands.length < 2) return finish({ ok: false, reason: "missing-operand", usage, exit: 1 }, usage);
|
|
9503
9701
|
r = Q.pathBetween(model, operands[0], operands[1]);
|
|
9504
9702
|
}
|
|
9505
9703
|
let line = r.card;
|
|
9704
|
+
if (line && r.complexity) line = `${line}\n ${r.complexity.line}`;
|
|
9506
9705
|
if (!line && r.state === "not-found") {
|
|
9507
9706
|
const near = (r.nearest || []).map((s) => `${s.qname} (${s.file}:${s.lines[0]})`);
|
|
9508
9707
|
line = r.missing
|
|
@@ -9526,21 +9725,26 @@ ${line || ""}`;
|
|
|
9526
9725
|
` +
|
|
9527
9726
|
(line || "");
|
|
9528
9727
|
}
|
|
9728
|
+
const cx = r.complexity || null;
|
|
9529
9729
|
const trace =
|
|
9530
|
-
|
|
9730
|
+
cx
|
|
9731
|
+
? `GRAPH-COMPLEXITY ${cx.verdict} :: files=${cx.numbers.files} callers=${cx.numbers.callers_outside} caller_files=${cx.numbers.caller_files_outside}` +
|
|
9732
|
+
` maybe=${cx.numbers.maybe} tests=${cx.numbers.tests_reaching} risk=${cx.numbers.risk.length} cochange=${cx.numbers.cochange_missing.length} gen=${r.generation || (r.facts && r.facts.generation) || 0}`
|
|
9733
|
+
: sub === "ctx" && r.exit === 0
|
|
9531
9734
|
? `GRAPH-CONSULT ${r.view === "for-slice" ? "slice" : "card"} :: targets=${(r.view === "for-slice" ? r.files : r.cards ? r.cards.filter((c) => c.state === "found").map((c) => c.query) : [operands[0]]).join(",")}` +
|
|
9532
9735
|
(healed && healed.state && healed.state !== "skipped" ? ` healed=${healed.trigger}` : "")
|
|
9533
9736
|
: null;
|
|
9737
|
+
let gainRow = null;
|
|
9534
9738
|
if (r.exit === 0) {
|
|
9535
9739
|
try {
|
|
9536
|
-
|
|
9740
|
+
gainRow = gainRowFor(sub, Q, model, operands, r, Date.now() - t0, forSlice);
|
|
9537
9741
|
} catch (_) {
|
|
9538
9742
|
// K6: the meter is never allowed to fail the read it is measuring. The
|
|
9539
9743
|
// append was already fail-quiet; the PRICING was not, because it was an
|
|
9540
9744
|
// argument to it.
|
|
9541
9745
|
}
|
|
9542
9746
|
}
|
|
9543
|
-
return finish(r, line, trace, !r.card);
|
|
9747
|
+
return finish(r, line, trace, !r.card, gainRow);
|
|
9544
9748
|
}
|
|
9545
9749
|
|
|
9546
9750
|
if (asJson) emitJson({ ok: false, reason: "unknown-subcommand", usage }, 1);
|
|
@@ -11034,7 +11238,7 @@ function resume() {
|
|
|
11034
11238
|
// assumed the opposite, so an interrupted turn produced a SECOND agent on the
|
|
11035
11239
|
// same task while the first was still working. A graded run put THREE
|
|
11036
11240
|
// `orc-executor-opus-5-low` agents on one task for 50m19s + 115m22s + 100m53s
|
|
11037
|
-
// — 266 minutes of Opus 5 for one authorised dispatch, all editing the same
|
|
11241
|
+
// — 266 minutes of Opus 5.5 for one authorised dispatch, all editing the same
|
|
11038
11242
|
// files. The hook already recorded every one of them; nothing ever READ it.
|
|
11039
11243
|
//
|
|
11040
11244
|
// The pending sidecar (`<trace>.pending.json`, written by orc-trace.js on every
|
|
@@ -21038,7 +21242,7 @@ function docForecastCmd(claudeDir, slugArg) {
|
|
|
21038
21242
|
for (const part of roleParts) {
|
|
21039
21243
|
const vec = vecFor(part.agent, part.n, pct);
|
|
21040
21244
|
if (!part.target) {
|
|
21041
|
-
const m = priceVector(claudeDir, vec, "claude-opus-5");
|
|
21245
|
+
const m = priceVector(claudeDir, vec, "claude-opus-5-5");
|
|
21042
21246
|
if (m.usd === null) priceable = false;
|
|
21043
21247
|
else total += m.usd;
|
|
21044
21248
|
continue;
|
|
@@ -21062,8 +21266,8 @@ function docForecastCmd(claudeDir, slugArg) {
|
|
|
21062
21266
|
};
|
|
21063
21267
|
const usd50 = usdAt("p50");
|
|
21064
21268
|
const usd90 = usdAt("p90");
|
|
21065
|
-
const money50 = priceVector(claudeDir, p50, "claude-opus-5");
|
|
21066
|
-
const money90 = priceVector(claudeDir, p90, "claude-opus-5");
|
|
21269
|
+
const money50 = priceVector(claudeDir, p50, "claude-opus-5-5");
|
|
21270
|
+
const money90 = priceVector(claudeDir, p90, "claude-opus-5-5");
|
|
21067
21271
|
const extraView = {
|
|
21068
21272
|
resolved: docExtra.resolved,
|
|
21069
21273
|
why: docExtra.why,
|
|
@@ -21282,7 +21486,7 @@ function docCostCmd(claudeDir, slugArg) {
|
|
|
21282
21486
|
runRows.push({ trace: r.name, lane: r.lane, date: r.date, tokens: runVec, weighted: weightedTokens(runVec) });
|
|
21283
21487
|
}
|
|
21284
21488
|
|
|
21285
|
-
const money = priceVector(claudeDir, total, "claude-opus-5");
|
|
21489
|
+
const money = priceVector(claudeDir, total, "claude-opus-5-5");
|
|
21286
21490
|
const sections = Object.values(bySection).map((s) => ({
|
|
21287
21491
|
id: s.id,
|
|
21288
21492
|
heading: s.heading,
|
|
@@ -21291,7 +21495,7 @@ function docCostCmd(claudeDir, slugArg) {
|
|
|
21291
21495
|
joined: s.joined > 0,
|
|
21292
21496
|
tokens: s.joined ? s.vec : null,
|
|
21293
21497
|
weighted: s.joined ? weightedTokens(s.vec) : null,
|
|
21294
|
-
usd: s.joined ? priceVector(claudeDir, s.vec, "claude-opus-5").usd : null,
|
|
21498
|
+
usd: s.joined ? priceVector(claudeDir, s.vec, "claude-opus-5-5").usd : null,
|
|
21295
21499
|
}));
|
|
21296
21500
|
const unjoined = sections.filter((s) => !s.joined).length;
|
|
21297
21501
|
const code = joined === 0 ? 3 : unjoined ? 1 : 0;
|
|
@@ -25625,8 +25829,8 @@ function extraResolveFor(claudeDir, score, opts) {
|
|
|
25625
25829
|
//
|
|
25626
25830
|
// `claude` is an ARRAY because `quick-executor` has two: a menu is what that
|
|
25627
25831
|
// lane is. `claude_opus5` is the variant `opus5_only` would have used, derived
|
|
25628
|
-
// from the shipped ladders — NULL where the agent is already Opus 5, so two
|
|
25629
|
-
// wiki slots collapsing onto one Opus 5 scanner is not a contradiction: the
|
|
25832
|
+
// from the shipped ladders — NULL where the agent is already Opus 5.5, so two
|
|
25833
|
+
// wiki slots collapsing onto one Opus 5.5 scanner is not a contradiction: the
|
|
25630
25834
|
// slot names the POSITION, not the model. NO AGENT IS ADDED by this release
|
|
25631
25835
|
// and no pair is needed (the floor stays 51).
|
|
25632
25836
|
const EXTRA_SLOTS = [
|
|
@@ -43401,7 +43605,7 @@ function slEngine() {
|
|
|
43401
43605
|
// panel really hands over — including `tokenCount`, which is the number v1.2.0
|
|
43402
43606
|
// concluded could not be measured.
|
|
43403
43607
|
const SL_TASK_FIXTURES = {
|
|
43404
|
-
healthy: { id: "t1", name: "orc-executor-opus-5-low", type: "orc-executor-opus-5-low", description: "wire the retry ladder", status: "running", model: "claude-opus-5", effort: "low", tokenCount: 84000, contextWindowSize: 200000, startTime: 1767225600000 - 17 * 60000 },
|
|
43608
|
+
healthy: { id: "t1", name: "orc-executor-opus-5-low", type: "orc-executor-opus-5-low", description: "wire the retry ladder", status: "running", model: "claude-opus-5-5", effort: "low", tokenCount: 84000, contextWindowSize: 200000, startTime: 1767225600000 - 17 * 60000 },
|
|
43405
43609
|
degraded: { id: "t2", name: "orc-executor-sonnet-4-6-med", type: "orc-executor-sonnet-4-6-med", description: "rename two files", status: "failed", model: "claude-sonnet-4-6", effort: "medium", tokenCount: 191000, contextWindowSize: 200000, startTime: 1767225600000 - 96 * 60000 },
|
|
43406
43610
|
empty: { id: "t3" },
|
|
43407
43611
|
};
|
|
@@ -43410,7 +43614,7 @@ const SL_FIXTURES = {
|
|
|
43410
43614
|
healthy: {
|
|
43411
43615
|
label: "a healthy session mid-run",
|
|
43412
43616
|
payload: {
|
|
43413
|
-
model: { id: "claude-opus-5", display_name: "Opus 5" },
|
|
43617
|
+
model: { id: "claude-opus-5-5", display_name: "Opus 5.5" },
|
|
43414
43618
|
effort: { level: "high" },
|
|
43415
43619
|
version: "2.1.80",
|
|
43416
43620
|
context_window: { used_percentage: 38, remaining_percentage: 62, context_window_size: 200000 },
|