@azure-id/orc 1.9.1 → 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.
Files changed (107) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/README-id.md +38 -39
  3. package/README.md +36 -35
  4. package/bin/build-agents.js +109 -109
  5. package/bin/cli.js +35 -33
  6. package/bin/onboarding-content.js +4 -4
  7. package/bin/pricing.json +207 -200
  8. package/bin/verify-contracts.js +2 -2
  9. package/bin/verify-package.js +7 -7
  10. package/bin/webui/css/04-motion.css +162 -152
  11. package/bin/webui/css/panels/knowledge.css +563 -116
  12. package/bin/webui/fixtures/extra.js +2036 -2036
  13. package/bin/webui/fixtures/hookui.js +5 -5
  14. package/bin/webui/fixtures/settings.js +305 -305
  15. package/bin/webui/i18n/en/knowledge.json +117 -2
  16. package/bin/webui/i18n/id/knowledge.json +117 -2
  17. package/bin/webui/js/panels/knowledge.js +552 -7
  18. package/bin/webui/js/panels/overview.js +13 -4
  19. package/mock-run/context-combiner.md +100 -100
  20. package/mock-run/orc-budget.md +534 -534
  21. package/mock-run/orc-challenge-council.md +262 -262
  22. package/mock-run/orc-ultra.md +103 -103
  23. package/package.json +1 -1
  24. package/templates/agents/MODEL-MAPPING.md +43 -43
  25. package/templates/agents/orc-advisor-opus-5-xhigh.md +56 -56
  26. package/templates/agents/orc-analyze-mini-opus-5-med.md +60 -60
  27. package/templates/agents/orc-analyze-mini-sonnet-5-high.md +58 -58
  28. package/templates/agents/orc-challenge-advisor-opus-5-med.md +75 -75
  29. package/templates/agents/orc-challenge-contrarian-opus-5-high.md +110 -110
  30. package/templates/agents/orc-challenge-executor-opus-5-med.md +114 -114
  31. package/templates/agents/orc-challenge-expansionist-opus-5-med.md +112 -112
  32. package/templates/agents/orc-challenge-judge-opus-5-high.md +132 -132
  33. package/templates/agents/orc-challenge-outsider-opus-5-low.md +109 -109
  34. package/templates/agents/orc-challenge-principles-opus-5-high.md +109 -109
  35. package/templates/agents/orc-challenge-reader-opus-5-low.md +90 -90
  36. package/templates/agents/orc-claude-writer-opus-5-med.md +55 -55
  37. package/templates/agents/orc-context-combiner-opus-5-high.md +88 -88
  38. package/templates/agents/orc-doc-checker-opus-5-low.md +108 -108
  39. package/templates/agents/orc-doc-writer-opus-5-med.md +134 -134
  40. package/templates/agents/orc-executor-opus-5-high.md +2 -2
  41. package/templates/agents/orc-executor-opus-5-low.md +2 -2
  42. package/templates/agents/orc-executor-opus-5-med.md +2 -2
  43. package/templates/agents/orc-graph-noter-sonnet-4-6-med.md +1 -1
  44. package/templates/agents/orc-judge-opus-5-xhigh.md +85 -85
  45. package/templates/agents/orc-learn-writer-opus-5-low.md +73 -73
  46. package/templates/agents/orc-pattern-codifier-opus-5-med.md +65 -65
  47. package/templates/agents/orc-planner-mini-opus-5-med.md +4 -4
  48. package/templates/agents/orc-planner-mini-sonnet-5-high.md +1 -1
  49. package/templates/agents/orc-planner-opus-5-med.md +160 -160
  50. package/templates/agents/orc-recon-opus-5-low.md +3 -3
  51. package/templates/agents/orc-retro-opus-5-med.md +3 -3
  52. package/templates/agents/orc-reviewer-opus-5-med.md +60 -60
  53. package/templates/agents/orc-scout-opus-5-low.md +40 -40
  54. package/templates/agents/orc-system-analyst-opus-5-high.md +120 -120
  55. package/templates/agents/orc-test-author-opus-5-med.md +71 -71
  56. package/templates/agents/orc-test-designer-opus-5-high.md +158 -158
  57. package/templates/agents/orc-test-interpreter-opus-5-low.md +130 -130
  58. package/templates/agents/orc-verifier-opus-5-med.md +69 -69
  59. package/templates/agents/orc-wiki-scanner-opus-5-med.md +81 -81
  60. package/templates/commands/orc-ultra.md +17 -17
  61. package/templates/commands/orc-verify.md +11 -11
  62. package/templates/hooks/README.md +2 -2
  63. package/templates/hooks/orc-effort-guard.js +178 -178
  64. package/templates/hooks/orc-statusline.js +6 -6
  65. package/templates/skills/_shared/code-graph.md +1 -1
  66. package/templates/skills/_shared/config-precedence.md +198 -198
  67. package/templates/skills/_shared/extra-dispatch.md +1346 -1346
  68. package/templates/skills/_shared/opus5-only.md +8 -8
  69. package/templates/skills/_shared/phases/analyst-gates.md +136 -136
  70. package/templates/skills/_shared/phases/review.md +1 -1
  71. package/templates/skills/_shared/phases/trace.md +1 -1
  72. package/templates/skills/_shared/return-validation.md +1 -1
  73. package/templates/skills/context-combiner/SKILL.md +1 -1
  74. package/templates/skills/context-combiner/schemas/combined-report.md +78 -78
  75. package/templates/skills/orc/README.md +2 -2
  76. package/templates/skills/orc/SKILL.md +7 -7
  77. package/templates/skills/orc/config.md +9 -9
  78. package/templates/skills/orc/examples/full-run-mock.md +73 -73
  79. package/templates/skills/orc/references/effort-and-mode.md +222 -222
  80. package/templates/skills/orc/references/preflight-report.md +2 -2
  81. package/templates/skills/orc/references/ultra-mode.md +3 -3
  82. package/templates/skills/orc/subskills/orc-planner/SKILL.md +2 -2
  83. package/templates/skills/orc/subskills/orc-planner-mini/SKILL.md +121 -121
  84. package/templates/skills/orc/subskills/orc-review-verify/SKILL.md +76 -76
  85. package/templates/skills/orc/subskills/orc-testgen/SKILL.md +45 -45
  86. package/templates/skills/orc-analyze/SKILL.md +2 -2
  87. package/templates/skills/orc-analyze/examples/analyze-mock.md +42 -42
  88. package/templates/skills/orc-analyze/schemas/report-audit.md +83 -83
  89. package/templates/skills/orc-analyze/schemas/report-prose.md +63 -63
  90. package/templates/skills/orc-analyze/schemas/report-requirement.md +78 -78
  91. package/templates/skills/orc-challenge/README.md +142 -142
  92. package/templates/skills/orc-challenge/examples/council-full-roster.md +273 -273
  93. package/templates/skills/orc-challenge/references/council.md +315 -315
  94. package/templates/skills/orc-challenge/references/intake.md +171 -171
  95. package/templates/skills/orc-claude/SKILL.md +14 -14
  96. package/templates/skills/orc-diy/README.md +143 -143
  97. package/templates/skills/orc-diy/references/flow-schema.md +1 -1
  98. package/templates/skills/orc-doc/README.md +229 -229
  99. package/templates/skills/orc-doc/examples/orc-doc-prd-run.md +325 -325
  100. package/templates/skills/orc-doc/references/chunking.md +527 -527
  101. package/templates/skills/orc-fast/SKILL.md +1 -1
  102. package/templates/skills/orc-learn/SKILL.md +14 -14
  103. package/templates/skills/orc-learn/examples/learn-run-mock.md +61 -61
  104. package/templates/skills/orc-mini/SKILL.md +3 -3
  105. package/templates/skills/orc-verify/SKILL.md +15 -15
  106. package/templates/skills/orc-verify/examples/verify-mock.md +33 -33
  107. package/templates/skills/orc-wiki/references/extra.md +1 -1
