@dzhechkov/harness-core 0.3.88 → 0.3.90

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.
@@ -0,0 +1,125 @@
1
+ /**
2
+ * feature-adr per-stage model routing — the pure resolution core.
3
+ *
4
+ * This is the TESTABLE mirror of the routing block inlined into the
5
+ * `.claude/workflows/feature-adr.js` workflow (and its byte-identical
6
+ * skills-feature-adr template copy). The workflow is a top-level-`await`
7
+ * SCRIPT, not an importable module — the pipeline runs on import — so the
8
+ * pure helpers cannot be `import`-ed from it directly. Instead the workflow
9
+ * INLINES a byte-equivalent copy of the function bodies below, and
10
+ * `feature-adr-model-routing.test.ts` asserts the inline copy is
11
+ * string-equivalent to this module (a drift guard tying the tested code to
12
+ * the shipped code), then exercises these exports for the load-bearing
13
+ * behavioral assertions (LB-A/B/C, AC-1…AC-6).
14
+ *
15
+ * The load-bearing property: a model that WRITES code must not also SELF-QE.
16
+ * When `args.models.qe` is unset, the QE stage is auto-routed to the OTHER
17
+ * family than the resolved coder (codex-coder → Claude `opus`; Claude-coder →
18
+ * `codex:<top>:high`, or `opus` if codex is unavailable — never a block).
19
+ *
20
+ * DESIGN CONSTRAINT — the Workflow parser is STRICTER than `node --check`
21
+ * (no nested template literals, no inline `cond ? agent() : null` in arrays).
22
+ * The function BODIES here are written parser-safe (string `+` concat, explicit
23
+ * `if`/return, object-literal data tables) so the same source can be inlined
24
+ * verbatim into the workflow. Keep this module and the workflow's inline block
25
+ * in lock-step.
26
+ *
27
+ * @packageDocumentation
28
+ */
29
+ /** A resolved `agent()` opts fragment: either a Claude `{model}` or a codex spec. */
30
+ export interface StageOpts {
31
+ readonly model?: string;
32
+ readonly agentType?: string;
33
+ readonly codexModel?: string;
34
+ readonly _reasoning?: string;
35
+ }
36
+ /** The knobs `resolveStageModel` closes over — passed in from the workflow. */
37
+ export interface RoutingEnv {
38
+ /** `args.models` — the per-stage override map (may be empty). */
39
+ readonly MODELS: Record<string, string | null | undefined>;
40
+ /** `args.codexModel` default id (default `'auto'`). */
41
+ readonly CODEX_MODEL: string;
42
+ /** Resolved legacy coder knob: `'claude' | 'codex' | 'codex-fallback'`. */
43
+ readonly CODER: string;
44
+ /** Resolved legacy qeReviewer knob: `'claude' | 'codex' | 'codex-fallback'`. */
45
+ readonly QE_REVIEWER: string;
46
+ /** `args.planner` shortcut (only `'codex'` is meaningful). */
47
+ readonly PLANNER?: string;
48
+ /**
49
+ * Whether codex is available at qe-resolution time. Defaults true; the caller
50
+ * passes `false` (from a pre-flight probe / `A.codexAvailable===false`) to force
51
+ * the cross-model QE default to fall back to a Claude reviewer instead of codex.
52
+ */
53
+ readonly codexAvailable?: boolean;
54
+ /** Optional log sink (the workflow passes its `log`); defaults to a no-op. */
55
+ readonly log?: (msg: string) => void;
56
+ }
57
+ /** Known codex ids. Adding a new id (e.g. `'gpt-5.7'`) is a DATA-ONLY change. */
58
+ export declare const KNOWN_CODEX: Record<string, number>;
59
+ /** The Claude model names the Workflow runtime accepts as `agent()` `model`. */
60
+ export declare const CLAUDE_NAMES: Record<string, number>;
61
+ /**
62
+ * The proven DEFAULT TABLE, applied only when the user opts into routing.
63
+ * `code`/`qe` are `null` SENTINELS: their defaults are DERIVED (the coder knob /
64
+ * the cross-model rule), not fixed model names.
65
+ */
66
+ export declare const DEFAULT_MODELS: Record<string, string | null>;
67
+ /**
68
+ * Turn a compact model SPEC into `agent()` opts.
69
+ * - falsy → `{}` (session-inherited — the BC path)
70
+ * - `'codex[:id[:r]]'` → `{agentType:'codex:codex-rescue', codexModel, _reasoning}`
71
+ * - `'fable'|'opus'|…` → `{model}`
72
+ * - unknown → warn + `{}` (Claude) / `CODEX_MODEL` (codex id)
73
+ */
74
+ export declare function specToOpts(spec: string | null | undefined, env: RoutingEnv): StageOpts;
75
+ /**
76
+ * Fold the legacy `coder` knob into a spec:
77
+ * `codex`/`codex-fallback` → `'codex:' + CODEX_MODEL + ':high'`; else `'opus'`.
78
+ * NOTE: a DIRECT `MODELS.code` spec bypasses this (handled in `resolveStageModel`);
79
+ * this only maps the KNOB, which is why `coderIsCodex` (below) also inspects `MODELS.code`.
80
+ */
81
+ export declare function resolveCoderSpec(env: RoutingEnv): string;
82
+ /**
83
+ * Whether the RESOLVED coder is the codex family — true when the coder knob is
84
+ * codex/codex-fallback OR a direct `MODELS.code` spec is a codex spec. The
85
+ * cross-model QE default derives from THIS (not the knob alone), so a direct
86
+ * `MODELS.code='codex'` still routes QE to Claude (never codex-self-QE).
87
+ */
88
+ export declare function coderIsCodex(env: RoutingEnv): boolean;
89
+ /**
90
+ * The CROSS-MODEL QE default (load-bearing). Called only when `MODELS.qe` is
91
+ * unset. Resolves to the OTHER family than the coder:
92
+ * - coder is codex → `'opus'` (Claude reviews codex's code)
93
+ * - coder is Claude → codex-available ? `'codex:<top>:high'` : `'opus'` (never block)
94
+ * `<top>` = `CODEX_MODEL` when pinned (≠'auto'), else the top `KNOWN_CODEX` id.
95
+ */
96
+ export declare function resolveQeSpec(env: RoutingEnv): string;
97
+ /**
98
+ * Whether the caller opted into routing at all. When FALSE (no `args.models`,
99
+ * no codex knobs), every Claude stage resolves to `{}` → byte-identical to today.
100
+ */
101
+ export declare function routingRequested(env: RoutingEnv): boolean;
102
+ /**
103
+ * Whether the Step-8 QE reviewer should be CODEX. This is the load-bearing cross-model gate — it must
104
+ * NEVER let the model that wrote the code also self-QE. Order:
105
+ * 1. an explicit `MODELS.qe` spec wins outright (user opt-in — even a codex qe against a codex coder).
106
+ * 2. else the legacy `QE_REVIEWER==='codex'` knob asks for codex, but is HONORED ONLY when the coder is
107
+ * NOT codex — a codex coder + `qeReviewer:'codex'` would be codex-self-QE (the anti-pattern this whole
108
+ * feature exists to prevent), so cross-model wins and QE stays Claude.
109
+ * 3. else fall to the cross-model DEFAULT (`resolveQeSpec`): codex iff the coder is Claude & codex is
110
+ * available & routing was opted into. No routing → false → today's Claude QE (byte-identical BC).
111
+ * NOTE: the previous inline gate re-added `QE_REVIEWER==='codex'` AFTER the safe resolver, so a codex
112
+ * coder with the legacy knob silently self-QE'd. This function is the single tested source of that truth.
113
+ */
114
+ export declare function qeShouldUseCodex(env: RoutingEnv): boolean;
115
+ /**
116
+ * Resolve a stage to its `agent()` opts fragment.
117
+ * 1. explicit `MODELS[stage]` wins
118
+ * 2. else if the user did NOT opt into routing → `{}` (byte-identical BC path)
119
+ * 3. else the DEFAULT TABLE fills the gap
120
+ * 4. `code`/`qe` `null` sentinels resolve via the coder / cross-model rules
121
+ */
122
+ export declare function resolveStageModel(stage: string, env: RoutingEnv): StageOpts;
123
+ /** Spread-merge a resolved opts fragment onto a call's base opts (extra wins). */
124
+ export declare function mergeOpts<B extends object, E extends object>(base: B, extra: E): B & E;
125
+ //# sourceMappingURL=feature-adr-routing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-adr-routing.d.ts","sourceRoot":"","sources":["../src/feature-adr-routing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,qFAAqF;AACrF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,+EAA+E;AAC/E,MAAM,WAAW,UAAU;IACzB,iEAAiE;IACjE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAC3D,uDAAuD;IACvD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,gFAAgF;IAChF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,8EAA8E;IAC9E,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAID,iFAAiF;AACjF,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAA2C,CAAC;AAE3F,gFAAgF;AAChF,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAA8C,CAAC;AAE/F;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAYxD,CAAC;AAIF;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG,EAAE,UAAU,GAAG,SAAS,CAiBtF;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAGxD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAKrD;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAYrD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CASzD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAOzD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,SAAS,CAS3E;AAED,kFAAkF;AAClF,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAKtF"}
@@ -0,0 +1,190 @@
1
+ /**
2
+ * feature-adr per-stage model routing — the pure resolution core.
3
+ *
4
+ * This is the TESTABLE mirror of the routing block inlined into the
5
+ * `.claude/workflows/feature-adr.js` workflow (and its byte-identical
6
+ * skills-feature-adr template copy). The workflow is a top-level-`await`
7
+ * SCRIPT, not an importable module — the pipeline runs on import — so the
8
+ * pure helpers cannot be `import`-ed from it directly. Instead the workflow
9
+ * INLINES a byte-equivalent copy of the function bodies below, and
10
+ * `feature-adr-model-routing.test.ts` asserts the inline copy is
11
+ * string-equivalent to this module (a drift guard tying the tested code to
12
+ * the shipped code), then exercises these exports for the load-bearing
13
+ * behavioral assertions (LB-A/B/C, AC-1…AC-6).
14
+ *
15
+ * The load-bearing property: a model that WRITES code must not also SELF-QE.
16
+ * When `args.models.qe` is unset, the QE stage is auto-routed to the OTHER
17
+ * family than the resolved coder (codex-coder → Claude `opus`; Claude-coder →
18
+ * `codex:<top>:high`, or `opus` if codex is unavailable — never a block).
19
+ *
20
+ * DESIGN CONSTRAINT — the Workflow parser is STRICTER than `node --check`
21
+ * (no nested template literals, no inline `cond ? agent() : null` in arrays).
22
+ * The function BODIES here are written parser-safe (string `+` concat, explicit
23
+ * `if`/return, object-literal data tables) so the same source can be inlined
24
+ * verbatim into the workflow. Keep this module and the workflow's inline block
25
+ * in lock-step.
26
+ *
27
+ * @packageDocumentation
28
+ */
29
+ // ── Data tables (data-only extensibility — gpt-5.6-ready) ───────────────────
30
+ /** Known codex ids. Adding a new id (e.g. `'gpt-5.7'`) is a DATA-ONLY change. */
31
+ export const KNOWN_CODEX = { auto: 1, 'gpt-5.5': 1, 'gpt-5.6': 1 };
32
+ /** The Claude model names the Workflow runtime accepts as `agent()` `model`. */
33
+ export const CLAUDE_NAMES = { fable: 1, opus: 1, sonnet: 1, haiku: 1 };
34
+ /**
35
+ * The proven DEFAULT TABLE, applied only when the user opts into routing.
36
+ * `code`/`qe` are `null` SENTINELS: their defaults are DERIVED (the coder knob /
37
+ * the cross-model rule), not fixed model names.
38
+ */
39
+ export const DEFAULT_MODELS = {
40
+ router: 'fable',
41
+ requirements: 'sonnet',
42
+ research: 'sonnet',
43
+ adr: 'opus',
44
+ ideation: 'sonnet',
45
+ ddd: 'opus',
46
+ architecture: 'opus',
47
+ plan: 'sonnet',
48
+ code: null,
49
+ qe: null,
50
+ fleet: 'sonnet',
51
+ };
52
+ // ── Pure resolvers (byte-equivalent to the workflow's inline block) ──────────
53
+ /**
54
+ * Turn a compact model SPEC into `agent()` opts.
55
+ * - falsy → `{}` (session-inherited — the BC path)
56
+ * - `'codex[:id[:r]]'` → `{agentType:'codex:codex-rescue', codexModel, _reasoning}`
57
+ * - `'fable'|'opus'|…` → `{model}`
58
+ * - unknown → warn + `{}` (Claude) / `CODEX_MODEL` (codex id)
59
+ */
60
+ export function specToOpts(spec, env) {
61
+ const log = env.log || function () { };
62
+ if (!spec)
63
+ return {};
64
+ const parts = String(spec).split(':');
65
+ const head = parts[0] || '';
66
+ if (head === 'codex') {
67
+ let id = parts[1] || env.CODEX_MODEL;
68
+ if (id !== 'auto' && !KNOWN_CODEX[id]) {
69
+ log('models: unknown codex id ' + id + ' — using ' + env.CODEX_MODEL);
70
+ id = env.CODEX_MODEL;
71
+ }
72
+ const reasoning = parts[2] || 'high';
73
+ return { agentType: 'codex:codex-rescue', codexModel: id, _reasoning: reasoning };
74
+ }
75
+ if (CLAUDE_NAMES[head])
76
+ return { model: head };
77
+ log('models: unknown spec ' + spec + ' — session-inherited');
78
+ return {};
79
+ }
80
+ /**
81
+ * Fold the legacy `coder` knob into a spec:
82
+ * `codex`/`codex-fallback` → `'codex:' + CODEX_MODEL + ':high'`; else `'opus'`.
83
+ * NOTE: a DIRECT `MODELS.code` spec bypasses this (handled in `resolveStageModel`);
84
+ * this only maps the KNOB, which is why `coderIsCodex` (below) also inspects `MODELS.code`.
85
+ */
86
+ export function resolveCoderSpec(env) {
87
+ if (env.CODER === 'codex' || env.CODER === 'codex-fallback')
88
+ return 'codex:' + env.CODEX_MODEL + ':high';
89
+ return 'opus';
90
+ }
91
+ /**
92
+ * Whether the RESOLVED coder is the codex family — true when the coder knob is
93
+ * codex/codex-fallback OR a direct `MODELS.code` spec is a codex spec. The
94
+ * cross-model QE default derives from THIS (not the knob alone), so a direct
95
+ * `MODELS.code='codex'` still routes QE to Claude (never codex-self-QE).
96
+ */
97
+ export function coderIsCodex(env) {
98
+ if (env.CODER === 'codex' || env.CODER === 'codex-fallback')
99
+ return true;
100
+ const codeSpec = env.MODELS.code;
101
+ if (codeSpec && String(codeSpec).split(':')[0] === 'codex')
102
+ return true;
103
+ return false;
104
+ }
105
+ /**
106
+ * The CROSS-MODEL QE default (load-bearing). Called only when `MODELS.qe` is
107
+ * unset. Resolves to the OTHER family than the coder:
108
+ * - coder is codex → `'opus'` (Claude reviews codex's code)
109
+ * - coder is Claude → codex-available ? `'codex:<top>:high'` : `'opus'` (never block)
110
+ * `<top>` = `CODEX_MODEL` when pinned (≠'auto'), else the top `KNOWN_CODEX` id.
111
+ */
112
+ export function resolveQeSpec(env) {
113
+ if (coderIsCodex(env))
114
+ return 'opus';
115
+ const CODEX_AVAILABLE = env.codexAvailable !== false;
116
+ if (!CODEX_AVAILABLE)
117
+ return 'opus';
118
+ let top = env.CODEX_MODEL;
119
+ if (top === 'auto') {
120
+ const ids = Object.keys(KNOWN_CODEX);
121
+ for (let i = 0; i < ids.length; i++) {
122
+ if (ids[i] !== 'auto')
123
+ top = ids[i] || top;
124
+ }
125
+ }
126
+ return 'codex:' + top + ':high';
127
+ }
128
+ /**
129
+ * Whether the caller opted into routing at all. When FALSE (no `args.models`,
130
+ * no codex knobs), every Claude stage resolves to `{}` → byte-identical to today.
131
+ */
132
+ export function routingRequested(env) {
133
+ return (Object.keys(env.MODELS).length > 0 ||
134
+ env.PLANNER === 'codex' ||
135
+ env.CODER === 'codex' ||
136
+ env.CODER === 'codex-fallback' ||
137
+ env.QE_REVIEWER === 'codex' ||
138
+ env.QE_REVIEWER === 'codex-fallback');
139
+ }
140
+ /**
141
+ * Whether the Step-8 QE reviewer should be CODEX. This is the load-bearing cross-model gate — it must
142
+ * NEVER let the model that wrote the code also self-QE. Order:
143
+ * 1. an explicit `MODELS.qe` spec wins outright (user opt-in — even a codex qe against a codex coder).
144
+ * 2. else the legacy `QE_REVIEWER==='codex'` knob asks for codex, but is HONORED ONLY when the coder is
145
+ * NOT codex — a codex coder + `qeReviewer:'codex'` would be codex-self-QE (the anti-pattern this whole
146
+ * feature exists to prevent), so cross-model wins and QE stays Claude.
147
+ * 3. else fall to the cross-model DEFAULT (`resolveQeSpec`): codex iff the coder is Claude & codex is
148
+ * available & routing was opted into. No routing → false → today's Claude QE (byte-identical BC).
149
+ * NOTE: the previous inline gate re-added `QE_REVIEWER==='codex'` AFTER the safe resolver, so a codex
150
+ * coder with the legacy knob silently self-QE'd. This function is the single tested source of that truth.
151
+ */
152
+ export function qeShouldUseCodex(env) {
153
+ const explicit = env.MODELS.qe;
154
+ if (explicit !== undefined && explicit !== null) {
155
+ return String(explicit).split(':')[0] === 'codex';
156
+ }
157
+ if (env.QE_REVIEWER === 'codex')
158
+ return !coderIsCodex(env);
159
+ return routingRequested(env) && resolveQeSpec(env).split(':')[0] === 'codex';
160
+ }
161
+ /**
162
+ * Resolve a stage to its `agent()` opts fragment.
163
+ * 1. explicit `MODELS[stage]` wins
164
+ * 2. else if the user did NOT opt into routing → `{}` (byte-identical BC path)
165
+ * 3. else the DEFAULT TABLE fills the gap
166
+ * 4. `code`/`qe` `null` sentinels resolve via the coder / cross-model rules
167
+ */
168
+ export function resolveStageModel(stage, env) {
169
+ let spec = env.MODELS[stage];
170
+ if (spec === undefined) {
171
+ if (!routingRequested(env))
172
+ return {};
173
+ spec = DEFAULT_MODELS[stage];
174
+ }
175
+ if (stage === 'code' && (spec === null || spec === undefined))
176
+ return specToOpts(resolveCoderSpec(env), env);
177
+ if (stage === 'qe' && (spec === null || spec === undefined))
178
+ return specToOpts(resolveQeSpec(env), env);
179
+ return specToOpts(spec, env);
180
+ }
181
+ /** Spread-merge a resolved opts fragment onto a call's base opts (extra wins). */
182
+ export function mergeOpts(base, extra) {
183
+ const out = {};
184
+ for (const k in base)
185
+ out[k] = base[k];
186
+ for (const k in extra)
187
+ out[k] = extra[k];
188
+ return out;
189
+ }
190
+ //# sourceMappingURL=feature-adr-routing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-adr-routing.js","sourceRoot":"","sources":["../src/feature-adr-routing.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -63,4 +63,6 @@ export type { ReconcileReport, ReconcileFinding, ReconcileAxis, AxisState, Limit
63
63
  export type { McpFinding, McpScanReport, McpVerdict, McpSeverity, McpCapability, } from './mcp-scan.js';
