harness-everything 0.21.0 → 0.22.1

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 (64) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +18 -0
  4. package/README.md +30 -0
  5. package/benchmarks/results/system-one/cua-s1-forms-resident-async-cpu-2026-09-23/README.md +87 -0
  6. package/benchmarks/results/system-one/cua-s1-forms-resident-async-cpu-2026-09-23/paired-latency.json +107 -0
  7. package/benchmarks/results/system-one/cua-s1-forms-resident-async-cpu-2026-09-23/report.json +856 -0
  8. package/benchmarks/results/system-one/cua-s1-forms-resident-cpu-2026-09-23/README.md +74 -0
  9. package/benchmarks/results/system-one/cua-s1-forms-resident-cpu-2026-09-23/report.json +856 -0
  10. package/benchmarks/results/system-one/pre-merge-review-2026-09-23/README.md +92 -0
  11. package/benchmarks/results/system-one/pre-merge-review-2026-09-23/haiku-spec-conformance.md +241 -0
  12. package/benchmarks/results/system-one/pre-merge-review-2026-09-23/luna-adversarial.md +212 -0
  13. package/benchmarks/results/system-one/pre-merge-review-2026-09-23/skill-top1-probe.js +83 -0
  14. package/benchmarks/results/system-one/pre-merge-review-2026-09-23/skill-top1-probe.json +7700 -0
  15. package/ci/fixtures/system-one-resident-stub.py +28 -0
  16. package/ci/fixtures/system-one-worker-probe.js +15 -0
  17. package/ci/mechanism-packaging-bytecode.test.js +61 -0
  18. package/ci/mechanism-system-one-install.test.js +11 -0
  19. package/ci/mechanism-system-one-resident.test.js +296 -0
  20. package/ci/mechanism-system-one-router.test.js +25 -0
  21. package/ci/system-one-adapter-test.py +166 -0
  22. package/docs/platform-capabilities.md +8 -0
  23. package/docs/system-one-routing.md +91 -3
  24. package/evals/pilot-router-nonsoftware/graders/no-tier-language.md +6 -0
  25. package/evals/pilot-router-nonsoftware/graders/skill-not-fired.md +9 -0
  26. package/evals/pilot-router-nonsoftware/prompt.md +8 -0
  27. package/evals/pilot-router-tier3/graders/skill-fired.md +6 -0
  28. package/evals/pilot-router-tier3/prompt.md +8 -0
  29. package/evals/pilot-tdd-bugfix/graders/skill-fired.md +6 -0
  30. package/evals/pilot-tdd-bugfix/prompt.md +8 -0
  31. package/evals/pilot-tdd-trivia/graders/no-red-phase-claim.md +7 -0
  32. package/evals/pilot-tdd-trivia/graders/skill-not-fired.md +9 -0
  33. package/evals/pilot-tdd-trivia/prompt.md +8 -0
  34. package/evals/pilot-verify-discussion/graders/no-verification-claim.md +7 -0
  35. package/evals/pilot-verify-discussion/graders/skill-not-fired.md +9 -0
  36. package/evals/pilot-verify-discussion/prompt.md +8 -0
  37. package/evals/pilot-verify-preship/graders/skill-fired.md +6 -0
  38. package/evals/pilot-verify-preship/prompt.md +8 -0
  39. package/harness-everything/SKILL.md +1 -1
  40. package/harness-everything/scripts/system-one/cua_adapter.py +265 -6
  41. package/harness-everything/scripts/system-one/install.js +17 -8
  42. package/harness-everything/scripts/system-one/provider.js +18 -3
  43. package/harness-everything/scripts/system-one/resident.js +200 -0
  44. package/harness-everything/scripts/system-one/router.js +18 -2
  45. package/harness-everything/scripts/tier-router.js +13 -4
  46. package/opencode-plugin/plugin.json +1 -1
  47. package/package.json +1 -1
  48. package/plugins/harness-everything/.codex-plugin/plugin.json +1 -1
  49. package/plugins/harness-everything/plugin.json +1 -1
  50. package/plugins/harness-everything/scripts/lib/packaging-noise.js +6 -0
  51. package/plugins/harness-everything/scripts/lib/skills.js +2 -0
  52. package/plugins/harness-everything/skills/harness-everything/SKILL.md +1 -1
  53. package/plugins/harness-everything/skills/harness-everything/scripts/system-one/cua_adapter.py +265 -6
  54. package/plugins/harness-everything/skills/harness-everything/scripts/system-one/install.js +17 -8
  55. package/plugins/harness-everything/skills/harness-everything/scripts/system-one/provider.js +18 -3
  56. package/plugins/harness-everything/skills/harness-everything/scripts/system-one/resident.js +200 -0
  57. package/plugins/harness-everything/skills/harness-everything/scripts/system-one/router.js +18 -2
  58. package/plugins/harness-everything/skills/harness-everything/scripts/tier-router.js +13 -4
  59. package/sbom.cdx.json +7 -7
  60. package/scripts/build-openai-submission.js +2 -0
  61. package/scripts/evaluate-system-one.js +18 -9
  62. package/scripts/lib/packaging-noise.js +6 -0
  63. package/scripts/lib/skills.js +2 -0
  64. package/scripts/sync-openai-plugin.js +2 -1