@@ -1,178 +1,178 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
-
4
- /**
5
- * ORC effort guard — a Claude Code PreToolUse hook.
6
- *
7
- * Blocks invocation of the full `orc` orchestrator skill unless the MAIN
8
- * session is running at HIGH reasoning effort (Opus 5 / Fable 5 clear at
9
- * medium+ — see the session-model bridge below). This is the one half of the
10
- * "run ORC on Opus 4.8 high or better" rule hooks can enforce deterministically:
11
- * Claude Code exposes `effort.level` (and $CLAUDE_EFFORT) to PreToolUse, but
12
- * NOT the model id (only SessionStart may see the model, and cannot block).
13
- * The model tier is surfaced separately by the statusline warning + the
14
- * self-check inside skills/orc/SKILL.md.
15
- *
16
- * Wiring (installed by `orc init` into .claude/settings.json):
17
- * hooks.PreToolUse[] { matcher: "Skill", hooks:[{ type:"command",
18
- * command: 'node "<.claude>/hooks/orc-effort-guard.js"' }] }
19
- *
20
- * Contract: read PreToolUse JSON from stdin. Exit 0 = allow. Exit 2 = block
21
- * the tool call and show stderr to Claude, which relays it to the user.
22
- *
23
- * Also surfaces a "newer orc version available" nudge here — this hook fires
24
- * exactly when /orc is invoked, so it's the natural place to tell the user
25
- * without them running `orc version`. On allow it emits a `systemMessage`
26
- * (shown to the user, NOT added to model context → zero tokens); on block it
27
- * appends the nudge to the block reason. Version check is cached 24h and
28
- * fail-silent. (systemMessage handling may vary by Claude Code version — verify
29
- * with /doctor if you don't see it; the statusline shows it regardless.)
30
- */
31
-
32
- // Shared update-check helper (sibling file). Degrade gracefully if absent.
33
- let updater = null;
34
- try {
35
- updater = require("./orc-update-lib.js");
36
- } catch (_) {
37
- updater = null;
38
- }
39
-
40
- // Effort ladder: low < medium < high < xhigh < max. A tier that meets the bar
41
- // meets it at that rung OR anything stronger — so "requires high" allows xhigh
42
- // and max too (the bug this fixes: an xhigh/max session was hard-blocked).
43
- const EFFORT_LADDER = ["low", "medium", "high", "xhigh", "max"];
44
- const effortsAtOrAbove = (e) => {
45
- const i = EFFORT_LADDER.indexOf(String(e).toLowerCase());
46
- return i === -1 ? ["high", "xhigh", "max"] : EFFORT_LADDER.slice(i);
47
- };
48
-
49
- // Session-model bridge (written by orc-statusline.js). The guard can't see the
50
- // model id itself, so it reads it here to grant the medium-effort allowance of
51
- // the models that are strictly stronger than the Opus 4.8 baseline (Opus 5 and
52
- // Fable 5). Fail-OPEN: missing / unreadable / stale → null, and the guard
53
- // behaves exactly as it would without a bridge (never blocks on our own error).
54
- // Stale = older than this window; a live session re-renders the statusline far
55
- // more often, so a fresh file always exists during active use.
56
- const BRIDGE_MAX_AGE_MS = 30 * 60 * 1000;
57
- function readSessionModel(projectDir) {
58
- try {
59
- const fs = require("fs");
60
- const path = require("path");
61
- const p = path.join(projectDir, ".claude", "orc", "session-model.json");
62
- const j = JSON.parse(fs.readFileSync(p, "utf8").replace(/^/, ""));
63
- if (!j || typeof j.written_at !== "number") return null;
64
- if (Date.now() - j.written_at > BRIDGE_MAX_AGE_MS) return null;
65
- return String(j.model_id || "");
66
- } catch (_) {
67
- return null;
68
- }
69
- }
70
- // Models that clear /orc at medium effort — strictly stronger than the Opus 4.8
71
- // baseline, so medium on them beats high on it. Opus 5 (v0.34.0) joins Fable 5.
72
- // The `\b` after the 5 keeps 4.8 / 4.7 / 5-something-else correctly gated.
73
- const isMediumOkModel = (id) =>
74
- /(opus|fable)[\s._-]?5\b/.test(String(id || "").toLowerCase());
75
-
76
- let raw = "";
77
- process.stdin.on("data", (c) => (raw += c));
78
- process.stdin.on("end", () => {
79
- let data = {};
80
- try {
81
- data = JSON.parse(raw || "{}");
82
- } catch (_) {
83
- // Unparseable payload — never block on our own error.
84
- process.exit(0);
85
- }
86
-
87
- const tool = data.tool_name || "";
88
- const input = data.tool_input || {};
89
- const skill = String(input.skill || input.name || "");
90
-
91
- // Only gate the full orchestrator and the compiled DIY lane. orc-mini /
92
- // orc-fast / orc-analyze / subskills pass — orc-fast is DESIGNED to run at
93
- // Sonnet medium; never widen this match to include it.
94
- const isOrc = tool === "Skill" && /^orc$/i.test(skill);
95
- const isDiy = tool === "Skill" && /^orc-diy$/i.test(skill);
96
- if (!isOrc && !isDiy) process.exit(0);
97
-
98
- const effort = String(
99
- (data.effort && data.effort.level) || process.env.CLAUDE_EFFORT || ""
100
- ).toLowerCase();
101
- const installed = updater ? updater.installedVersion(__dirname) : null;
102
- const projectDir = data.cwd || process.cwd();
103
-
104
- // Baseline /orc: the session must be at high effort OR stronger (xhigh/max).
105
- // Opus 5 and Fable 5 additionally clear at medium — strictly-capable models —
106
- // detected through the session-model bridge (the guard can't see the model id
107
- // itself; fail-open when the bridge is missing/stale, i.e. medium stays blocked).
108
- let requiredEfforts = effortsAtOrAbove("high");
109
- let requiredLabel =
110
- "Opus 4.8 at high effort (Opus 5 / Fable 5 also clear at medium+)";
111
- if (!isDiy && isMediumOkModel(readSessionModel(projectDir))) {
112
- requiredEfforts = ["medium", ...requiredEfforts];
113
- }
114
-
115
- // /orc-diy: the required tier is whatever the flow was COMPILED for — read
116
- // it from flow.lock.json (written only by the `orc diy` CLI). Fail closed:
117
- // no lock = no compiled flow = deterministic onboarding block. `compile` /
118
- // `status` invocations pass at any effort (they just shell out to the CLI).
119
- if (isDiy) {
120
- if (/^\s*(compile|status)\b/i.test(String(input.args || ""))) process.exit(0);
121
- const fs = require("fs");
122
- const path = require("path");
123
- let lock = null;
124
- try {
125
- lock = JSON.parse(
126
- fs
127
- .readFileSync(
128
- path.join(projectDir, ".claude", "orc", "diy", "flow.lock.json"),
129
- "utf8"
130
- )
131
- .replace(/^\uFEFF/, "")
132
- );
133
- } catch (_) {}
134
- if (!lock || !lock.session_tier) {
135
- process.stderr.write(
136
- "\n⛔ /orc-diy blocked — no compiled flow in this project (fail-closed gate)." +
137
- "\n Compose and build your flow in the terminal first:" +
138
- "\n orc diy init (then shape it: orc diy set <key> <value>)" +
139
- "\n orc diy compile" +
140
- "\n Guide: .claude/skills/orc-diy/README.md — or use plain /orc for this request.\n"
141
- );
142
- process.exit(2);
143
- }
144
- // Effort half is DETERMINISTIC from the compiled slug's suffix (allow that
145
- // effort or anything stronger); the model half is warn-only on the
146
- // statusline (hooks can't block on model). Covers the full tier grid —
147
- // sonnet-4-6 / opus-4-7 / opus-4-8 / fable-5 at med|high|xhigh|max.
148
- const m = String(lock.session_tier).match(/-(med|high|xhigh|max)$/);
149
- const slugEffort = m ? (m[1] === "med" ? "medium" : m[1]) : "high";
150
- requiredEfforts = effortsAtOrAbove(slugEffort);
151
- requiredLabel = `${lock.session_tier} (compiled session_tier — needs effort ${slugEffort}+)`;
152
- }
153
-
154
- const decide = (nudge) => {
155
- if (requiredEfforts.includes(effort)) {
156
- // Requirement met — allow. Surface a version nudge if one exists.
157
- if (nudge) {
158
- try {
159
- process.stdout.write(JSON.stringify({ systemMessage: nudge }));
160
- } catch (_) {}
161
- }
162
- process.exit(0);
163
- }
164
-
165
- process.stderr.write(
166
- `\n⛔ ${isDiy ? "/orc-diy" : "ORC"} blocked — required effort not met` +
167
- (effort ? ` (current effort: ${effort}).` : " (effort not detected).") +
168
- `\n Switch this session to ${requiredLabel}, then re-run.` +
169
- "\n Run the MAIN session at (or above) the required tier — subagents cannot" +
170
- "\n exceed the main tier, so pinned agents silently downgrade below it.\n" +
171
- (nudge ? "\n" + nudge + "\n" : "")
172
- );
173
- process.exit(2);
174
- };
175
-
176
- if (updater) updater.refreshAndNudge(installed, decide);
177
- else decide(null);
178
- });
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ /**
5
+ * ORC effort guard — a Claude Code PreToolUse hook.
6
+ *
7
+ * Blocks invocation of the full `orc` orchestrator skill unless the MAIN
8
+ * session is running at HIGH reasoning effort (Opus 5.5 / Fable 5 clear at
9
+ * medium+ — see the session-model bridge below). This is the one half of the
10
+ * "run ORC on Opus 4.8 high or better" rule hooks can enforce deterministically:
11
+ * Claude Code exposes `effort.level` (and $CLAUDE_EFFORT) to PreToolUse, but
12
+ * NOT the model id (only SessionStart may see the model, and cannot block).
13
+ * The model tier is surfaced separately by the statusline warning + the
14
+ * self-check inside skills/orc/SKILL.md.
15
+ *
16
+ * Wiring (installed by `orc init` into .claude/settings.json):
17
+ * hooks.PreToolUse[] { matcher: "Skill", hooks:[{ type:"command",
18
+ * command: 'node "<.claude>/hooks/orc-effort-guard.js"' }] }
19
+ *
20
+ * Contract: read PreToolUse JSON from stdin. Exit 0 = allow. Exit 2 = block
21
+ * the tool call and show stderr to Claude, which relays it to the user.
22
+ *
23
+ * Also surfaces a "newer orc version available" nudge here — this hook fires
24
+ * exactly when /orc is invoked, so it's the natural place to tell the user
25
+ * without them running `orc version`. On allow it emits a `systemMessage`
26
+ * (shown to the user, NOT added to model context → zero tokens); on block it
27
+ * appends the nudge to the block reason. Version check is cached 24h and
28
+ * fail-silent. (systemMessage handling may vary by Claude Code version — verify
29
+ * with /doctor if you don't see it; the statusline shows it regardless.)
30
+ */
31
+
32
+ // Shared update-check helper (sibling file). Degrade gracefully if absent.
33
+ let updater = null;
34
+ try {
35
+ updater = require("./orc-update-lib.js");
36
+ } catch (_) {
37
+ updater = null;
38
+ }
39
+
40
+ // Effort ladder: low < medium < high < xhigh < max. A tier that meets the bar
41
+ // meets it at that rung OR anything stronger — so "requires high" allows xhigh
42
+ // and max too (the bug this fixes: an xhigh/max session was hard-blocked).
43
+ const EFFORT_LADDER = ["low", "medium", "high", "xhigh", "max"];
44
+ const effortsAtOrAbove = (e) => {
45
+ const i = EFFORT_LADDER.indexOf(String(e).toLowerCase());
46
+ return i === -1 ? ["high", "xhigh", "max"] : EFFORT_LADDER.slice(i);
47
+ };
48
+
49
+ // Session-model bridge (written by orc-statusline.js). The guard can't see the
50
+ // model id itself, so it reads it here to grant the medium-effort allowance of
51
+ // the models that are strictly stronger than the Opus 4.8 baseline (Opus 5.5 and
52
+ // Fable 5). Fail-OPEN: missing / unreadable / stale → null, and the guard
53
+ // behaves exactly as it would without a bridge (never blocks on our own error).
54
+ // Stale = older than this window; a live session re-renders the statusline far
55
+ // more often, so a fresh file always exists during active use.
56
+ const BRIDGE_MAX_AGE_MS = 30 * 60 * 1000;
57
+ function readSessionModel(projectDir) {
58
+ try {
59
+ const fs = require("fs");
60
+ const path = require("path");
61
+ const p = path.join(projectDir, ".claude", "orc", "session-model.json");
62
+ const j = JSON.parse(fs.readFileSync(p, "utf8").replace(/^/, ""));
63
+ if (!j || typeof j.written_at !== "number") return null;
64
+ if (Date.now() - j.written_at > BRIDGE_MAX_AGE_MS) return null;
65
+ return String(j.model_id || "");
66
+ } catch (_) {
67
+ return null;
68
+ }
69
+ }
70
+ // Models that clear /orc at medium effort — strictly stronger than the Opus 4.8
71
+ // baseline, so medium on them beats high on it. Opus 5.5 (v0.34.0) joins Fable 5.
72
+ // The `\b` after the 5 keeps 4.8 / 4.7 / 5-something-else correctly gated.
73
+ const isMediumOkModel = (id) =>
74
+ /(opus|fable)[\s._-]?5\b/.test(String(id || "").toLowerCase());
75
+
76
+ let raw = "";
77
+ process.stdin.on("data", (c) => (raw += c));
78
+ process.stdin.on("end", () => {
79
+ let data = {};
80
+ try {
81
+ data = JSON.parse(raw || "{}");
82
+ } catch (_) {
83
+ // Unparseable payload — never block on our own error.
84
+ process.exit(0);
85
+ }
86
+
87
+ const tool = data.tool_name || "";
88
+ const input = data.tool_input || {};
89
+ const skill = String(input.skill || input.name || "");
90
+
91
+ // Only gate the full orchestrator and the compiled DIY lane. orc-mini /
92
+ // orc-fast / orc-analyze / subskills pass — orc-fast is DESIGNED to run at
93
+ // Sonnet medium; never widen this match to include it.
94
+ const isOrc = tool === "Skill" && /^orc$/i.test(skill);
95
+ const isDiy = tool === "Skill" && /^orc-diy$/i.test(skill);
96
+ if (!isOrc && !isDiy) process.exit(0);
97
+
98
+ const effort = String(
99
+ (data.effort && data.effort.level) || process.env.CLAUDE_EFFORT || ""
100
+ ).toLowerCase();
101
+ const installed = updater ? updater.installedVersion(__dirname) : null;
102
+ const projectDir = data.cwd || process.cwd();
103
+
104
+ // Baseline /orc: the session must be at high effort OR stronger (xhigh/max).
105
+ // Opus 5.5 and Fable 5 additionally clear at medium — strictly-capable models —
106
+ // detected through the session-model bridge (the guard can't see the model id
107
+ // itself; fail-open when the bridge is missing/stale, i.e. medium stays blocked).
108
+ let requiredEfforts = effortsAtOrAbove("high");
109
+ let requiredLabel =
110
+ "Opus 4.8 at high effort (Opus 5.5 / Fable 5 also clear at medium+)";
111
+ if (!isDiy && isMediumOkModel(readSessionModel(projectDir))) {
112
+ requiredEfforts = ["medium", ...requiredEfforts];
113
+ }
114
+
115
+ // /orc-diy: the required tier is whatever the flow was COMPILED for — read
116
+ // it from flow.lock.json (written only by the `orc diy` CLI). Fail closed:
117
+ // no lock = no compiled flow = deterministic onboarding block. `compile` /
118
+ // `status` invocations pass at any effort (they just shell out to the CLI).
119
+ if (isDiy) {
120
+ if (/^\s*(compile|status)\b/i.test(String(input.args || ""))) process.exit(0);
121
+ const fs = require("fs");
122
+ const path = require("path");
123
+ let lock = null;
124
+ try {
125
+ lock = JSON.parse(
126
+ fs
127
+ .readFileSync(
128
+ path.join(projectDir, ".claude", "orc", "diy", "flow.lock.json"),
129
+ "utf8"
130
+ )
131
+ .replace(/^\uFEFF/, "")
132
+ );
133
+ } catch (_) {}
134
+ if (!lock || !lock.session_tier) {
135
+ process.stderr.write(
136
+ "\n⛔ /orc-diy blocked — no compiled flow in this project (fail-closed gate)." +
137
+ "\n Compose and build your flow in the terminal first:" +
138
+ "\n orc diy init (then shape it: orc diy set <key> <value>)" +
139
+ "\n orc diy compile" +
140
+ "\n Guide: .claude/skills/orc-diy/README.md — or use plain /orc for this request.\n"
141
+ );
142
+ process.exit(2);
143
+ }
144
+ // Effort half is DETERMINISTIC from the compiled slug's suffix (allow that
145
+ // effort or anything stronger); the model half is warn-only on the
146
+ // statusline (hooks can't block on model). Covers the full tier grid —
147
+ // sonnet-4-6 / opus-4-7 / opus-4-8 / fable-5 at med|high|xhigh|max.
148
+ const m = String(lock.session_tier).match(/-(med|high|xhigh|max)$/);
149
+ const slugEffort = m ? (m[1] === "med" ? "medium" : m[1]) : "high";
150
+ requiredEfforts = effortsAtOrAbove(slugEffort);
151
+ requiredLabel = `${lock.session_tier} (compiled session_tier — needs effort ${slugEffort}+)`;
152
+ }
153
+
154
+ const decide = (nudge) => {
155
+ if (requiredEfforts.includes(effort)) {
156
+ // Requirement met — allow. Surface a version nudge if one exists.
157
+ if (nudge) {
158
+ try {
159
+ process.stdout.write(JSON.stringify({ systemMessage: nudge }));
160
+ } catch (_) {}
161
+ }
162
+ process.exit(0);
163
+ }
164
+
165
+ process.stderr.write(
166
+ `\n⛔ ${isDiy ? "/orc-diy" : "ORC"} blocked — required effort not met` +
167
+ (effort ? ` (current effort: ${effort}).` : " (effort not detected).") +
168
+ `\n Switch this session to ${requiredLabel}, then re-run.` +
169
+ "\n Run the MAIN session at (or above) the required tier — subagents cannot" +
170
+ "\n exceed the main tier, so pinned agents silently downgrade below it.\n" +
171
+ (nudge ? "\n" + nudge + "\n" : "")
172
+ );
173
+ process.exit(2);
174
+ };
175
+
176
+ if (updater) updater.refreshAndNudge(installed, decide);
177
+ else decide(null);
178
+ });
@@ -24,8 +24,8 @@
24
24
  * ICON carries the verdict and the words carry the installed ORC version — but