64
64
  export type { RegistryEntry, Registry } from './registry.js';
65
65
  export type { BenchmarkCheck, BenchmarkScore, BenchmarkReport, CompareResult } from './benchmark.js';
66
+ export { specToOpts, resolveStageModel, resolveCoderSpec, coderIsCodex, resolveQeSpec, routingRequested, mergeOpts, DEFAULT_MODELS, KNOWN_CODEX, CLAUDE_NAMES, } from './feature-adr-routing.js';
67
+ export type { StageOpts, RoutingEnv } from './feature-adr-routing.js';
66
68
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -37,4 +37,5 @@ export { importEcc } from './import-ecc.js';
37
37
  export { scanMcp, parseGrant } from './mcp-scan.js';
38
38
  export { detectScriptCapabilities, parseDeclaredCapabilities, parseDeclaredLimits, stripCodeNoise, toolKind, } from './capability-vocab.js';
39
39
  export { reconcileCapabilities, RECONCILE_BANNER } from './reconcile.js';
40
+ export { specToOpts, resolveStageModel, resolveCoderSpec, coderIsCodex, resolveQeSpec, routingRequested, mergeOpts, DEFAULT_MODELS, KNOWN_CODEX, CLAUDE_NAMES, } from './feature-adr-routing.js';
40
41
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dzhechkov/harness-core",
3
- "version": "0.3.88",
3
+ "version": "0.3.90",
4
4
  "description": "Shared harness logic - skill loading, additive apply, and the init/sync/verify/doctor operations.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -30,13 +30,13 @@