@@ -0,0 +1,28 @@
1
+ """Stub scorer behind the real resident server code; never model-quality evidence."""
2
+ import importlib.util
3
+ from pathlib import Path
4
+ import sys
5
+ import time
6
+
7
+ sys.dont_write_bytecode = True # never leave __pycache__ in the source tree that packaging copies
8
+ path = Path(__file__).resolve().parents[2] / 'harness-everything/scripts/system-one/cua_adapter.py'
9
+ spec = importlib.util.spec_from_file_location('adapter', path)
10
+ adapter = importlib.util.module_from_spec(spec)
11
+ spec.loader.exec_module(adapter)
12
+
13
+
14
+ def factory(weights, manifest):
15
+ if manifest['modelId'] == 'stub-fail':
16
+ raise ValueError('load-failed')
17
+
18
+ def score(request):
19
+ if manifest['modelId'] == 'stub-slow':
20
+ time.sleep(3)
21
+ return [1.0] + [0.0] * (len(request['options']) - 1)
22
+ return score, {'context_tokens': 224, 'option_tokens': 96}
23
+
24
+
25
+ if __name__ == '__main__':
26
+ if sys.argv[1:2] != ['--serve']:
27
+ sys.exit(2)
28
+ sys.exit(adapter.serve_main(sys.argv[2:], scorer_factory=factory))
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+ // Preload (NODE_OPTIONS --require) that proves which System One client path ran.
3
+ // HARNESS_TEST_WORKER_MODE=deny makes every worker thread fail to start; =count records
4
+ // how many were started into HARNESS_TEST_WORKER_COUNT_FILE when the process exits.
5
+ const fs = require('node:fs');
6
+ const threads = require('node:worker_threads');
7
+ const mode = process.env.HARNESS_TEST_WORKER_MODE;
8
+ const Original = threads.Worker;
9
+ let count = 0;
10
+ if (mode === 'deny') {
11
+ threads.Worker = class { constructor() { throw new Error('worker-disabled-by-test'); } };
12
+ } else if (mode === 'count') {
13
+ threads.Worker = class extends Original { constructor(...args) { count += 1; super(...args); } };
14
+ process.on('exit', () => fs.writeFileSync(process.env.HARNESS_TEST_WORKER_COUNT_FILE, String(count)));
15
+ }
@@ -0,0 +1,61 @@
1
+ 'use strict';
2
+ // Python bytecode written by local/CI test runs is an untracked build artifact; no distribution may ship it.
3
+ const { test } = require('node:test');
4
+ const assert = require('node:assert/strict');
5
+ const fs = require('node:fs');
6
+ const os = require('node:os');
7
+ const path = require('node:path');
8
+ const { spawnSync } = require('node:child_process');
9
+ const { copyDir } = require('../scripts/lib/skills');
10
+ const { filesUnder } = require('../scripts/build-openai-submission');
11
+ const root = path.resolve(__dirname, '..');
12
+ const noise = files => files.filter(f => /(^|[\\/])__pycache__([\\/]|$)|\.py[co]$/.test(f));
13
+
14
+ function plant(dir) {
15
+ fs.mkdirSync(path.join(dir, '__pycache__'), { recursive: true });
16
+ fs.writeFileSync(path.join(dir, '__pycache__', 'cua_adapter.cpython-313.pyc'), 'bytecode');
17
+ fs.writeFileSync(path.join(dir, 'stray.pyc'), 'bytecode');
18
+ fs.writeFileSync(path.join(dir, 'keep.py'), 'print(1)\n');
19
+ }
20
+
21
+ test('PK-01 skills installer copy and submission file walk skip Python bytecode', () => {
22
+ const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-pk-'));
23
+ try {
24
+ const src = path.join(tmp, 'src', 'scripts');
25
+ plant(src);
26
+ copyDir(path.join(tmp, 'src'), path.join(tmp, 'dest'));
27
+ const copied = filesUnder(path.join(tmp, 'dest'));
28
+ assert.deepEqual(noise(copied), []);
29
+ assert.ok(copied.includes('scripts/keep.py'));
30
+ const walked = filesUnder(path.join(tmp, 'src'));
31
+ assert.deepEqual(noise(walked), []);
32
+ assert.deepEqual(walked, ['scripts/keep.py']);
33
+ } finally { fs.rmSync(tmp, { recursive: true, force: true }); }
34
+ });
35
+
36
+ test('PK-02 plugin sync does not mirror bytecode from the canonical tree', () => {
37
+ const canonical = path.join(root, 'harness-everything', 'scripts', 'system-one');
38
+ const planted = [path.join(canonical, '__pycache__', 'cua_adapter.cpython-313.pyc'), path.join(canonical, 'stray.pyc')];
39
+ const hadCache = fs.existsSync(path.join(canonical, '__pycache__'));
40
+ try {
41
+ fs.mkdirSync(path.join(canonical, '__pycache__'), { recursive: true });
42
+ for (const file of planted) fs.writeFileSync(file, 'bytecode');
43
+ const sync = spawnSync(process.execPath, [path.join(root, 'scripts', 'sync-openai-plugin.js')], { cwd: root, encoding: 'utf8' });
44
+ assert.equal(sync.status, 0, sync.stderr);
45
+ const mirror = path.join(root, 'plugins', 'harness-everything', 'skills', 'harness-everything', 'scripts', 'system-one');
46
+ assert.deepEqual(noise(filesUnder(mirror)), []);
47
+ assert.equal(fs.existsSync(path.join(mirror, '__pycache__')), false);
48
+ } finally {
49
+ for (const file of planted) fs.rmSync(file, { force: true });
50
+ if (!hadCache) fs.rmSync(path.join(canonical, '__pycache__'), { recursive: true, force: true });
51
+ }
52
+ });
53
+
54
+ test('PK-03 Python tests do not write bytecode into the source tree', () => {
55
+ const canonical = path.join(root, 'harness-everything', 'scripts', 'system-one');
56
+ fs.rmSync(path.join(canonical, '__pycache__'), { recursive: true, force: true });
57
+ const python = process.env.PYTHON || (process.platform === 'win32' ? 'python' : 'python3');
58
+ const run = spawnSync(python, [path.join(__dirname, 'system-one-adapter-test.py')], { encoding: 'utf8', env: { ...process.env, PYTHONDONTWRITEBYTECODE: '' } });
59
+ assert.equal(run.status, 0, run.stderr);
60
+ assert.equal(fs.existsSync(path.join(canonical, '__pycache__')), false);
61
+ });
@@ -28,6 +28,7 @@ test('S1-I01 pins stay consistent with the provider contract', () => {
28
28
  assert.equal(manifest.checkpoint, path.join(dir, 'checkpoints', PINS.modelRevision, PINS.files.weights.name));
29
29
  assert.equal(manifest.weightsSha256, PINS.files.weights.sha256); assert.equal(manifest.configSha256, PINS.files.config.sha256);
30
30
  assert.equal(manifest.revision, PINS.modelRevision); assert.equal(manifest.timeoutMs, 10000);
31
+ assert.equal(manifest.transport, 'resident'); assert.equal(manifest.idleTimeoutMs, 1800000);
31
32
  });
32
33
 