25
25
  * the degrade branch still names every reason, because a warning with no reason
26
26
  * is an emoji:
27
- * ✅ ORC v1.2.1 - Opus 5/high Opus 4.8 high (the baseline)
28
- * 🚀 ORC v1.2.1 - Opus 5/high Opus 4.8 xhigh/max, or Opus 5 / Fable 5 medium…max
27
+ * ✅ ORC v1.2.1 - Opus 5.5/high Opus 4.8 high (the baseline)
28
+ * 🚀 ORC v1.2.1 - Opus 5.5/high Opus 4.8 xhigh/max, or Opus 5.5 / Fable 5 medium…max
29
29
  * ⛔ ORC v1.2.1 - Sonnet 5/high (why) everything below (wrong model, sub-baseline effort, quota)
30
30
  *
31
31
  * The two lines, in full (v1.2.1):
@@ -52,7 +52,7 @@
52
52
  * This is the ONLY place Claude Code exposes the live model id, so it also
53
53
  * writes a fail-silent session-model bridge (.claude/orc/session-model.json)
54
54
  * that the PreToolUse effort guard reads — the guard can't see the model id
55
- * on its own, so the bridge is how the Opus 5 / Fable 5 medium-effort allowance
55
+ * on its own, so the bridge is how the Opus 5.5 / Fable 5 medium-effort allowance
56
56
  * reaches it.
