harness-everything 0.27.0 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +33 -0
- package/behavioral-evals/README.md +39 -0
- package/behavioral-evals/case-validator.js +34 -0
- package/behavioral-evals/cases/baseline-worktree-submodule-reachability.yaml +30 -0
- package/behavioral-evals/fixtures/setup/fail.js +3 -0
- package/behavioral-evals/fixtures/setup/noop.js +4 -0
- package/behavioral-evals/fixtures/setup/verify-worktree-submodule.js +46 -0
- package/behavioral-evals/fixtures/setup/worktree-submodule.js +86 -0
- package/behavioral-evals/paired-benchmark.js +39 -5
- package/behavioral-evals/run-with-plugin.js +53 -39
- package/behavioral-evals/run.js +88 -9
- package/benchmarks/fixtures/system-one-holdout-reviews.json +18 -18
- package/benchmarks/fixtures/system-one-holdout.json +9 -9
- package/benchmarks/results/system-one/harness-routing-v1-cpu-2026-09-24/README.md +75 -0
- package/benchmarks/results/system-one/harness-routing-v1-cpu-2026-09-24/report.json +10832 -0
- package/benchmarks/results/system-one/harness-routing-v1-ngram-2026-09-24/README.md +72 -0
- package/benchmarks/results/system-one/harness-routing-v1-ngram-2026-09-24/report.json +10817 -0
- package/benchmarks/results/system-one/harness-routing-v3-ngram-2026-09-24/README.md +63 -0
- package/benchmarks/results/system-one/harness-routing-v3-ngram-2026-09-24/report.json +10817 -0
- package/benchmarks/results/system-one/labeler-holdout-check-2026-09-24/report.json +1104 -0
- package/benchmarks/results/system-one/labeler-holdout-check-codex-2026-09-24/report.json +1104 -0
- package/benchmarks/results/system-one/labeler-holdout-check-codex-tier3-2026-09-24/report.json +1104 -0
- package/ci/mechanism-2j-behavioral-runner.test.js +121 -1
- package/ci/mechanism-2j-fixture-entrypoints.test.js +153 -0
- package/ci/mechanism-system-one-evaluation.test.js +17 -0
- package/ci/mechanism-system-one-label.test.js +27 -0
- package/ci/mechanism-system-one-ngram.test.js +161 -0
- package/ci/mechanism-system-one-train.test.js +12 -0
- package/ci/system-one-ngram-parity.py +19 -0
- package/ci/system-one-train-test.py +6 -0
- package/ci/test-behavioral-case-validation.js +26 -0
- package/docs/system-one-corpus.md +31 -3
- package/docs/system-one-routing.md +84 -2
- package/docs/system-one-training.md +14 -2
- package/harness-everything/SKILL.md +1 -1
- package/harness-everything/scripts/system-one/evaluate.js +3 -2
- package/harness-everything/scripts/system-one/ngram.js +84 -0
- package/harness-everything/scripts/system-one/provider.js +15 -5
- package/opencode-plugin/plugin.json +1 -1
- package/package.json +1 -1
- package/plugins/harness-everything/.codex-plugin/plugin.json +1 -1
- package/plugins/harness-everything/plugin.json +1 -1
- package/plugins/harness-everything/skills/harness-everything/SKILL.md +1 -1
- package/plugins/harness-everything/skills/harness-everything/scripts/system-one/evaluate.js +3 -2
- package/plugins/harness-everything/skills/harness-everything/scripts/system-one/ngram.js +84 -0
- package/plugins/harness-everything/skills/harness-everything/scripts/system-one/provider.js +15 -5
- package/sbom.cdx.json +7 -7
- package/scripts/evaluate-system-one.js +16 -9
- package/scripts/system-one-calibrate.js +1 -1
- package/scripts/system-one-label.js +32 -3
- package/scripts/system-one-train-ngram.py +129 -0
- package/scripts/system-one-train.py +14 -1
|
@@ -2,7 +2,8 @@ const helper = require('./test-helper');
|
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const os = require('os');
|
|
4
4
|
const path = require('path');
|
|
5
|
-
const {
|
|
5
|
+
const { spawnSync } = require('child_process');
|
|
6
|
+
const { buildEngineInvocation, buildWorkspace, runFixtureSetup, prepareWorkspace, summarizePairResults } = require('../behavioral-evals/run');
|
|
6
7
|
|
|
7
8
|
console.log('\n[2j] Behavioral runner argv integrity...');
|
|
8
9
|
const prompt = "Add punctuation stripping to slug.js, then run npm test. Do not truncate this request.";
|
|
@@ -59,4 +60,123 @@ helper.check(
|
|
|
59
60
|
traversalError && traversalError.stack ? traversalError.stack : traversalTarget
|
|
60
61
|
);
|
|
61
62
|
|
|
63
|
+
let setupWorkspace = null;
|
|
64
|
+
try {
|
|
65
|
+
setupWorkspace = buildWorkspace({
|
|
66
|
+
id: 'fixture-setup-valid',
|
|
67
|
+
fixture: {
|
|
68
|
+
files: [{ path: 'seed.txt', content: 'seed' }],
|
|
69
|
+
setup: 'behavioral-evals/fixtures/setup/noop.js',
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
const setupResult = runFixtureSetup({
|
|
73
|
+
id: 'fixture-setup-valid',
|
|
74
|
+
fixture: { setup: 'behavioral-evals/fixtures/setup/noop.js' },
|
|
75
|
+
}, setupWorkspace);
|
|
76
|
+
helper.check(
|
|
77
|
+
'2j. fixture setup runs via Node in the generated workspace',
|
|
78
|
+
setupResult.status === 'pass' &&
|
|
79
|
+
fs.readFileSync(path.join(setupWorkspace, '.fixture-setup-ok'), 'utf8') === 'ok\n',
|
|
80
|
+
JSON.stringify(setupResult)
|
|
81
|
+
);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
helper.check('2j. fixture setup runs via Node in the generated workspace', false, error && error.stack ? error.stack : String(error));
|
|
84
|
+
} finally {
|
|
85
|
+
if (setupWorkspace) fs.rmSync(setupWorkspace, { recursive: true, force: true });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let failedPreparation = null;
|
|
89
|
+
try {
|
|
90
|
+
failedPreparation = prepareWorkspace({
|
|
91
|
+
id: 'fixture-setup-fails',
|
|
92
|
+
fixture: {
|
|
93
|
+
files: [{ path: 'seed.txt', content: 'seed' }],
|
|
94
|
+
setup: 'behavioral-evals/fixtures/setup/fail.js',
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
} catch (error) {
|
|
98
|
+
failedPreparation = { threw: error && error.stack ? error.stack : String(error) };
|
|
99
|
+
}
|
|
100
|
+
helper.check(
|
|
101
|
+
'2j. setup failure is classified as fixture-error before any model session',
|
|
102
|
+
Boolean(
|
|
103
|
+
failedPreparation &&
|
|
104
|
+
failedPreparation.ok === false &&
|
|
105
|
+
failedPreparation.outcome === 'fixture-error' &&
|
|
106
|
+
failedPreparation.setup &&
|
|
107
|
+
failedPreparation.setup.status === 'fail' &&
|
|
108
|
+
failedPreparation.setup.exit_code === 17
|
|
109
|
+
),
|
|
110
|
+
JSON.stringify(failedPreparation)
|
|
111
|
+
);
|
|
112
|
+
if (failedPreparation && failedPreparation.workspace) {
|
|
113
|
+
fs.rmSync(failedPreparation.workspace, { recursive: true, force: true });
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
let topologyPreparation = null;
|
|
117
|
+
try {
|
|
118
|
+
topologyPreparation = prepareWorkspace({
|
|
119
|
+
id: 'worktree-submodule-setup-smoke',
|
|
120
|
+
fixture: {
|
|
121
|
+
files: [{ path: 'README.md', content: 'topology smoke' }],
|
|
122
|
+
setup: 'behavioral-evals/fixtures/setup/worktree-submodule.js',
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
const linkedSub = topologyPreparation.ok
|
|
126
|
+
? path.join(topologyPreparation.workspace, 'super-wt', 'libs', 'sub')
|
|
127
|
+
: null;
|
|
128
|
+
const branchResult = linkedSub
|
|
129
|
+
? spawnSync('git', ['-C', linkedSub, 'branch', '--show-current'], { encoding: 'utf8', windowsHide: true })
|
|
130
|
+
: null;
|
|
131
|
+
const helperResult = topologyPreparation.ok
|
|
132
|
+
? spawnSync(process.execPath, [
|
|
133
|
+
path.join(topologyPreparation.workspace, '.fixture-tools', 'submodule-reachability.js'),
|
|
134
|
+
'--json', '--root', 'super-wt',
|
|
135
|
+
], { cwd: topologyPreparation.workspace, encoding: 'utf8', windowsHide: true })
|
|
136
|
+
: null;
|
|
137
|
+
helper.check(
|
|
138
|
+
'2j. worktree/submodule setup creates the real #243 topology before model execution',
|
|
139
|
+
Boolean(
|
|
140
|
+
topologyPreparation.ok &&
|
|
141
|
+
fs.existsSync(path.join(topologyPreparation.workspace, 'super-wt', '.git')) &&
|
|
142
|
+
fs.existsSync(path.join(linkedSub, '.git')) &&
|
|
143
|
+
branchResult && branchResult.status === 0 && branchResult.stdout.trim() === '' &&
|
|
144
|
+
helperResult && helperResult.status === 0
|
|
145
|
+
),
|
|
146
|
+
JSON.stringify({
|
|
147
|
+
preparation: topologyPreparation,
|
|
148
|
+
branchStatus: branchResult && branchResult.status,
|
|
149
|
+
branch: branchResult && branchResult.stdout,
|
|
150
|
+
helperStatus: helperResult && helperResult.status,
|
|
151
|
+
helperStderr: helperResult && helperResult.stderr,
|
|
152
|
+
})
|
|
153
|
+
);
|
|
154
|
+
} catch (error) {
|
|
155
|
+
helper.check(
|
|
156
|
+
'2j. worktree/submodule setup creates the real #243 topology before model execution',
|
|
157
|
+
false,
|
|
158
|
+
error && error.stack ? error.stack : String(error)
|
|
159
|
+
);
|
|
160
|
+
} finally {
|
|
161
|
+
if (topologyPreparation && topologyPreparation.workspace) {
|
|
162
|
+
fs.rmSync(topologyPreparation.workspace, { recursive: true, force: true });
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const fixtureFailureSummary = summarizePairResults([{
|
|
167
|
+
id: 'fixture-error-pair',
|
|
168
|
+
pressure_category: null,
|
|
169
|
+
arms: {
|
|
170
|
+
baseline: { outcome: 'fixture-error', cost: null, tool_call_count: null },
|
|
171
|
+
treatment: { outcome: 'pass', cost: null, tool_call_count: 1 },
|
|
172
|
+
},
|
|
173
|
+
}]);
|
|
174
|
+
helper.check(
|
|
175
|
+
'2j. fixture errors remain distinct aggregate infrastructure failures',
|
|
176
|
+
fixtureFailureSummary.fixture_failures === 1 &&
|
|
177
|
+
fixtureFailureSummary.session_failures === 0 &&
|
|
178
|
+
fixtureFailureSummary.completed_pairs === 0,
|
|
179
|
+
JSON.stringify(fixtureFailureSummary)
|
|
180
|
+
);
|
|
181
|
+
|
|
62
182
|
helper.finish();
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const assert = require('assert');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const { spawnSync } = require('child_process');
|
|
8
|
+
const { parseSimpleYaml, prepareWorkspace } = require('../behavioral-evals/run');
|
|
9
|
+
const paired = require('../behavioral-evals/paired-benchmark');
|
|
10
|
+
const ROOT = path.resolve(__dirname, '..');
|
|
11
|
+
const topology = parseSimpleYaml(fs.readFileSync(path.join(ROOT, 'behavioral-evals/cases/baseline-worktree-submodule-reachability.yaml'), 'utf8'));
|
|
12
|
+
const failure = { ...topology, fixture: { ...topology.fixture, setup: 'behavioral-evals/fixtures/setup/fail.js' } };
|
|
13
|
+
const paths = [];
|
|
14
|
+
const topologyFingerprints = [];
|
|
15
|
+
const setupHashes = [];
|
|
16
|
+
function track(ws) { if (ws) paths.push(ws); return ws; }
|
|
17
|
+
function gitText(cwd, args) {
|
|
18
|
+
const result = spawnSync('git', args, { cwd, encoding: 'utf8', windowsHide: true });
|
|
19
|
+
assert.strictEqual(result.status, 0, result.stderr || result.stdout);
|
|
20
|
+
return result.stdout.trim();
|
|
21
|
+
}
|
|
22
|
+
function topologyFingerprint(ws) {
|
|
23
|
+
return {
|
|
24
|
+
child_head: gitText(path.join(ws, 'child-origin'), ['rev-parse', 'HEAD']),
|
|
25
|
+
super_head: gitText(path.join(ws, 'super'), ['rev-parse', 'HEAD']),
|
|
26
|
+
linked_head: gitText(path.join(ws, 'super-wt'), ['rev-parse', 'HEAD']),
|
|
27
|
+
gitlink: gitText(path.join(ws, 'super-wt'), ['rev-parse', 'HEAD:libs/sub']),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function assertTopology(ws) {
|
|
31
|
+
assert.ok(fs.existsSync(path.join(ws, 'super-wt', '.git')), 'setup must construct the linked worktree');
|
|
32
|
+
assert.ok(fs.existsSync(path.join(ws, '.fixture-tools', 'verify-worktree-submodule.js')), 'setup must install the grader');
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
for (const arm of ['baseline', 'treatment']) {
|
|
36
|
+
for (const effect of ['skill-text', 'plugin-enforcement']) {
|
|
37
|
+
const prepared = paired.prepareArmWorkspace(topology, effect, arm, 'opencode');
|
|
38
|
+
track(prepared.ws);
|
|
39
|
+
assertTopology(prepared.ws);
|
|
40
|
+
assert.strictEqual(prepared.fixture_setup.status, 'pass');
|
|
41
|
+
assert.match(prepared.fixture_setup.script_sha256, /^[0-9a-f]{64}$/);
|
|
42
|
+
topologyFingerprints.push(topologyFingerprint(prepared.ws));
|
|
43
|
+
setupHashes.push(prepared.fixture_setup.script_sha256);
|
|
44
|
+
const failed = paired.prepareArmWorkspace(failure, effect, arm, 'opencode');
|
|
45
|
+
track(failed.ws);
|
|
46
|
+
assert.strictEqual(failed.ok, false);
|
|
47
|
+
assert.strictEqual(failed.outcome, 'fixture-error');
|
|
48
|
+
assert.strictEqual(failed.fixture_setup.exit_code, 17);
|
|
49
|
+
assert.ok(!fs.existsSync(path.join(failed.ws, '.claude')), 'setup failure must precede skill installation');
|
|
50
|
+
assert.ok(!fs.existsSync(path.join(failed.ws, '.opencode')), 'setup failure must precede plugin installation');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
assert.ok(topologyFingerprints.length >= 4);
|
|
54
|
+
for (const fingerprint of topologyFingerprints.slice(1)) {
|
|
55
|
+
assert.deepStrictEqual(fingerprint, topologyFingerprints[0], 'fixture setup must produce identical Git object identities across independent arms/runs');
|
|
56
|
+
}
|
|
57
|
+
assert.strictEqual(new Set(setupHashes).size, 1, 'all arms must retain the same checked-in setup script hash');
|
|
58
|
+
|
|
59
|
+
const pairDir = track(fs.mkdtempSync(path.join(os.tmpdir(), 'fixture-entrypoints-')));
|
|
60
|
+
let launches = 0;
|
|
61
|
+
const context = { effect_type: 'skill-text', engine: 'claude', model: 'test' };
|
|
62
|
+
const arms = {};
|
|
63
|
+
for (const arm of ['baseline', 'treatment']) {
|
|
64
|
+
arms[arm] = paired.runArm(failure, context, arm, pairDir, () => { launches++; throw new Error('model must not start'); });
|
|
65
|
+
assert.strictEqual(arms[arm].outcome, 'fixture-error');
|
|
66
|
+
assert.strictEqual(arms[arm].fixture_setup.exit_code, 17);
|
|
67
|
+
assert.strictEqual(arms[arm].tool_call_count, null);
|
|
68
|
+
}
|
|
69
|
+
assert.strictEqual(launches, 0);
|
|
70
|
+
const summary = paired.summarizePairs([{ id: topology.id, arms }], 10);
|
|
71
|
+
assert.strictEqual(summary.fixture_failures, 1);
|
|
72
|
+
assert.strictEqual(summary.included_pairs, 0);
|
|
73
|
+
assert.deepStrictEqual(summary.arm_outcomes, { baseline: { pass: 0, fail: 0 }, treatment: { pass: 0, fail: 0 } });
|
|
74
|
+
|
|
75
|
+
const plugin = require('../behavioral-evals/run-with-plugin');
|
|
76
|
+
const failed = plugin.runCase(failure, () => { launches++; throw new Error('model must not start'); });
|
|
77
|
+
track(failed.workspace);
|
|
78
|
+
assert.strictEqual(failed.outcome, 'fixture-error');
|
|
79
|
+
assert.strictEqual(failed.fixture_setup.exit_code, 17);
|
|
80
|
+
assert.strictEqual(launches, 0);
|
|
81
|
+
assert.ok(!fs.existsSync(path.join(failed.workspace, '.harness-src')), 'failed setup must precede Harness installation');
|
|
82
|
+
|
|
83
|
+
// Exercise the same public case path as the plugin CLI, without calling a model.
|
|
84
|
+
const result = plugin.runCase(topology, (_prompt, ws) => {
|
|
85
|
+
launches++;
|
|
86
|
+
assertTopology(ws);
|
|
87
|
+
const transcript = path.join(pairDir, 'plugin-transcript.jsonl');
|
|
88
|
+
fs.writeFileSync(transcript, '');
|
|
89
|
+
return transcript;
|
|
90
|
+
});
|
|
91
|
+
track(result.workspace);
|
|
92
|
+
assert.strictEqual(launches, 1);
|
|
93
|
+
assert.strictEqual(result.fixture_setup.status, 'pass');
|
|
94
|
+
assert.strictEqual(result.outcome, 'fail', 'an untouched topology must fail the actual final-state graders');
|
|
95
|
+
|
|
96
|
+
for (const fixture of [
|
|
97
|
+
{ files: [{ path: '../escape', content: 'bad' }] },
|
|
98
|
+
{ files: [{ path: 'seed', content: 'ok' }], setup: '../escape.js' },
|
|
99
|
+
]) {
|
|
100
|
+
const result = prepareWorkspace({ id: 'invalid-fixture', fixture });
|
|
101
|
+
track(result.workspace);
|
|
102
|
+
assert.strictEqual(result.outcome, 'fixture-error');
|
|
103
|
+
}
|
|
104
|
+
// The public CLIs must retain fixture-error evidence and exit nonzero.
|
|
105
|
+
const caseId = `fixture-entrypoints-failure-${process.pid}`;
|
|
106
|
+
const casePath = path.join(ROOT, 'behavioral-evals/cases', `${caseId}.yaml`);
|
|
107
|
+
fs.writeFileSync(casePath, `id: ${caseId}
|
|
108
|
+
name: Fixture failure CLI control
|
|
109
|
+
loaded_skills:
|
|
110
|
+
- git-commit
|
|
111
|
+
fixture:
|
|
112
|
+
files:
|
|
113
|
+
- path: seed.txt
|
|
114
|
+
content: seed
|
|
115
|
+
setup: behavioral-evals/fixtures/setup/fail.js
|
|
116
|
+
prompt: This model session must never start.
|
|
117
|
+
max_turns: 1
|
|
118
|
+
expectations:
|
|
119
|
+
- type: file_contains
|
|
120
|
+
path: seed.txt
|
|
121
|
+
value: seed
|
|
122
|
+
`);
|
|
123
|
+
paths.push(casePath);
|
|
124
|
+
const pairedCli = spawnSync(process.execPath, [
|
|
125
|
+
path.join(ROOT, 'behavioral-evals/paired-benchmark.js'), 'run',
|
|
126
|
+
'--effect', 'skill-text', '--engine', 'claude', '--model', 'fixture-test',
|
|
127
|
+
'--min-effect-pp', '10', '--case', caseId,
|
|
128
|
+
], { cwd: ROOT, encoding: 'utf8', timeout: 30000 });
|
|
129
|
+
const summaryMatch = pairedCli.stdout.match(/Summary: (.+)/);
|
|
130
|
+
assert.ok(summaryMatch, pairedCli.stderr || pairedCli.stdout);
|
|
131
|
+
const summaryPath = summaryMatch[1].trim();
|
|
132
|
+
track(path.dirname(summaryPath));
|
|
133
|
+
assert.strictEqual(pairedCli.status, 1, pairedCli.stderr);
|
|
134
|
+
const cliSummary = JSON.parse(fs.readFileSync(summaryPath, 'utf8'));
|
|
135
|
+
assert.strictEqual(cliSummary.fixture_failures, 1);
|
|
136
|
+
assert.strictEqual(cliSummary.included_pairs, 0);
|
|
137
|
+
const pluginCli = spawnSync(process.execPath, [
|
|
138
|
+
path.join(ROOT, 'behavioral-evals/run-with-plugin.js'), 'run', '--case', caseId,
|
|
139
|
+
], { cwd: ROOT, encoding: 'utf8', timeout: 30000 });
|
|
140
|
+
assert.strictEqual(pluginCli.status, 1, pluginCli.stderr);
|
|
141
|
+
const resultMatch = pluginCli.stdout.match(/fixture-error -> (.+)/);
|
|
142
|
+
assert.ok(resultMatch, pluginCli.stdout);
|
|
143
|
+
const resultPath = resultMatch[1].trim();
|
|
144
|
+
paths.push(resultPath);
|
|
145
|
+
const pluginFailure = JSON.parse(fs.readFileSync(resultPath, 'utf8'));
|
|
146
|
+
track(pluginFailure.workspace);
|
|
147
|
+
assert.strictEqual(pluginFailure.fixture_setup.exit_code, 17);
|
|
148
|
+
assert.ok(!fs.existsSync(path.join(pluginFailure.workspace, '.harness-src')));
|
|
149
|
+
|
|
150
|
+
console.log('Fixture entrypoints: paired baseline/treatment and plugin execute setup; failures skip installation/model and are excluded from scores.');
|
|
151
|
+
} finally {
|
|
152
|
+
for (const dir of paths) fs.rmSync(dir, { recursive: true, force: true });
|
|
153
|
+
}
|
|
@@ -85,3 +85,20 @@ test('S1-E07 source provenance gate requires the pinned cua_s1 revision', () =>
|
|
|
85
85
|
assert.equal(evaluate(make(), records(), recorded('pinned')).gates.sourceProvenance, true);
|
|
86
86
|
assert.equal(evaluate(make(), records(), recorded('pinned')).rolloutReady, false);
|
|
87
87
|
});
|
|
88
|
+
test('S1-E09 an ngram source passes provenance only with a verified artifact', () => {
|
|
89
|
+
const ngramSource = verified => ({ status: 'recorded', transport: 'ngram', artifactVerified: verified });
|
|
90
|
+
assert.equal(evaluate(make(), records(), ngramSource(true)).gates.sourceProvenance, true);
|
|
91
|
+
assert.equal(evaluate(make(), records(), ngramSource(false)).gates.sourceProvenance, false);
|
|
92
|
+
assert.equal(evaluate(make(), records(), { status: 'recorded', transport: 'ngram' }).gates.sourceProvenance, false);
|
|
93
|
+
assert.equal(evaluate(make(), records(), { status: 'unavailable', reason: 'provider-config', transport: 'ngram', artifactVerified: true }).gates.sourceProvenance, false);
|
|
94
|
+
});
|
|
95
|
+
test('S1-E08 the accepted-precision gate is the owner advisory 85%', () => {
|
|
96
|
+
// 7 accepted tier1 answers: 6 correct (85.7%) passes, 5 correct (71.4%) fails.
|
|
97
|
+
const cases = Array.from({ length: 7 }, (_, i) => ({ id: `p${i}`, family: `f${i}`, split: 'holdout', language: 'en', source: 'human:fixture', reviewed: false,
|
|
98
|
+
request: createRequest('tier', `bounded prompt ${i}`, TIER_OPTIONS), gold: 'tier1' }));
|
|
99
|
+
const corpus = { schemaVersion: 1, cases };
|
|
100
|
+
const recs = wrong => cases.map((c, i) => { const id = i < wrong ? 'tier2' : 'tier1';
|
|
101
|
+
return { id: c.id, baseline: 'tier2', runs: [0, 1].map(() => ({ decision: decision(id), scores: oneHot(id), latencyMs: 20, coldStart: true })) }; });
|
|
102
|
+
assert.equal(evaluate(corpus, recs(1)).gates.acceptedPrecision, true);
|
|
103
|
+
assert.equal(evaluate(corpus, recs(2)).gates.acceptedPrecision, false);
|
|
104
|
+
});
|
|
@@ -61,6 +61,33 @@ test('S1-L03 invalid replies are retried once, persistent failures are recorded,
|
|
|
61
61
|
assert.equal(again.labeled.length, 0);
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
+
test('S1-L06 the codex engine runs one stateless exec per batch and reads the schema-checked last message', () => {
|
|
65
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-s1-codex-'));
|
|
66
|
+
try {
|
|
67
|
+
// Fake codex: records its argv, reads the prompt from stdin, writes the reply to the -o file.
|
|
68
|
+
const fake = path.join(dir, 'fake-codex.js'); const argvLog = path.join(dir, 'argv.json');
|
|
69
|
+
// Without an -o target the fake exits instead of writing (a[-1 + 1] would land in the working directory).
|
|
70
|
+
fs.writeFileSync(fake, `const fs=require('fs');const a=process.argv.slice(2);fs.writeFileSync(${JSON.stringify(argvLog)},JSON.stringify(a));
|
|
71
|
+
const o=a.indexOf('-o');if(o<0)process.exit(3);
|
|
72
|
+
let s='';process.stdin.on('data',d=>s+=d).on('end',()=>{const m=[...s.matchAll(/\\{"i":(\\d+),"text"/g)];
|
|
73
|
+
fs.writeFileSync(a[o+1],JSON.stringify({labels:m.map(x=>({i:Number(x[1]),gold:'tier1'}))}));});`);
|
|
74
|
+
const input = path.join(dir, 'prompts.jsonl');
|
|
75
|
+
fs.writeFileSync(input, items(3).map(r => JSON.stringify({ ...r, family: 'f', source: 'claude', split: 'train' })).join('\n') + '\n');
|
|
76
|
+
const out = path.join(dir, 'labels.jsonl');
|
|
77
|
+
const r = spawnSync(process.execPath, [path.join(root, 'scripts/system-one-label.js'), 'label', '--engine', 'codex', '--in', input, '--out', out],
|
|
78
|
+
{ encoding: 'utf8', cwd: root, env: { ...process.env, HARNESS_S1_LABEL_COMMAND: JSON.stringify([process.execPath, fake]) } });
|
|
79
|
+
assert.equal(r.status, 0, r.stderr);
|
|
80
|
+
assert.deepEqual(JSON.parse(r.stdout), { labeled: 3, failed: 0, total: 3 });
|
|
81
|
+
const rows = fs.readFileSync(out, 'utf8').trim().split('\n').map(l => JSON.parse(l));
|
|
82
|
+
assert.ok(rows.every(x => x.gold === 'tier1' && x.labeler.model === 'gpt-5.6-luna' && x.labeler.engine === 'codex'));
|
|
83
|
+
const argv = JSON.parse(fs.readFileSync(argvLog, 'utf8'));
|
|
84
|
+
for (const flag of ['exec', '--ephemeral', '--ignore-user-config', '--output-schema', '-o']) assert.ok(argv.includes(flag), flag);
|
|
85
|
+
assert.equal(argv[argv.indexOf('--sandbox') + 1], 'read-only');
|
|
86
|
+
assert.equal(argv[argv.indexOf('--model') + 1], 'gpt-5.6-luna');
|
|
87
|
+
assert.equal(argv[argv.length - 1], '-', 'the prompt comes from stdin');
|
|
88
|
+
} finally { fs.rmSync(dir, { recursive: true, force: true }); }
|
|
89
|
+
});
|
|
90
|
+
|
|
64
91
|
test('S1-L04 holdout agreement reports overall, per-class recall and confusion', () => {
|
|
65
92
|
const gold = [['a', 'tier1'], ['b', 'tier1'], ['c', 'tier2'], ['d', null]];
|
|
66
93
|
const pred = { a: 'tier1', b: 'tier2', c: 'tier2', d: null };
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { test } = require('node:test');
|
|
3
|
+
const assert = require('node:assert/strict');
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const os = require('node:os');
|
|
6
|
+
const path = require('node:path');
|
|
7
|
+
const { createHash } = require('node:crypto');
|
|
8
|
+
const { spawnSync } = require('node:child_process');
|
|
9
|
+
const ngram = require('../harness-everything/scripts/system-one/ngram');
|
|
10
|
+
const provider = require('../harness-everything/scripts/system-one/provider');
|
|
11
|
+
const { createRequest, decide } = require('../harness-everything/scripts/system-one/contract');
|
|
12
|
+
const { TIER_OPTIONS } = require('../harness-everything/scripts/system-one/router');
|
|
13
|
+
const root = path.resolve(__dirname, '..');
|
|
14
|
+
const python = process.env.PYTHON || (process.platform === 'win32' ? 'python' : 'python3');
|
|
15
|
+
const sha = file => createHash('sha256').update(fs.readFileSync(file)).digest('hex');
|
|
16
|
+
const IDS = TIER_OPTIONS.map(o => o.id);
|
|
17
|
+
|
|
18
|
+
// A tiny model whose weights push any text containing the "commit" trigram toward tier1.
|
|
19
|
+
function artifact(dir, { dim = 1024, nmax = 3, catalog = IDS, sidecar = {}, bytes } = {}) {
|
|
20
|
+
const W = new Float32Array(dim * catalog.length);
|
|
21
|
+
const hot = ngram.fnv1a32('3:com') % dim;
|
|
22
|
+
W[hot * catalog.length + 0] = 40;
|
|
23
|
+
const bin = path.join(dir, 'tier.bin'); const json = path.join(dir, 'tier.json');
|
|
24
|
+
fs.writeFileSync(bin, bytes || Buffer.from(W.buffer));
|
|
25
|
+
fs.writeFileSync(json, JSON.stringify({ format: 'harness-ngram', formatVersion: 1, dim, nmax, hash: 'fnv1a32', catalog, bias: catalog.map(() => 0), metadata: { fixture: true }, ...sidecar }));
|
|
26
|
+
return { bin, json };
|
|
27
|
+
}
|
|
28
|
+
function manifest(dir, files, extra = {}) {
|
|
29
|
+
const m = { schemaVersion: 1, transport: 'ngram', checkpoint: files.bin, weightsSha256: sha(files.bin), configSha256: sha(files.json),
|
|
30
|
+
modelId: 'fixture/ngram', revision: 'v1', domain: 'harness-routing-v1', ...extra };
|
|
31
|
+
const p = path.join(dir, 'manifest.json'); fs.writeFileSync(p, JSON.stringify(m)); return { m, p };
|
|
32
|
+
}
|
|
33
|
+
const tmp = () => fs.mkdtempSync(path.join(os.tmpdir(), 'harness-s1-ngram-'));
|
|
34
|
+
|
|
35
|
+
test('S1-N01 fnv1a32 matches the published test vectors', () => {
|
|
36
|
+
assert.equal(ngram.fnv1a32(''), 0x811c9dc5);
|
|
37
|
+
assert.equal(ngram.fnv1a32('a'), 0xe40c292c);
|
|
38
|
+
assert.equal(ngram.fnv1a32('foobar'), 0xbf9cf968);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('S1-N02 featurization follows the pinned rules', () => {
|
|
42
|
+
const f = ngram.featurize(' Commit ALL\tchanges ', 3, 1 << 16);
|
|
43
|
+
assert.deepEqual(f, ngram.featurize('commit all changes', 3, 1 << 16), 'lowercase and whitespace normalization');
|
|
44
|
+
const norm = Math.sqrt([...f.values()].reduce((s, v) => s + v * v, 0));
|
|
45
|
+
assert.ok(Math.abs(norm - 1) < 1e-12);
|
|
46
|
+
assert.ok(f.has(ngram.fnv1a32('len:4') % (1 << 16)), 'length bucket for 18 UTF-8 bytes');
|
|
47
|
+
const cjk = ngram.featurize('修正😀', 2, 1 << 16);
|
|
48
|
+
assert.ok(cjk.has(ngram.fnv1a32('2:正😀') % (1 << 16)), 'n-grams are over code points, not UTF-16 units');
|
|
49
|
+
assert.ok(!ngram.featurize('a b', 3, 1 << 16).has(ngram.fnv1a32('1: ') % (1 << 16)), 'space-only grams are skipped');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('S1-N03 the Python trainer and the Node provider produce identical features', () => {
|
|
53
|
+
const texts = ['commit all changes', '幫我修正 parser 的錯誤並補測試', ' MIXED Case\ttext 😀 ', 'x', '重構 plugin 介面,跨兩個 repo'];
|
|
54
|
+
const hashes = ['', 'a', 'foobar', '3:修正測'];
|
|
55
|
+
const r = spawnSync(python, [path.join(__dirname, 'system-one-ngram-parity.py')], { input: JSON.stringify({ texts, hashes, nmax: 3, dim: 1 << 16 }), encoding: 'utf8', env: { ...process.env, PYTHONDONTWRITEBYTECODE: '1', PYTHONIOENCODING: 'utf-8' } });
|
|
56
|
+
assert.equal(r.status, 0, r.stderr);
|
|
57
|
+
const py = JSON.parse(r.stdout);
|
|
58
|
+
assert.deepEqual(py.hash, hashes.map(h => ngram.fnv1a32(h)));
|
|
59
|
+
texts.forEach((t, i) => {
|
|
60
|
+
const node = ngram.featurize(t, 3, 1 << 16);
|
|
61
|
+
assert.deepEqual(Object.keys(py.features[i]).map(Number).sort((a, b) => a - b), [...node.keys()].sort((a, b) => a - b), t);
|
|
62
|
+
for (const [k, v] of Object.entries(py.features[i])) assert.ok(Math.abs(v - node.get(Number(k))) < 1e-12, t);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test('S1-N04 the ngram transport scores in process with the Phase 0 response shape', async () => {
|
|
67
|
+
const dir = tmp();
|
|
68
|
+
try {
|
|
69
|
+
const { m, p } = manifest(dir, artifact(dir), { acceptance: { minConfidence: 0.5, minMargin: 0 } });
|
|
70
|
+
assert.equal(provider.validateManifest(m), true);
|
|
71
|
+
const request = createRequest('tier', 'please commit these changes', TIER_OPTIONS);
|
|
72
|
+
const result = provider.score(request, p);
|
|
73
|
+
assert.equal(result.status, 'scored');
|
|
74
|
+
assert.deepEqual(result.acceptance, { minConfidence: 0.5, minMargin: 0 });
|
|
75
|
+
assert.deepEqual(result.response.model, { id: 'fixture/ngram', revision: 'v1', domain: 'harness-routing-v1' });
|
|
76
|
+
assert.ok(Math.abs(result.response.scores.reduce((s, x) => s + x.probability, 0) - 1) < 1e-9);
|
|
77
|
+
const d = decide(request, result.response, result.acceptance);
|
|
78
|
+
assert.equal(d.status, 'accepted'); assert.equal(d.selectedId, 'tier1');
|
|
79
|
+
assert.deepEqual(await provider.scoreAsync(request, p), result);
|
|
80
|
+
const other = provider.score(createRequest('tier', 'unrelated words only', TIER_OPTIONS), p);
|
|
81
|
+
assert.ok(other.response.scores.every(s => Math.abs(s.probability - 0.25) < 1e-9), 'no active weights gives a uniform vector');
|
|
82
|
+
} finally { fs.rmSync(dir, { recursive: true, force: true }); }
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('S1-N05 any artifact mismatch is provider-config and never scores', () => {
|
|
86
|
+
const request = createRequest('tier', 'commit it', TIER_OPTIONS);
|
|
87
|
+
const cases = [
|
|
88
|
+
dir => { const f = artifact(dir); const { m, p } = manifest(dir, f); fs.appendFileSync(f.bin, Buffer.alloc(4)); return p; },
|
|
89
|
+
dir => { const f = artifact(dir, { bytes: Buffer.alloc(8) }); return manifest(dir, f).p; },
|
|
90
|
+
dir => manifest(dir, artifact(dir, { catalog: ['tier1', 'tier2', 'tier3', 'other'] })).p,
|
|
91
|
+
dir => manifest(dir, artifact(dir, { sidecar: { format: 'other' } })).p,
|
|
92
|
+
dir => manifest(dir, artifact(dir, { sidecar: { extra: 1 } })).p,
|
|
93
|
+
dir => manifest(dir, artifact(dir, { dim: 1000 })).p,
|
|
94
|
+
dir => manifest(dir, artifact(dir, { nmax: 9 })).p,
|
|
95
|
+
dir => manifest(dir, artifact(dir, { sidecar: { bias: [0, 0] } })).p,
|
|
96
|
+
];
|
|
97
|
+
for (const make of cases) {
|
|
98
|
+
const dir = tmp();
|
|
99
|
+
try { assert.deepEqual(provider.score(request, make(dir)), { status: 'unavailable', reason: 'provider-config' }); }
|
|
100
|
+
finally { fs.rmSync(dir, { recursive: true, force: true }); }
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('S1-N06 manifest rules: ngram needs a .bin and no python; other transports still need python', () => {
|
|
105
|
+
const dir = tmp();
|
|
106
|
+
try {
|
|
107
|
+
const { m } = manifest(dir, artifact(dir));
|
|
108
|
+
assert.equal(provider.validateManifest(m), true);
|
|
109
|
+
assert.throws(() => provider.validateManifest({ ...m, checkpoint: m.checkpoint.replace(/\.bin$/, '.safetensors') }));
|
|
110
|
+
assert.throws(() => provider.validateManifest({ ...m, transport: 'resident' }), 'resident requires python and a .safetensors checkpoint');
|
|
111
|
+
assert.throws(() => provider.validateManifest({ ...m, transport: 'bogus' }));
|
|
112
|
+
} finally { fs.rmSync(dir, { recursive: true, force: true }); }
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test('S1-N08 the evaluator records ngram samples warm and verifies the artifact as provenance', () => {
|
|
116
|
+
const dir = tmp();
|
|
117
|
+
try {
|
|
118
|
+
const { p } = manifest(dir, artifact(dir));
|
|
119
|
+
const output = path.join(dir, 'report.json');
|
|
120
|
+
const corpus = path.join(root, 'benchmarks/fixtures/system-one-routing.json');
|
|
121
|
+
const r = spawnSync(process.execPath, [path.join(root, 'scripts/evaluate-system-one.js'), corpus, p, output], { encoding: 'utf8', cwd: root });
|
|
122
|
+
assert.equal(r.status, 0, r.stderr);
|
|
123
|
+
const report = JSON.parse(fs.readFileSync(output, 'utf8'));
|
|
124
|
+
assert.ok(report.records.every(x => x.runs.every(run => run.coldStart === false)));
|
|
125
|
+
assert.equal(report.latency.coldSamples, 0);
|
|
126
|
+
assert.equal(report.gates.warmLatency, true);
|
|
127
|
+
assert.deepEqual(report.evidence.source, { status: 'recorded', transport: 'ngram', artifactVerified: true });
|
|
128
|
+
assert.equal(report.gates.sourceProvenance, true);
|
|
129
|
+
assert.equal(report.evidence.kind, 'offline-ngram');
|
|
130
|
+
fs.appendFileSync(path.join(dir, 'tier.bin'), Buffer.alloc(4));
|
|
131
|
+
const tampered = spawnSync(process.execPath, [path.join(root, 'scripts/evaluate-system-one.js'), corpus, p, output], { encoding: 'utf8', cwd: root });
|
|
132
|
+
assert.equal(tampered.status, 0, tampered.stderr);
|
|
133
|
+
const bad = JSON.parse(fs.readFileSync(output, 'utf8'));
|
|
134
|
+
assert.equal(bad.evidence.source.artifactVerified, false);
|
|
135
|
+
assert.equal(bad.gates.sourceProvenance, false);
|
|
136
|
+
assert.equal(bad.model.coverage, 0);
|
|
137
|
+
} finally { fs.rmSync(dir, { recursive: true, force: true }); }
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test('S1-N07 a real ngram training run produces an artifact the provider scores (skipped without torch)', t => {
|
|
141
|
+
if (spawnSync(python, ['-c', 'import torch'], { encoding: 'utf8' }).status !== 0) { t.skip('torch not installed'); return; }
|
|
142
|
+
const dir = tmp();
|
|
143
|
+
try {
|
|
144
|
+
const data = path.join(dir, 'data'); fs.mkdirSync(data);
|
|
145
|
+
const texts = [['commit all changes', 'tier1'], ['push and open a pr', 'tier1'], ['add a new flag with tests', 'tier3'], ['migrate every service', 'tier3'], ['fix the failing parser test', 'tier2'], ['go', null]];
|
|
146
|
+
const prompts = []; const labels = [];
|
|
147
|
+
for (let k = 0; k < 10; k++) texts.forEach(([x, g], i) => { const id = `p${k}-${i}`; prompts.push({ id, family: `f${k}`, source: 'claude', split: k < 8 ? 'train' : 'validation', text: `${x} ${k}` }); labels.push({ id, gold: g }); });
|
|
148
|
+
fs.writeFileSync(path.join(data, 'prompts.jsonl'), prompts.map(x => JSON.stringify(x)).join('\n') + '\n');
|
|
149
|
+
fs.writeFileSync(path.join(data, 'labels.jsonl'), labels.map(x => JSON.stringify(x)).join('\n') + '\n');
|
|
150
|
+
const out = path.join(dir, 'model');
|
|
151
|
+
const r = spawnSync(python, [path.join(root, 'scripts/system-one-train-ngram.py'), '--data-dir', data, '--out', out, '--dim', '4096', '--epochs', '40'], { encoding: 'utf8' });
|
|
152
|
+
assert.equal(r.status, 0, r.stdout + r.stderr);
|
|
153
|
+
const files = { bin: path.join(out, 'harness-routing-v1.bin'), json: path.join(out, 'harness-routing-v1.json') };
|
|
154
|
+
assert.equal(fs.statSync(files.bin).size, 4096 * 4 * 4);
|
|
155
|
+
assert.equal(fs.readFileSync(path.join(out, 'val-scores.jsonl'), 'utf8').trim().split('\n').length, 12);
|
|
156
|
+
const { p } = manifest(dir, files);
|
|
157
|
+
const scored = provider.score(createRequest('tier', 'commit all changes now', TIER_OPTIONS), p);
|
|
158
|
+
assert.equal(scored.status, 'scored');
|
|
159
|
+
assert.equal(decide(createRequest('tier', 'commit all changes now', TIER_OPTIONS), scored.response, { minConfidence: 0.5, minMargin: 0 }).selectedId, 'tier1');
|
|
160
|
+
} finally { fs.rmSync(dir, { recursive: true, force: true }); }
|
|
161
|
+
});
|
|
@@ -41,6 +41,18 @@ test('S1-T03 calibration maximizes coverage subject to accepted precision on val
|
|
|
41
41
|
assert.deepEqual(calibrate(rows, { minPrecision: 0.98 }), c, 'deterministic');
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
+
test('S1-T06 the default calibration target is the owner advisory 85%', () => {
|
|
45
|
+
const rows = [
|
|
46
|
+
...Array.from({ length: 86 }, () => row('tier1', [0.9, 0.05, 0.03, 0.02])),
|
|
47
|
+
...Array.from({ length: 14 }, () => row('tier2', [0.9, 0.05, 0.03, 0.02])),
|
|
48
|
+
];
|
|
49
|
+
const c = calibrate(rows);
|
|
50
|
+
assert.equal(c.minPrecision, 0.85);
|
|
51
|
+
assert.equal(c.feasible, true);
|
|
52
|
+
assert.equal(c.coverage, 1);
|
|
53
|
+
assert.equal(calibrate(rows, { minPrecision: 0.9 }).feasible, false);
|
|
54
|
+
});
|
|
55
|
+
|
|
44
56
|
test('S1-T04 calibration CLI reads validation scores and writes thresholds', () => {
|
|
45
57
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-s1-cal-'));
|
|
46
58
|
try {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Print the trainer's n-gram features for texts on stdin (JSON list) so the Node provider can be compared exactly."""
|
|
2
|
+
import importlib.util
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
sys.dont_write_bytecode = True
|
|
8
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
9
|
+
spec = importlib.util.spec_from_file_location('ngram_trainer', ROOT / 'scripts' / 'system-one-train-ngram.py')
|
|
10
|
+
trainer = importlib.util.module_from_spec(spec)
|
|
11
|
+
spec.loader.exec_module(trainer)
|
|
12
|
+
assert 'torch' not in sys.modules, 'importing the ngram trainer must not import torch'
|
|
13
|
+
|
|
14
|
+
request = json.loads(sys.stdin.read())
|
|
15
|
+
out = []
|
|
16
|
+
for text in request['texts']:
|
|
17
|
+
feats = trainer.featurize(text, request['nmax'], request['dim'])
|
|
18
|
+
out.append({str(k): v for k, v in sorted(feats.items())})
|
|
19
|
+
print(json.dumps({'hash': [trainer.fnv1a32(s) for s in request['hashes']], 'features': out}))
|
|
@@ -46,6 +46,12 @@ assert flat == list(range(len(lengths))), 'every example exactly once'
|
|
|
46
46
|
assert all(len(b) * max(lengths[i] for i in b) <= 4096 or len(b) == 1 for b in batches), 'budget respected'
|
|
47
47
|
assert batches == trainer.make_batches(lengths, token_budget=4096), 'deterministic'
|
|
48
48
|
|
|
49
|
+
weights = trainer.class_weights([0, 0, 0, 1, 2, 2], 4)
|
|
50
|
+
assert len(weights) == 4
|
|
51
|
+
assert weights[3] == 0.0, 'an absent class gets no weight'
|
|
52
|
+
assert weights[1] > weights[2] > weights[0], weights
|
|
53
|
+
assert abs(sum(w * n for w, n in zip(weights, [3, 1, 2, 0])) - 6) < 1e-9, 'weights average to 1 over the examples'
|
|
54
|
+
|
|
49
55
|
with tempfile.TemporaryDirectory() as tmp:
|
|
50
56
|
p = Path(tmp) / 'rows.jsonl'
|
|
51
57
|
p.write_text('\n'.join(json.dumps(r) for r in prompts) + '\n', encoding='utf-8')
|
|
@@ -21,6 +21,32 @@ assert.deepStrictEqual(validateCase({
|
|
|
21
21
|
expectations: [{ type: 'tool_call', value: 'Bash' }]
|
|
22
22
|
}), [], 'tool_call must remain part of the runner/validator schema');
|
|
23
23
|
|
|
24
|
+
const setupCase = setup => ({
|
|
25
|
+
id: 'fixture-setup-schema',
|
|
26
|
+
prompt: 'inspect the prepared fixture',
|
|
27
|
+
max_turns: 1,
|
|
28
|
+
fixture: {
|
|
29
|
+
files: [{ path: 'README.md', content: 'fixture' }],
|
|
30
|
+
setup,
|
|
31
|
+
},
|
|
32
|
+
expectations: [{ type: 'trace_contains', value: 'fixture' }],
|
|
33
|
+
});
|
|
34
|
+
assert.deepStrictEqual(
|
|
35
|
+
validateCase(setupCase('behavioral-evals/fixtures/setup/noop.js')),
|
|
36
|
+
[],
|
|
37
|
+
'checked-in repository-relative .js setup should be valid'
|
|
38
|
+
);
|
|
39
|
+
for (const [setup, expected] of [
|
|
40
|
+
['../escape.js', /fixture\.setup/],
|
|
41
|
+
['/tmp/escape.js', /fixture\.setup/],
|
|
42
|
+
['behavioral-evals/fixtures/setup/noop.txt', /\.js/],
|
|
43
|
+
['behavioral-evals/fixtures/setup/missing.js', /missing|checked-in/],
|
|
44
|
+
[{ command: 'echo unsafe' }, /fixture\.setup/],
|
|
45
|
+
]) {
|
|
46
|
+
const setupErrors = validateCase(setupCase(setup));
|
|
47
|
+
assert.ok(setupErrors.some(error => expected.test(error)), `setup ${JSON.stringify(setup)} should be rejected: ${setupErrors.join('; ')}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
24
50
|
const transcriptDir = fs.mkdtempSync(path.join(os.tmpdir(), 'behavioral-case-validation-'));
|
|
25
51
|
try {
|
|
26
52
|
const transcriptPath = path.join(transcriptDir, 'trace.jsonl');
|
|
@@ -16,7 +16,7 @@ to, judged from the prompt alone?** The labels follow the tier model in
|
|
|
16
16
|
| --- | --- | --- |
|
|
17
17
|
| `tier1` | Something answered or done without changing project behavior: Git/GitHub housekeeping (commit, push, open a PR, sync, tag, post given results as a comment), a status check, reading a log or searching and reporting, the smallest doc fix (a typo, a link, an ignore entry), or a reply the assistant can give directly, including non-engineering chores and discussion questions | "commit these changes", "is issue 88 still open?", "find every repo still using the old logging package", "close the other apps" |
|
|
18
18
|
| `tier2` | A bounded change or investigation: any code, configuration or CI edit (a rename, a value, a revert), running tests or a build, filing an issue, explaining code that must be read first, most bug fixes, a focused review or benchmark, planning or synthesis that produces documents (phase plans, an ADR, an overview), and answers that settle open decisions for work in progress | "rename tmp to buffer", "run npm test", "the CLI fails with this error, fix it", "1. agree 2. keep the old name" |
|
|
19
|
-
| `tier3` |
|
|
19
|
+
| `tier3` | Work that needs several agents (sub-agents included); a new module or subsystem, a refactor, or a change to a framework or interface definition; or code or design work that spans several repositories or several workflows | "add a plugin system to the CLI", "refactor the parser into modules", "change the plugin interface", "dispatch agents to audit every repo" |
|
|
20
20
|
| `null` | No actionable content: a bare continuation, "do what you said", a vague reaction, a question about what the assistant meant, or pasted status with no request | "go", "yes", "照剛剛說的改", "something is off here" |
|
|
21
21
|
|
|
22
22
|
Rules:
|
|
@@ -31,6 +31,30 @@ Rules:
|
|
|
31
31
|
reformat or extend the assistant's previous answer without changing files is
|
|
32
32
|
`tier1`. A requested change to code or configuration, however small, is at
|
|
33
33
|
least `tier2`. Only the smallest doc fixes listed in the table stay `tier1`.
|
|
34
|
+
The line between `tier2` and `tier3` is the owner's: `tier3` when the work
|
|
35
|
+
needs several agents or sub-agents, adds a feature, refactors, changes a
|
|
36
|
+
framework or interface definition, or spans several repositories or
|
|
37
|
+
workflows. Fixing, adjusting, investigating or reviewing existing behavior
|
|
38
|
+
within one workflow is `tier2`.
|
|
39
|
+
The owner settled four more lines from the third spot-check:
|
|
40
|
+
- **Git is `tier1` at any width.** Committing sub-repositories and then the
|
|
41
|
+
main repository is still housekeeping. "Several repositories" applies to
|
|
42
|
+
code or design work only.
|
|
43
|
+
- **Scope, not the word "add".** Adding an option, a function or a parser
|
|
44
|
+
inside one existing tool or component is `tier2`. A new module or
|
|
45
|
+
subsystem, or an addition that spans several components, is `tier3`.
|
|
46
|
+
A bug fix, even with a regression test, is `tier2`.
|
|
47
|
+
- **Repository-wide or cross-component work is `tier3`.** Replacing or
|
|
48
|
+
unifying a pattern across the repository (every `console.log`, all error
|
|
49
|
+
handling, every path in a report), upgrading a dependency and fixing what
|
|
50
|
+
breaks, a data migration, a CI matrix across platforms, or restructuring a
|
|
51
|
+
documentation tree is `tier3`, even when each edit is small.
|
|
52
|
+
- **A short reply follows the work in progress.** A reply that asks to
|
|
53
|
+
change an output (code, a document, an example) is `tier2`. Only a pure
|
|
54
|
+
question or a bare acknowledgement stays `tier1`.
|
|
55
|
+
- **Explicit agents or architecture make `tier3`.** A request for several
|
|
56
|
+
agents, a team discussion or a verifier pass, or one that redefines an
|
|
57
|
+
architecture, is `tier3` even when it is phrased as discussion.
|
|
34
58
|
4. Explicit workflow words ("use fable", "no subagents") do not change the gold.
|
|
35
59
|
Precedence is a router policy, not a label.
|
|
36
60
|
5. Never derive gold from the lexical router or any model output. A reviewer may
|
|
@@ -102,6 +126,10 @@ a decision on its own.
|
|
|
102
126
|
| `benchmarks/fixtures/system-one-holdout.json` | Evaluation corpus, rebuilt with `node scripts/system-one-corpus.js build <draft> <reviews> <corpus>` |
|
|
103
127
|
|
|
104
128
|
The reviewed holdout has 215 cases (11 rejected): en 93 and zh-TW 122; gold
|
|
105
|
-
`tier1`
|
|
106
|
-
gate.
|
|
129
|
+
`tier1` 48, `tier2` 104, `tier3` 43 and `null` 20. It meets the `reviewedHoldout`
|
|
130
|
+
gate. After the third training spot-check the owner moved nine cases to the new
|
|
131
|
+
lines: `h-long-git-ops-1` to `tier1`, and the `h-add-cli-flag-*`,
|
|
132
|
+
`h-hash-algorithm-support-1/2`, `h-fix-cli-error-log-3/4` and
|
|
133
|
+
`h-fix-failing-test-3` cases to `tier2`. Results recorded before that change
|
|
134
|
+
used 47 `tier1`, 97 `tier2` and 51 `tier3`. It says nothing about model quality until a `harness-routing-v1`
|
|
107
135
|
checkpoint is evaluated on it.
|