33
34
  test('S1-I02 interpreter selection accepts only the upstream-supported Python range', () => {
@@ -76,6 +77,16 @@ test('S1-I04 downloads are verified before an atomic write; a valid file is reus
76
77
  } finally { fs.rmSync(dir, { recursive: true, force: true }); }
77
78
  });
78
79
 
80
+ test('S1-I06 child command output goes to stderr so stdout stays machine-readable JSON', () => {
81
+ const code = `require(${JSON.stringify(script)}).exec(process.execPath, ['-e', 'console.log("pip-noise")'])`;
82
+ const child = spawnSync(process.execPath, ['-e', code], { encoding: 'utf8' });
83
+ assert.equal(child.status, 0, child.stderr);
84
+ assert.equal(child.stdout, '');
85
+ assert.match(child.stderr, /pip-noise/);
86
+ const captured = spawnSync(process.execPath, ['-e', `process.stdout.write(require(${JSON.stringify(script)}).exec(process.execPath, ['-e', 'console.log("3.13.6")'], true))`], { encoding: 'utf8' });
87
+ assert.equal(captured.stdout, '3.13.6');
88
+ });
89
+
79
90
  test('S1-I05 dry run prints the pinned plan and changes nothing, repeatably', () => {
80
91
  const dir = path.join(fs.mkdtempSync(path.join(os.tmpdir(), 'harness-s1-dry-')), 'target');
81
92
  try {
@@ -0,0 +1,296 @@
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 resident = require('../harness-everything/scripts/system-one/resident');
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 python = process.env.PYTHON || (process.platform === 'win32' ? 'python' : 'python3');
14
+ const stub = path.join(__dirname, 'fixtures/system-one-resident-stub.py');
15
+ const request = createRequest('tier', 'fix a typo in README', TIER_OPTIONS);
16
+ const sha = file => createHash('sha256').update(fs.readFileSync(file)).digest('hex');
17
+ const sleep = ms => Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
18
+
19
+ function fixture(modelId = 'stub') {
20
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-s1-resident-'));
21
+ const checkpoint = path.join(dir, 'model.safetensors');
22
+ fs.writeFileSync(checkpoint, 'synthetic-not-real-weights');
23
+ fs.writeFileSync(path.join(dir, 'model.json'), '{}');
24
+ const manifest = { schemaVersion: 1, python, checkpoint, weightsSha256: sha(checkpoint), configSha256: sha(path.join(dir, 'model.json')),
25
+ modelId, revision: 'v1', domain: 'harness-routing-v1', transport: 'resident', idleTimeoutMs: 60000 };
26
+ const manifestPath = path.join(dir, 'manifest.json');
27
+ fs.writeFileSync(manifestPath, JSON.stringify(manifest));
28
+ const spawns = [];
29
+ const deps = { command: m => { spawns.push(m.modelId); return [python, [stub, '--serve']]; } };
30
+ return { dir, manifest, manifestPath, spawns, deps };
31
+ }
32
+ function cleanup(f) {
33
+ try { resident.stop(f.manifest, f.manifestPath); } catch (_) { /* best effort */ }
34
+ fs.rmSync(f.dir, { recursive: true, force: true });
35
+ }
36
+ // A client view whose state file names the live server with a wrong token. The server polls only its own
37
+ // state file and exits once that file stops naming it, so rewriting it would race the wrong-token request.
38
+ function wrongTokenView(f) {
39
+ const good = JSON.parse(fs.readFileSync(resident.stateFiles(f.manifest, f.manifestPath).state, 'utf8'));
40
+ const viewDir = fs.mkdtempSync(path.join(f.dir, 'client-view-'));
41
+ const manifestPath = path.join(viewDir, 'manifest.json');
42
+ fs.writeFileSync(manifestPath, JSON.stringify(f.manifest));
43
+ fs.writeFileSync(resident.stateFiles(f.manifest, manifestPath).state, JSON.stringify({ ...good, token: 'b'.repeat(64) }));
44
+ return manifestPath;
45
+ }
46
+
47
+ test('S1-RS01 manifest transport fields and digest-bound file names', () => {
48
+ const f = fixture();
49
+ try {
50
+ assert.equal(provider.validateManifest(f.manifest), true);
51
+ for (const change of [{ transport: 'oneshot' }, { idleTimeoutMs: 60000 }, { idleTimeoutMs: 14400000 }]) assert.equal(provider.validateManifest({ ...f.manifest, ...change }), true);
52
+ for (const change of [{ transport: 'daemon' }, { transport: '' }, { idleTimeoutMs: 59999 }, { idleTimeoutMs: 14400001 }, { idleTimeoutMs: '60000' }]) {
53
+ assert.throws(() => provider.validateManifest({ ...f.manifest, ...change }));
54
+ }
55
+ const files = resident.stateFiles(f.manifest, f.manifestPath);
56
+ const digest = createHash('sha256').update(JSON.stringify(f.manifest)).digest('hex').slice(0, 16);
57
+ assert.equal(files.state, path.join(f.dir, `system-one-resident-${digest}.json`));
58
+ assert.equal(files.lock, path.join(f.dir, `system-one-resident-${digest}.starting`));
59
+ assert.notEqual(resident.stateFiles({ ...f.manifest, revision: 'v2' }, f.manifestPath).state, files.state);
60
+ } finally { cleanup(f); }
61
+ });
62
+
63
+ test('S1-RS02 cold start never blocks, spawns once, then serves warm repeatable scores', () => {
64
+ const f = fixture();
65
+ try {
66
+ assert.deepEqual(resident.score(request, f.manifest, f.manifestPath, f.deps), { status: 'unavailable', reason: 'provider-starting' });
67
+ assert.deepEqual(resident.score(request, f.manifest, f.manifestPath, f.deps), { status: 'unavailable', reason: 'provider-starting' });
68
+ assert.deepEqual(f.spawns, ['stub']);
69
+ assert.equal(resident.ensureReady(f.manifest, f.manifestPath, 20000, f.deps), true);
70
+ assert.equal(f.spawns.length, 1);
71
+ const one = resident.score(request, f.manifest, f.manifestPath, f.deps);
72
+ const two = resident.score(request, f.manifest, f.manifestPath, f.deps);
73
+ assert.equal(one.status, 'scored'); assert.deepEqual(one, two);
74
+ assert.equal(decide(request, one.response).selectedId, 'tier1');
75
+ assert.equal(resident.status(f.manifest, f.manifestPath).running, true);
76
+ assert.equal(resident.stop(f.manifest, f.manifestPath), true);
77
+ const deadline = Date.now() + 5000;
78
+ while (fs.existsSync(resident.stateFiles(f.manifest, f.manifestPath).state) && Date.now() < deadline) sleep(50);
79
+ assert.equal(resident.status(f.manifest, f.manifestPath).running, false);
80
+ } finally { cleanup(f); }
81
+ });
82
+
83
+ test('S1-RS03 stale state is removed and replaced; a wrong token is rejected without respawn', () => {
84
+ const f = fixture();
85
+ try {
86
+ const { state } = resident.stateFiles(f.manifest, f.manifestPath);
87
+ const dead = spawnSync(process.execPath, ['-e', '0']).pid;
88
+ fs.writeFileSync(state, JSON.stringify({ schemaVersion: 1, pid: dead, port: 9, token: 'a'.repeat(64), startedAt: 1 }));
89
+ assert.deepEqual(resident.score(request, f.manifest, f.manifestPath, f.deps), { status: 'unavailable', reason: 'provider-starting' });
90
+ assert.equal(f.spawns.length, 1);
91
+ assert.equal(resident.ensureReady(f.manifest, f.manifestPath, 20000, f.deps), true);
92
+ const good = JSON.parse(fs.readFileSync(state, 'utf8'));
93
+ assert.deepEqual(resident.score(request, f.manifest, wrongTokenView(f), f.deps), { status: 'unavailable', reason: 'provider-unavailable' });
94
+ assert.equal(f.spawns.length, 1);
95
+ assert.equal(resident.status(f.manifest, f.manifestPath).running, true, 'a wrong token does not stop the server');
96
+ for (const bad of ['not-json', JSON.stringify({ ...good, extra: 1 }), JSON.stringify({ ...good, token: 'short' })]) {
97
+ fs.writeFileSync(state, bad);
98
+ assert.equal(resident.status(f.manifest, f.manifestPath).running, false);
99
+ }
100
+ fs.writeFileSync(state, JSON.stringify(good));
101
+ } finally { cleanup(f); }
102
+ });
103
+
104
+ test('S1-RS04 a slow server times out within the deadline and is not respawned', () => {
105
+ const f = fixture('stub-slow');
106
+ try {
107
+ assert.equal(resident.ensureReady(f.manifest, f.manifestPath, 20000, f.deps), true);
108
+ const start = Date.now();
109
+ assert.deepEqual(resident.score(request, f.manifest, f.manifestPath, f.deps), { status: 'unavailable', reason: 'provider-timeout' });
110
+ assert.ok(Date.now() - start < 2500);
111
+ assert.equal(f.spawns.length, 1);
112
+ } finally { cleanup(f); }
113
+ });
114
+
115
+ test('S1-RS05 startup failure is visible and throttled instead of respawning every prompt', () => {
116
+ const f = fixture('stub-fail');
117
+ try {
118
+ assert.equal(resident.score(request, f.manifest, f.manifestPath, f.deps).reason, 'provider-starting');
119
+ assert.equal(resident.ensureReady(f.manifest, f.manifestPath, 20000, f.deps), false);
120
+ const lock = JSON.parse(fs.readFileSync(resident.stateFiles(f.manifest, f.manifestPath).lock, 'utf8'));
121
+ assert.equal(lock.failed, 'load-failed');
122
+ assert.deepEqual(resident.score(request, f.manifest, f.manifestPath, f.deps), { status: 'unavailable', reason: 'provider-unavailable' });
123
+ assert.equal(f.spawns.length, 1);
124
+ } finally { cleanup(f); }
125
+ });
126
+
127
+ test('S1-RS06 provider dispatch uses the real adapter and reports a missing ML runtime', () => {
128
+ const f = fixture();
129
+ try {
130
+ assert.deepEqual(provider.score(request, f.manifestPath), { status: 'unavailable', reason: 'provider-starting' });
131
+ const { lock } = resident.stateFiles(f.manifest, f.manifestPath);
132
+ const deadline = Date.now() + 20000;
133
+ while (Date.now() < deadline && !(fs.existsSync(lock) && JSON.parse(fs.readFileSync(lock, 'utf8')).failed)) sleep(100);
134
+ const probe = spawnSync(python, ['-c', 'import torch, cua_s1'], { encoding: 'utf8' });
135
+ if (probe.status !== 0) {
136
+ assert.equal(JSON.parse(fs.readFileSync(lock, 'utf8')).failed, 'load-failed');
137
+ assert.deepEqual(provider.score(request, f.manifestPath), { status: 'unavailable', reason: 'provider-unavailable' });
138
+ }
139
+ const off = { ...f.manifest, transport: 'oneshot' };
140
+ fs.writeFileSync(f.manifestPath, JSON.stringify(off));
141
+ assert.notEqual(provider.score(request, f.manifestPath).reason, 'provider-starting');
142
+ } finally { cleanup(f); }
143
+ });
144
+
145
+ test('S1-RS07 operator CLI reports status and stops a running server', () => {
146
+ const f = fixture();
147
+ try {
148
+ const cli = args => spawnSync(process.execPath, [path.join(__dirname, '../harness-everything/scripts/system-one/resident.js'), ...args], { encoding: 'utf8' });
149
+ assert.equal(JSON.parse(cli(['status', f.manifestPath]).stdout).running, false);
150
+ assert.equal(resident.ensureReady(f.manifest, f.manifestPath, 20000, f.deps), true);
151
+ const running = JSON.parse(cli(['status', f.manifestPath]).stdout);
152
+ assert.equal(running.running, true); assert.ok(!JSON.stringify(running).includes('token'));
153
+ assert.equal(cli(['stop', f.manifestPath]).status, 0);
154
+ const deadline = Date.now() + 5000;
155
+ while (JSON.parse(cli(['status', f.manifestPath]).stdout).running && Date.now() < deadline) sleep(50);
156
+ assert.equal(JSON.parse(cli(['status', f.manifestPath]).stdout).running, false);
157
+ assert.equal(cli(['bogus', f.manifestPath]).status, 2);
158
+ assert.equal(cli(['status', 'relative.json']).status, 2);
159
+ } finally { cleanup(f); }
160
+ });
161
+
162
+ test('S1-RS08 an executable that cannot spawn is recorded as a visible, throttled failure', () => {
163
+ const f = fixture();
164
+ try {
165
+ const missing = path.join(f.dir, 'no-such-python.exe');
166
+ const deps = { command: () => { f.spawns.push('missing'); return [missing, []]; } };
167
+ assert.deepEqual(resident.score(request, f.manifest, f.manifestPath, deps), { status: 'unavailable', reason: 'provider-unavailable' });
168
+ assert.equal(JSON.parse(fs.readFileSync(resident.stateFiles(f.manifest, f.manifestPath).lock, 'utf8')).failed, 'spawn-failed');
169
+ assert.deepEqual(resident.score(request, f.manifest, f.manifestPath, deps), { status: 'unavailable', reason: 'provider-unavailable' });
170
+ assert.equal(resident.ensureReady(f.manifest, f.manifestPath, 2000, deps), false);
171
+ assert.deepEqual(f.spawns, ['missing']);
172
+ } finally { cleanup(f); }
173
+ });
174
+
175
+ test('S1-RS09 a corrupted state file never leaves an orphan server behind', () => {
176
+ const f = fixture();
177
+ try {
178
+ assert.equal(resident.ensureReady(f.manifest, f.manifestPath, 20000, f.deps), true);
179
+ const { state } = resident.stateFiles(f.manifest, f.manifestPath);
180
+ const old = JSON.parse(fs.readFileSync(state, 'utf8'));
181
+ fs.writeFileSync(state, 'corrupt');
182
+ assert.equal(resident.ensureReady(f.manifest, f.manifestPath, 20000, f.deps), true);
183
+ const fresh = JSON.parse(fs.readFileSync(state, 'utf8'));
184
+ assert.notEqual(fresh.pid, old.pid);
185
+ // "Stopped serving" is the contract. On POSIX an exited child stays a zombie (kill(pid, 0) succeeds)
186
+ // until this blocked test process reaps it, so a refused/failed ping also proves the server is gone.
187
+ const alive = pid => { try { process.kill(pid, 0); return true; } catch (e) { return e.code === 'EPERM'; } };
188
+ const serving = () => alive(old.pid) && resident.callSync(old.port, { token: old.token, op: 'ping' }).reply?.ok === true;
189
+ const deadline = Date.now() + 5000;
190
+ while (serving() && Date.now() < deadline) sleep(100);
191
+ assert.equal(serving(), false);
192
+ assert.equal(resident.status(f.manifest, f.manifestPath).pid, fresh.pid);
193
+ } finally { cleanup(f); }
194
+ });
195
+
196
+ test('S1-RS10 scoreAsync matches the sync client and keeps every start/failure mapping', async () => {
197
+ const f = fixture();
198
+ try {
199
+ assert.deepEqual(await resident.scoreAsync(request, f.manifest, f.manifestPath, f.deps), { status: 'unavailable', reason: 'provider-starting' });
200
+ assert.deepEqual(await resident.scoreAsync(request, f.manifest, f.manifestPath, f.deps), { status: 'unavailable', reason: 'provider-starting' });
201
+ assert.deepEqual(f.spawns, ['stub']);
202
+ assert.equal(resident.ensureReady(f.manifest, f.manifestPath, 20000, f.deps), true);
203
+ const sync = resident.score(request, f.manifest, f.manifestPath, f.deps);
204
+ assert.equal(sync.status, 'scored');
205
+ assert.deepEqual(await resident.scoreAsync(request, f.manifest, f.manifestPath, f.deps), sync);
206
+ assert.deepEqual(await resident.scoreAsync(request, f.manifest, f.manifestPath, f.deps), sync);
207
+ assert.deepEqual(await resident.scoreAsync(request, f.manifest, wrongTokenView(f), f.deps), { status: 'unavailable', reason: 'provider-unavailable' });
208
+ await assert.rejects(resident.scoreAsync({ ...request, extra: 1 }, f.manifest, f.manifestPath, f.deps));
209
+ assert.equal(f.spawns.length, 1);
210
+ } finally { cleanup(f); }
211
+ });
212
+
213
+ test('S1-RS10b scoreAsync removes refused state, restarts once, and times out slow servers', async () => {
214
+ const f = fixture();
215
+ // A live PID that is not this test process: cleanup may kill whatever the state file names.
216
+ const sleeper = require('node:child_process').spawn(process.execPath, ['-e', 'setTimeout(() => {}, 60000)'], { stdio: 'ignore' });
217
+ try {
218
+ const net = require('node:net');
219
+ const closed = net.createServer();
220
+ await new Promise(resolve => closed.listen(0, '127.0.0.1', resolve));
221
+ const port = closed.address().port;
222
+ await new Promise(resolve => closed.close(resolve));
223
+ const { state } = resident.stateFiles(f.manifest, f.manifestPath);
224
+ fs.writeFileSync(state, JSON.stringify({ schemaVersion: 1, pid: sleeper.pid, port, token: 'a'.repeat(64), startedAt: 1 }));
225
+ assert.deepEqual(await resident.scoreAsync(request, f.manifest, f.manifestPath, f.deps), { status: 'unavailable', reason: 'provider-starting' });
226
+ assert.deepEqual(f.spawns, ['stub']);
227
+ } finally { sleeper.kill(); cleanup(f); }
228
+ const slow = fixture('stub-slow');
229
+ try {
230
+ assert.equal(resident.ensureReady(slow.manifest, slow.manifestPath, 20000, slow.deps), true);
231
+ const start = Date.now();
232
+ assert.deepEqual(await resident.scoreAsync(request, slow.manifest, slow.manifestPath, slow.deps), { status: 'unavailable', reason: 'provider-timeout' });
233
+ assert.ok(Date.now() - start < 2500);
234
+ assert.equal(slow.spawns.length, 1);
235
+ } finally { cleanup(slow); }
236
+ });
237
+
238
+ test('S1-RS10c provider.scoreAsync dispatches by transport with the sync result shapes', async () => {
239
+ const f = fixture();
240
+ try {
241
+ assert.deepEqual(await provider.scoreAsync(request, path.join(f.dir, 'missing.json')), { status: 'unavailable', reason: 'provider-config' });
242
+ assert.deepEqual(await provider.scoreAsync(request, 'relative.json'), { status: 'unavailable', reason: 'provider-config' });
243
+ assert.equal(resident.ensureReady(f.manifest, f.manifestPath, 20000, f.deps), true);
244
+ assert.deepEqual(await provider.scoreAsync(request, f.manifestPath), provider.score(request, f.manifestPath));
245
+ const oneshot = path.join(f.dir, 'oneshot.json');
246
+ fs.writeFileSync(oneshot, JSON.stringify({ ...f.manifest, transport: 'oneshot' }));
247
+ assert.deepEqual(await provider.scoreAsync(request, oneshot), provider.score(request, oneshot));
248
+ } finally { cleanup(f); }
249
+ });
250
+
251
+ // The probe preload proves which client path ran inside a real child process.
252
+ const probeEnv = (mode, extra = {}) => ({ ...process.env,
253
+ NODE_OPTIONS: `${process.env.NODE_OPTIONS || ''} --require ./ci/fixtures/system-one-worker-probe.js`.trim(),
254
+ HARNESS_TEST_WORKER_MODE: mode, ...extra });
255
+
256
+ test('S1-RS11 the hook entry pre-scores over async IPC: it still scores when worker threads cannot start', () => {
257
+ const f = fixture();
258
+ const root = path.resolve(__dirname, '..');
259
+ try {
260
+ assert.equal(resident.ensureReady(f.manifest, f.manifestPath, 20000, f.deps), true);
261
+ const env = probeEnv('deny', { HARNESS_SYSTEM_ONE_MODE: 'shadow', HARNESS_SYSTEM_ONE_CONFIG: f.manifestPath });
262
+ const kernel = path.join(root, 'harness-everything/scripts/kernel-router-core.js');
263
+ const diagnostic = out => JSON.parse(out.match(/=> SYSTEM ONE: (.*)/)[1]);
264
+ const argv = spawnSync(process.execPath, [kernel, 'fix a typo in README'], { cwd: root, encoding: 'utf8', env });
265
+ assert.equal(argv.status, 0, argv.stderr);
266
+ assert.equal(diagnostic(argv.stdout).status, 'accepted');
267
+ const hook = spawnSync(process.execPath, [kernel], { cwd: root, encoding: 'utf8', env, input: JSON.stringify({ prompt: 'fix a typo in README' }) });
268
+ assert.equal(hook.status, 0, hook.stderr);
269
+ assert.equal(diagnostic(hook.stdout).status, 'accepted');
270
+ const off = spawnSync(process.execPath, [kernel, 'fix a typo in README'], { cwd: root, encoding: 'utf8', env: { ...env, HARNESS_SYSTEM_ONE_MODE: 'off' } });
271
+ assert.equal(off.status, 0, off.stderr);
272
+ assert.doesNotMatch(off.stdout, /SYSTEM ONE/);
273
+ assert.equal(f.spawns.length, 1);
274
+ } finally { cleanup(f); }
275
+ });
276
+
277
+ test('S1-RS12 the evaluator times the async path: no worker thread per warm score', () => {
278
+ const f = fixture();
279
+ const root = path.resolve(__dirname, '..');
280
+ try {
281
+ assert.equal(resident.ensureReady(f.manifest, f.manifestPath, 20000, f.deps), true);
282
+ const countFile = path.join(f.dir, 'workers.txt');
283
+ const output = path.join(f.dir, 'report.json');
284
+ const corpus = path.join(root, 'benchmarks/fixtures/system-one-routing.json');
285
+ const child = spawnSync(process.execPath, [path.join(root, 'scripts/evaluate-system-one.js'), corpus, f.manifestPath, output],
286
+ { cwd: root, encoding: 'utf8', env: probeEnv('count', { HARNESS_TEST_WORKER_COUNT_FILE: countFile }) });
287
+ assert.equal(child.status, 0, child.stderr);
288
+ const report = JSON.parse(fs.readFileSync(output, 'utf8'));
289
+ assert.equal(report.evidence.residentReady, true);
290
+ // Every sample reached the warm server (the seed's one over-limit context is a declined provider-exit).
291
+ const runs = report.records.flatMap(r => r.runs);
292
+ assert.ok(runs.every(run => run.coldStart === false && ['accepted', 'provider-exit'].includes(run.decision.status === 'accepted' ? 'accepted' : run.decision.reason)));
293
+ assert.ok(runs.filter(run => run.decision.status === 'accepted').length >= runs.length - 2);
294
+ assert.ok(Number(fs.readFileSync(countFile, 'utf8')) < report.records.length * 2, 'warm scores must not start a worker thread each');
295
+ } finally { cleanup(f); }
296
+ });
@@ -99,3 +99,28 @@ test('S1-R05 structural floor: a scorer can raise but never lower a deterministi
99
99
  assert.equal(plan.verification.independent, true);
100
100
  } finally { provider.score = original; console.log = log; if (mode === undefined) delete process.env.HARNESS_SYSTEM_ONE_MODE; else process.env.HARNESS_SYSTEM_ONE_MODE = mode; }
101
101
  });
102
+ test('S1-R06 prescoreTier: off loads nothing; a matching request reuses the async result; mismatch and failure keep sync semantics', async () => {
103
+ const { prescoreTier } = require('../harness-everything/scripts/system-one/router');
104
+ const provider = require('../harness-everything/scripts/system-one/provider');
105
+ const forbidden = () => { throw new Error('must not invoke'); };
106
+ for (const env of [{}, { HARNESS_SYSTEM_ONE_MODE: 'off' }, { HARNESS_SYSTEM_ONE_MODE: 'bogus' }]) assert.equal(await prescoreTier('實作功能', env, forbidden), null);
107
+ assert.equal(await prescoreTier('', { HARNESS_SYSTEM_ONE_MODE: 'shadow' }, forbidden), null);
108
+ const env = { HARNESS_SYSTEM_ONE_MODE: 'prefer', HARNESS_SYSTEM_ONE_CONFIG: '/abs/manifest.json' };
109
+ const input = { prompt: '實作功能', tier: 'Unclassified' };
110
+ const configs = [];
111
+ const pre = await prescoreTier(input.prompt, env, async (req, config) => { configs.push(config); return scorer('tier2')(req); });
112
+ assert.deepEqual(configs, ['/abs/manifest.json']);
113
+ assert.deepEqual(selectTier(input, env, pre), selectTier(input, env, scorer('tier2')));
114
+ const original = provider.score;
115
+ try {
116
+ let used = 0;
117
+ provider.score = req => { used += 1; return scorer('tier3')(req); };
118
+ assert.equal(selectTier({ ...input, prompt: 'different prompt' }, env, pre).tier, 'Tier 3 (Macro Task)');
119
+ assert.equal(used, 1);
120
+ } finally { provider.score = original; }
121
+ const failing = await prescoreTier(input.prompt, env, async () => { throw new Error('secret'); });
122
+ const failed = selectTier(input, env, failing);
123
+ assert.deepEqual(failed, selectTier(input, env, () => { throw new Error('secret'); }));
124
+ assert.equal(failed.diagnostic.reason, 'provider-unavailable');
125
+ assert.ok(!JSON.stringify(failed).includes('secret'));
126
+ });
@@ -2,10 +2,17 @@
2
2
  import hashlib
3
3
  import importlib.util
4
4
  import json
5
+ import os
5
6
  from pathlib import Path
7
+ import socket
8
+ import subprocess
9
+ import sys
6
10
  import tempfile
11
+ import threading
12
+ import time
7
13
  import unittest
8
14
 
15
+ sys.dont_write_bytecode = True # never leave __pycache__ in the source tree that packaging copies
9
16
  path = Path(__file__).resolve().parents[1] / 'harness-everything/scripts/system-one/cua_adapter.py'
10
17
  spec = importlib.util.spec_from_file_location('adapter', path)
11
18
  adapter = importlib.util.module_from_spec(spec)
@@ -52,5 +59,164 @@ class AdapterTests(unittest.TestCase):
52
59
  self.assertEqual(json.loads(json.dumps(result)), result)
53
60
 
54
61
 
62
+ def stub_factory(weights, manifest):
63
+ return (lambda request: [1.0] + [0.0] * (len(request['options']) - 1)), {'context_tokens': 8, 'option_tokens': 8}
64
+
65
+
66
+ def call(port, payload, raw=None):
67
+ with socket.create_connection(('127.0.0.1', port), timeout=5) as conn:
68
+ conn.sendall(raw if raw is not None else (json.dumps(payload) + '\n').encode('utf-8'))
69
+ conn.shutdown(socket.SHUT_WR)
70
+ data = b''.join(iter(lambda: conn.recv(65536), b''))
71
+ return json.loads(data)
72
+
73
+
74
+ class ResidentServerTests(unittest.TestCase):
75
+ def setUp(self):
76
+ self.root = tempfile.TemporaryDirectory()
77
+ weights = Path(self.root.name) / 'model.safetensors'
78
+ weights.write_bytes(b'synthetic-not-real-weights')
79
+ weights.with_suffix('.json').write_text('{}', encoding='utf-8')
80
+ self.weights = weights
81
+ self.manifest = {'checkpoint': str(weights), 'modelId': 'stub', 'revision': 'v1', 'domain': 'harness-routing-v1',
82
+ 'weightsSha256': hashlib.sha256(weights.read_bytes()).hexdigest(),
83
+ 'configSha256': hashlib.sha256(weights.with_suffix('.json').read_bytes()).hexdigest()}
84
+ self.state = Path(self.root.name) / 'state.json'
85
+ self.lock = Path(self.root.name) / 'state.starting'
86
+ self.lock.write_text('{}', encoding='utf-8')
87
+
88
+ def tearDown(self):
89
+ self.root.cleanup()
90
+
91
+ def start(self, idle=30):
92
+ thread = threading.Thread(target=adapter.serve, args=(self.manifest, self.state, self.lock),
93
+ kwargs={'scorer_factory': stub_factory, 'idle_timeout_s': idle}, daemon=True)
94
+ thread.start()
95
+ deadline = time.time() + 10
96
+ while not self.state.exists() and time.time() < deadline:
97
+ time.sleep(0.02)
98
+ self.assertTrue(self.state.exists())
99
+ return thread, json.loads(self.state.read_text(encoding='utf-8'))
100
+
101
+ def request(self, context='fix', options=('a', 'b')):
102
+ return {'schemaVersion': 1, 'task': 'tier', 'context': context, 'requestHash': 'a' * 64, 'catalogHash': 'b' * 64,
103
+ 'options': [{'id': f'o{i}', 'text': t} for i, t in enumerate(options)]}
104
+
105
+ def test_protocol_auth_limits_and_shutdown(self):
106
+ thread, state = self.start()
107
+ self.assertEqual(set(state), {'schemaVersion', 'pid', 'port', 'token', 'startedAt'})
108
+ self.assertRegex(state['token'], r'^[0-9a-f]{64}$')
109
+ self.assertEqual(state['pid'], os.getpid())
110
+ self.assertFalse(self.lock.exists())
111
+ if os.name == 'posix':
112
+ self.assertEqual(self.state.stat().st_mode & 0o777, 0o600)
113
+ token, port = state['token'], state['port']
114
+ self.assertEqual(call(port, {'token': token, 'op': 'ping'})['ok'], True)
115
+ self.assertEqual(call(port, {'token': '0' * 64, 'op': 'ping'}), {'ok': False, 'reason': 'unauthorized'})
116
+ self.assertEqual(call(port, {'op': 'ping'}), {'ok': False, 'reason': 'unauthorized'})
117
+ self.assertEqual(call(port, None, raw=b'not-json\n'), {'ok': False, 'reason': 'invalid-request'})
118
+ self.assertEqual(call(port, None, raw=b'x' * (2 * 1024 * 1024 + 2)), {'ok': False, 'reason': 'request-limit'})
119
+ self.assertEqual(call(port, {'token': token, 'op': 'unknown'}), {'ok': False, 'reason': 'invalid-request'})
120
+ reply = call(port, {'token': token, 'op': 'score', 'request': self.request()})
121
+ self.assertEqual(reply['ok'], True)
122
+ self.assertEqual(reply['response']['requestHash'], 'a' * 64)
123
+ self.assertEqual(reply['response']['model'], {'id': 'stub', 'revision': 'v1', 'domain': 'harness-routing-v1'})
124
+ self.assertEqual([s['probability'] for s in reply['response']['scores']], [1.0, 0.0])
125
+ self.assertEqual(call(port, {'token': token, 'op': 'score', 'request': self.request(context='123456789')}),
126
+ {'ok': False, 'reason': 'input-too-long'})
127
+ self.assertEqual(call(port, {'token': token, 'op': 'score', 'request': {'context': 'x'}}), {'ok': False, 'reason': 'invalid-request'})
128
+ self.assertEqual(call(port, {'token': token, 'op': 'shutdown'}), {'ok': True})
129
+ thread.join(5)
130
+ self.assertFalse(thread.is_alive())
131
+ self.assertFalse(self.state.exists())
132
+
133
+ def test_artifact_change_stops_server(self):
134
+ thread, state = self.start()
135
+ time.sleep(0.05)
136
+ self.weights.write_bytes(b'changed-weights-with-new-size')
137
+ reply = call(state['port'], {'token': state['token'], 'op': 'score', 'request': self.request()})
138
+ self.assertEqual(reply, {'ok': False, 'reason': 'artifact-changed'})
139
+ thread.join(5)
140
+ self.assertFalse(thread.is_alive())
141
+ self.assertFalse(self.state.exists())
142
+
143
+ def test_idle_timeout_exits_and_removes_state(self):
144
+ thread, _ = self.start(idle=0.3)
145
+ thread.join(5)
146
+ self.assertFalse(thread.is_alive())
147
+ self.assertFalse(self.state.exists())
148
+
149
+ @unittest.skipUnless(os.name == 'nt', 'Windows DACL')
150
+ def test_state_file_has_owner_only_explicit_dacl_on_windows(self):
151
+ thread, state = self.start()
152
+ # Drop the file path (it contains "C:\Users\...") and keep only the ACE text.
153
+ acl = subprocess.run(['icacls', str(self.state)], capture_output=True, text=True).stdout.replace(str(self.state), '')
154
+ self.assertIn(':(F)', acl)
155
+ for bad in ['(I)', 'Users', 'Everyone', 'Administrators', 'SYSTEM']:
156
+ self.assertNotIn(bad, acl)
157
+ call(state['port'], {'token': state['token'], 'op': 'shutdown'})
158
+ thread.join(5)
159
+
160
+ @unittest.skipUnless(os.name == 'nt', 'Windows DACL')
161
+ def test_explicit_foreign_aces_are_replaced_not_kept(self):
162
+ # CI runners create files with explicit (non-inherited) SYSTEM/Administrators/OWNER RIGHTS entries.
163
+ target = Path(self.root.name) / 'explicit.json'
164
+ target.write_text('{}', encoding='utf-8')
165
+ subprocess.run(['icacls', str(target), '/inheritance:d'], capture_output=True, check=True)
166
+ subprocess.run(['icacls', str(target), '/grant', '*S-1-5-32-544:F', '*S-1-5-18:F', '*S-1-3-4:F', '*S-1-5-32-545:R'], capture_output=True, check=True)
167
+ adapter._restrict_to_current_user(target)
168
+ acl = subprocess.run(['icacls', str(target)], capture_output=True, text=True).stdout.replace(str(target), '')
169
+ self.assertEqual(acl.count(':('), 1)
170
+ self.assertIn(':(F)', acl)
171
+
172
+ def test_slow_client_does_not_block_others_and_burst_is_served(self):
173
+ thread, state = self.start()
174
+ idle = socket.create_connection(('127.0.0.1', state['port']), timeout=5)
175
+ try:
176
+ began = time.monotonic()
177
+ self.assertEqual(call(state['port'], {'token': state['token'], 'op': 'ping'})['ok'], True)
178
+ self.assertLess(time.monotonic() - began, 0.5)
179
+ results = []
180
+ workers = [threading.Thread(target=lambda: results.append(call(state['port'], {'token': state['token'], 'op': 'ping'}))) for _ in range(32)]
181
+ for w in workers:
182
+ w.start()
183
+ for w in workers:
184
+ w.join(10)
185
+ self.assertEqual(len(results), 32)
186
+ self.assertTrue(all(r.get('ok') is True or r == {'ok': False, 'reason': 'busy'} for r in results))
187
+ self.assertGreaterEqual(sum(1 for r in results if r.get('ok') is True), 16)
188
+ finally:
189
+ idle.close()
190
+ call(state['port'], {'token': state['token'], 'op': 'shutdown'})
191
+ thread.join(5)
192
+
193
+ def test_server_exits_when_its_state_file_no_longer_names_it(self):
194
+ thread, _ = self.start()
195
+ self.state.write_text('{"corrupt": true}', encoding='utf-8')
196
+ thread.join(5)
197
+ self.assertFalse(thread.is_alive())
198
+ self.assertEqual(self.state.read_text(encoding='utf-8'), '{"corrupt": true}')
199
+
200
+ def test_rejects_requests_outside_phase0_structure(self):
201
+ thread, state = self.start()
202
+ token, port = state['token'], state['port']
203
+ many = self.request(options=tuple('x' for _ in range(257)))
204
+ extra = dict(self.request(), extra=1)
205
+ dup = self.request(); dup['options'][1]['id'] = dup['options'][0]['id']
206
+ bad_id = self.request(); bad_id['options'][0]['id'] = 'Bad ID'
207
+ wrong_version = dict(self.request(), schemaVersion=2)
208
+ for request in [many, extra, dup, bad_id, wrong_version]:
209
+ self.assertEqual(call(port, {'token': token, 'op': 'score', 'request': request}), {'ok': False, 'reason': 'invalid-request'})
210
+ self.assertEqual(call(port, {'token': token, 'op': 'score', 'request': self.request(options=tuple('x' for _ in range(256)))})['ok'], True)
211
+ call(port, {'token': token, 'op': 'shutdown'})
212
+ thread.join(5)
213
+
214
+ def test_startup_failure_is_recorded_in_lock(self):
215
+ self.manifest['weightsSha256'] = '0' * 64
216
+ adapter.serve(self.manifest, self.state, self.lock, scorer_factory=stub_factory, idle_timeout_s=1)
217
+ self.assertFalse(self.state.exists())
218
+ self.assertEqual(json.loads(self.lock.read_text(encoding='utf-8'))['failed'], 'artifact-hash')
219
+
220
+
55
221
  if __name__ == '__main__':
56
222
  unittest.main()