30
30
  "@dzhechkov/adapter-openclaude": "^0.1.0",
31
31
  "@dzhechkov/adapter-opencode": "^0.2.0",
32
32
  "yaml": "^2.0.0",
33
+ "@dzhechkov/adapter-gemini": "0.1.1",
34
+ "@dzhechkov/core": "0.2.14",
33
35
  "@dzhechkov/adapter-copilot": "0.1.1",
34
36
  "@dzhechkov/adapter-cursor": "0.1.1",
35
37
  "@dzhechkov/adapter-windsurf": "0.1.1",
36
- "@dzhechkov/adapter-gemini": "0.1.1",
37
- "@dzhechkov/adapter-agents-md": "0.1.1",
38
38
  "@dzhechkov/memory": "0.2.9",
39
- "@dzhechkov/core": "0.2.14"
39
+ "@dzhechkov/adapter-agents-md": "0.1.1"
40
40
  },
41
41
  "peerDependenciesMeta": {
42
42
  "@ruvector/rvf": {
@@ -0,0 +1,220 @@
1
+ /**
2
+ * feature-adr per-stage model routing — the pure resolution core.
3
+ *
4
+ * This is the TESTABLE mirror of the routing block inlined into the
5
+ * `.claude/workflows/feature-adr.js` workflow (and its byte-identical
6
+ * skills-feature-adr template copy). The workflow is a top-level-`await`
7
+ * SCRIPT, not an importable module — the pipeline runs on import — so the
8
+ * pure helpers cannot be `import`-ed from it directly. Instead the workflow
9
+ * INLINES a byte-equivalent copy of the function bodies below, and
10
+ * `feature-adr-model-routing.test.ts` asserts the inline copy is
11
+ * string-equivalent to this module (a drift guard tying the tested code to
12
+ * the shipped code), then exercises these exports for the load-bearing
13
+ * behavioral assertions (LB-A/B/C, AC-1…AC-6).
14
+ *
15
+ * The load-bearing property: a model that WRITES code must not also SELF-QE.
16
+ * When `args.models.qe` is unset, the QE stage is auto-routed to the OTHER
17
+ * family than the resolved coder (codex-coder → Claude `opus`; Claude-coder →
18
+ * `codex:<top>:high`, or `opus` if codex is unavailable — never a block).
19
+ *
20
+ * DESIGN CONSTRAINT — the Workflow parser is STRICTER than `node --check`
21
+ * (no nested template literals, no inline `cond ? agent() : null` in arrays).
22
+ * The function BODIES here are written parser-safe (string `+` concat, explicit
23
+ * `if`/return, object-literal data tables) so the same source can be inlined
24
+ * verbatim into the workflow. Keep this module and the workflow's inline block
25
+ * in lock-step.
26
+ *
27
+ * @packageDocumentation
28
+ */
29
+
30
+ /** A resolved `agent()` opts fragment: either a Claude `{model}` or a codex spec. */
31
+ export interface StageOpts {
32
+ readonly model?: string;
33
+ readonly agentType?: string;
34
+ readonly codexModel?: string;
35
+ readonly _reasoning?: string;
36
+ }
37
+
38
+ /** The knobs `resolveStageModel` closes over — passed in from the workflow. */
39
+ export interface RoutingEnv {
40
+ /** `args.models` — the per-stage override map (may be empty). */
41
+ readonly MODELS: Record<string, string | null | undefined>;
42
+ /** `args.codexModel` default id (default `'auto'`). */
43
+ readonly CODEX_MODEL: string;
44
+ /** Resolved legacy coder knob: `'claude' | 'codex' | 'codex-fallback'`. */
45
+ readonly CODER: string;
46
+ /** Resolved legacy qeReviewer knob: `'claude' | 'codex' | 'codex-fallback'`. */
47
+ readonly QE_REVIEWER: string;
48
+ /** `args.planner` shortcut (only `'codex'` is meaningful). */
49
+ readonly PLANNER?: string;
50
+ /**
51
+ * Whether codex is available at qe-resolution time. Defaults true; the caller
52
+ * passes `false` (from a pre-flight probe / `A.codexAvailable===false`) to force
53
+ * the cross-model QE default to fall back to a Claude reviewer instead of codex.
54
+ */
55
+ readonly codexAvailable?: boolean;
56
+ /** Optional log sink (the workflow passes its `log`); defaults to a no-op. */
57
+ readonly log?: (msg: string) => void;
58
+ }
59
+
60
+ // ── Data tables (data-only extensibility — gpt-5.6-ready) ───────────────────
61
+
62
+ /** Known codex ids. Adding a new id (e.g. `'gpt-5.7'`) is a DATA-ONLY change. */
63
+ export const KNOWN_CODEX: Record<string, number> = { auto: 1, 'gpt-5.5': 1, 'gpt-5.6': 1 };
64
+
65
+ /** The Claude model names the Workflow runtime accepts as `agent()` `model`. */
66
+ export const CLAUDE_NAMES: Record<string, number> = { fable: 1, opus: 1, sonnet: 1, haiku: 1 };
67
+
68
+ /**
69
+ * The proven DEFAULT TABLE, applied only when the user opts into routing.
70
+ * `code`/`qe` are `null` SENTINELS: their defaults are DERIVED (the coder knob /
71
+ * the cross-model rule), not fixed model names.
72
+ */
73
+ export const DEFAULT_MODELS: Record<string, string | null> = {
74
+ router: 'fable',
75
+ requirements: 'sonnet',
76
+ research: 'sonnet',
77
+ adr: 'opus',
78
+ ideation: 'sonnet',
79
+ ddd: 'opus',
80
+ architecture: 'opus',
81
+ plan: 'sonnet',
82
+ code: null,
83
+ qe: null,
84
+ fleet: 'sonnet',
85
+ };
86
+
87
+ // ── Pure resolvers (byte-equivalent to the workflow's inline block) ──────────
88
+
89
+ /**
90
+ * Turn a compact model SPEC into `agent()` opts.
91
+ * - falsy → `{}` (session-inherited — the BC path)
92
+ * - `'codex[:id[:r]]'` → `{agentType:'codex:codex-rescue', codexModel, _reasoning}`
93
+ * - `'fable'|'opus'|…` → `{model}`
94
+ * - unknown → warn + `{}` (Claude) / `CODEX_MODEL` (codex id)
95
+ */
96
+ export function specToOpts(spec: string | null | undefined, env: RoutingEnv): StageOpts {
97
+ const log = env.log || function () {};
98
+ if (!spec) return {};
99
+ const parts = String(spec).split(':');
100
+ const head = parts[0] || '';
101
+ if (head === 'codex') {
102
+ let id = parts[1] || env.CODEX_MODEL;
103
+ if (id !== 'auto' && !KNOWN_CODEX[id]) {
104
+ log('models: unknown codex id ' + id + ' — using ' + env.CODEX_MODEL);
105
+ id = env.CODEX_MODEL;
106
+ }
107
+ const reasoning = parts[2] || 'high';
108
+ return { agentType: 'codex:codex-rescue', codexModel: id, _reasoning: reasoning };
109
+ }
110
+ if (CLAUDE_NAMES[head]) return { model: head };
111
+ log('models: unknown spec ' + spec + ' — session-inherited');
112
+ return {};
113
+ }
114
+
115
+ /**
116
+ * Fold the legacy `coder` knob into a spec:
117
+ * `codex`/`codex-fallback` → `'codex:' + CODEX_MODEL + ':high'`; else `'opus'`.
118
+ * NOTE: a DIRECT `MODELS.code` spec bypasses this (handled in `resolveStageModel`);
119
+ * this only maps the KNOB, which is why `coderIsCodex` (below) also inspects `MODELS.code`.
120
+ */
121
+ export function resolveCoderSpec(env: RoutingEnv): string {
122
+ if (env.CODER === 'codex' || env.CODER === 'codex-fallback') return 'codex:' + env.CODEX_MODEL + ':high';
123
+ return 'opus';
124
+ }
125
+
126
+ /**
127
+ * Whether the RESOLVED coder is the codex family — true when the coder knob is
128
+ * codex/codex-fallback OR a direct `MODELS.code` spec is a codex spec. The
129
+ * cross-model QE default derives from THIS (not the knob alone), so a direct
130
+ * `MODELS.code='codex'` still routes QE to Claude (never codex-self-QE).
131
+ */
132
+ export function coderIsCodex(env: RoutingEnv): boolean {
133
+ if (env.CODER === 'codex' || env.CODER === 'codex-fallback') return true;
134
+ const codeSpec = env.MODELS.code;
135
+ if (codeSpec && String(codeSpec).split(':')[0] === 'codex') return true;
136
+ return false;
137
+ }
138
+
139
+ /**
140
+ * The CROSS-MODEL QE default (load-bearing). Called only when `MODELS.qe` is
141
+ * unset. Resolves to the OTHER family than the coder:
142
+ * - coder is codex → `'opus'` (Claude reviews codex's code)
143
+ * - coder is Claude → codex-available ? `'codex:<top>:high'` : `'opus'` (never block)
144
+ * `<top>` = `CODEX_MODEL` when pinned (≠'auto'), else the top `KNOWN_CODEX` id.
145
+ */
146
+ export function resolveQeSpec(env: RoutingEnv): string {
147
+ if (coderIsCodex(env)) return 'opus';
148
+ const CODEX_AVAILABLE = env.codexAvailable !== false;
149
+ if (!CODEX_AVAILABLE) return 'opus';
150
+ let top = env.CODEX_MODEL;
151
+ if (top === 'auto') {
152
+ const ids = Object.keys(KNOWN_CODEX);
153
+ for (let i = 0; i < ids.length; i++) {
154
+ if (ids[i] !== 'auto') top = ids[i] || top;
155
+ }
156
+ }
157
+ return 'codex:' + top + ':high';
158
+ }
159
+
160
+ /**
161
+ * Whether the caller opted into routing at all. When FALSE (no `args.models`,
162
+ * no codex knobs), every Claude stage resolves to `{}` → byte-identical to today.
163
+ */
164
+ export function routingRequested(env: RoutingEnv): boolean {
165
+ return (
166
+ Object.keys(env.MODELS).length > 0 ||
167
+ env.PLANNER === 'codex' ||
168
+ env.CODER === 'codex' ||
169
+ env.CODER === 'codex-fallback' ||
170
+ env.QE_REVIEWER === 'codex' ||
171
+ env.QE_REVIEWER === 'codex-fallback'
172
+ );
173
+ }
174
+
175
+ /**
176
+ * Whether the Step-8 QE reviewer should be CODEX. This is the load-bearing cross-model gate — it must
177
+ * NEVER let the model that wrote the code also self-QE. Order:
178
+ * 1. an explicit `MODELS.qe` spec wins outright (user opt-in — even a codex qe against a codex coder).
179
+ * 2. else the legacy `QE_REVIEWER==='codex'` knob asks for codex, but is HONORED ONLY when the coder is
180
+ * NOT codex — a codex coder + `qeReviewer:'codex'` would be codex-self-QE (the anti-pattern this whole
181
+ * feature exists to prevent), so cross-model wins and QE stays Claude.
182
+ * 3. else fall to the cross-model DEFAULT (`resolveQeSpec`): codex iff the coder is Claude & codex is
183
+ * available & routing was opted into. No routing → false → today's Claude QE (byte-identical BC).
184
+ * NOTE: the previous inline gate re-added `QE_REVIEWER==='codex'` AFTER the safe resolver, so a codex
185
+ * coder with the legacy knob silently self-QE'd. This function is the single tested source of that truth.
186
+ */
187
+ export function qeShouldUseCodex(env: RoutingEnv): boolean {
188
+ const explicit = env.MODELS.qe;
189
+ if (explicit !== undefined && explicit !== null) {
190
+ return String(explicit).split(':')[0] === 'codex';
191
+ }
192
+ if (env.QE_REVIEWER === 'codex') return !coderIsCodex(env);
193
+ return routingRequested(env) && resolveQeSpec(env).split(':')[0] === 'codex';
194
+ }
195
+
196
+ /**
197
+ * Resolve a stage to its `agent()` opts fragment.
198
+ * 1. explicit `MODELS[stage]` wins
199
+ * 2. else if the user did NOT opt into routing → `{}` (byte-identical BC path)
200
+ * 3. else the DEFAULT TABLE fills the gap
201
+ * 4. `code`/`qe` `null` sentinels resolve via the coder / cross-model rules
202
+ */
203
+ export function resolveStageModel(stage: string, env: RoutingEnv): StageOpts {
204
+ let spec = env.MODELS[stage];
205
+ if (spec === undefined) {
206
+ if (!routingRequested(env)) return {};
207
+ spec = DEFAULT_MODELS[stage];
208
+ }
209
+ if (stage === 'code' && (spec === null || spec === undefined)) return specToOpts(resolveCoderSpec(env), env);
210
+ if (stage === 'qe' && (spec === null || spec === undefined)) return specToOpts(resolveQeSpec(env), env);
211
+ return specToOpts(spec, env);
212
+ }
213
+
214
+ /** Spread-merge a resolved opts fragment onto a call's base opts (extra wins). */
215
+ export function mergeOpts<B extends object, E extends object>(base: B, extra: E): B & E {
216
+ const out: Record<string, unknown> = {};
217
+ for (const k in base) out[k] = (base as Record<string, unknown>)[k];
218
+ for (const k in extra) out[k] = (extra as Record<string, unknown>)[k];
219
+ return out as B & E;
220
+ }
package/src/index.ts CHANGED
@@ -167,3 +167,16 @@ export type {
167
167
  } from './mcp-scan.js';
168
168
  export type { RegistryEntry, Registry } from './registry.js';
169
169
  export type { BenchmarkCheck, BenchmarkScore, BenchmarkReport, CompareResult } from './benchmark.js';
170
+ export {
171
+ specToOpts,
172
+ resolveStageModel,
173
+ resolveCoderSpec,
174
+ coderIsCodex,
175
+ resolveQeSpec,
176
+ routingRequested,
177
+ mergeOpts,
178
+ DEFAULT_MODELS,
179
+ KNOWN_CODEX,
180
+ CLAUDE_NAMES,
181
+ } from './feature-adr-routing.js';
182
+ export type { StageOpts, RoutingEnv } from './feature-adr-routing.js';