57
57
  *
58
58
  * Also appends a "newer orc version available" hint from the 24h update cache
@@ -66,7 +66,7 @@
66
66
  * over that budget — ORC_STATUSLINE_SCAN_MS — and nothing in ORC ever sets it.
67
67
  */
68
68
 
69
- // Opus 4.8 / Opus 5 / Fable 5 are matched by tolerant regexes below (accept
69
+ // Opus 4.8 / Opus 5.5 / Fable 5 are matched by tolerant regexes below (accept
70
70
  // dated/suffixed ids and the display name), not strict strings. Effort ranks give
71
71
  // the acceptance-matrix tiers (0 = unknown, never treated as a positive downgrade).
72
72
  const EFFORT_RANK = { low: 1, medium: 2, high: 3, xhigh: 4, max: 5 };
@@ -526,7 +526,7 @@ process.stdin.on("end", () => {
526
526
  // ── Session-model bridge (fail-silent) ─────────────────────────────────────
527
527
  // The PreToolUse effort guard cannot see the model id; it can only read
528
528
  // effort. Persist {model_id, effort, written_at} here so the guard can grant
529
- // the Opus 5 / Fable 5 medium-effort allowance. The statusline re-renders constantly
529
+ // the Opus 5.5 / Fable 5 medium-effort allowance. The statusline re-renders constantly
530
530
  // while a session is active, so written_at stays fresh; the guard treats a
531
531
  // stale file (older than its freshness window) as absent and never blocks on
532
532
  // it. Any error (no dir, read-only fs) is swallowed — this is a nicety, not a
@@ -674,7 +674,7 @@ process.stdin.on("end", () => {
674
674
  const hay = `${model} ${display}`.toLowerCase();
675
675
  const isOpus48 = /opus[\s._-]?4[\s._-]?8\b/.test(hay);
676
676
  const isFable5 = /fable[\s._-]?5\b/.test(hay);
677
- // Opus 5 (v0.34.0) — strictly above the baseline, so it boosts from medium up,
677
+ // Opus 5.5 (v0.34.0) — strictly above the baseline, so it boosts from medium up,
678
678
  // exactly like Fable 5. The `\b` keeps opus 4.8 / 4.7 out of this branch.
679
679
  const isOpus5 = /opus[\s._-]?5\b/.test(hay);
680
680
  const modelKnown = model !== "" || (display !== "" && display !== "unknown");
@@ -294,7 +294,7 @@ false.
294
294
  on every later turn (~100K tokens across a 6-task run).
295
295
  4. `code_graph_notes: wave` → once per wave. `end` → once, at the end of the
296
296
  run, for every path the run changed.
297
- 5. Under `opus5_only` there is no Opus 5 noter. Print
297
+ 5. Under `opus5_only` there is no Opus 5.5 noter. Print
298
298
  `graph notes: skipped (opus5_only)` once and dispatch nothing.
299
299
 
300
300
  ## 7. Slice injection — and when NOT to inject