harness-everything 0.24.0 → 0.25.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 +10 -0
- package/ci/mechanism-system-one-collect.test.js +29 -0
- package/ci/mechanism-system-one-label.test.js +4 -0
- package/docs/system-one-corpus.md +4 -0
- package/docs/system-one-training.md +16 -6
- 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/sbom.cdx.json +7 -7
- package/scripts/system-one-collect.js +6 -2
- package/scripts/system-one-label.js +4 -3
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"name": "harness-everything",
|
|
11
11
|
"source": "./",
|
|
12
12
|
"description": "Harness OS: an orchestrated agent operating system — tier routing, circuit breaker guardrails, verification gates, WAL session memory, and self-evolving workspace rules.",
|
|
13
|
-
"version": "0.
|
|
13
|
+
"version": "0.25.0",
|
|
14
14
|
"author": {
|
|
15
15
|
"name": "Miya Daniel"
|
|
16
16
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "harness-everything",
|
|
3
3
|
"description": "Harness OS: an orchestrated agent operating system — tier routing, circuit breaker guardrails, verification gates, WAL session memory, and self-evolving workspace rules.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.25.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Miya Daniel"
|
|
7
7
|
},
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.25.0](https://github.com/dyphn1/Harness-everything/compare/v0.24.0...v0.25.0) (2026-09-23)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
* **router:** bound system one labeling runs with --max-batches ([e69b596](https://github.com/dyphn1/Harness-everything/commit/e69b5962888ad9e53ca189f36e67ccf6ada03290)), closes [#233](https://github.com/dyphn1/Harness-everything/issues/233)
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **router:** drop agent-authored prompts from system one training data ([8a2f959](https://github.com/dyphn1/Harness-everything/commit/8a2f959bb2ffd56c64d7e9eb2342b1178cd559dd)), closes [#233](https://github.com/dyphn1/Harness-everything/issues/233)
|
|
14
|
+
|
|
5
15
|
## [0.24.0](https://github.com/dyphn1/Harness-everything/compare/v0.23.0...v0.24.0) (2026-09-23)
|
|
6
16
|
|
|
7
17
|
### Features
|
|
@@ -25,11 +25,13 @@ function fakeHome() {
|
|
|
25
25
|
{ type: 'assistant', message: { content: 'assistant text must be skipped' } },
|
|
26
26
|
]));
|
|
27
27
|
write('.codex/sessions/2026/09/01/rollout-a.jsonl', jsonl([
|
|
28
|
+
{ type: 'session_meta', payload: { originator: 'codex_vscode', source: 'vscode' } },
|
|
28
29
|
{ type: 'response_item', payload: { type: 'message', role: 'user', content: [{ type: 'input_text', text: '<environment_context>cwd</environment_context>' }] } },
|
|
29
30
|
{ type: 'response_item', payload: { type: 'message', role: 'user', content: [{ type: 'input_text', text: 'duplicate of the event message' }] } },
|
|
30
31
|
{ type: 'event_msg', payload: { type: 'user_message', message: 'add a --verbose flag with tests' } },
|
|
31
32
|
]));
|
|
32
33
|
write('.codex/sessions/2026/09/02/rollout-b.jsonl', jsonl([
|
|
34
|
+
{ type: 'session_meta', payload: { originator: 'Codex Desktop', source: 'vscode' } },
|
|
33
35
|
{ type: 'response_item', payload: { type: 'message', role: 'user', content: [{ type: 'input_text', text: '<user_instructions>agents</user_instructions>' }] } },
|
|
34
36
|
{ type: 'response_item', payload: { type: 'message', role: 'user', content: [{ type: 'input_text', text: 'older session without event messages' }] } },
|
|
35
37
|
]));
|
|
@@ -69,6 +71,33 @@ test('S1-C101 each source yields only owner-typed text', () => {
|
|
|
69
71
|
} finally { fs.rmSync(home, { recursive: true, force: true }); }
|
|
70
72
|
});
|
|
71
73
|
|
|
74
|
+
test('S1-C106 only interactive Codex sessions count, and VS Code terminal notifications are dropped', () => {
|
|
75
|
+
const home = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-s1-collect-'));
|
|
76
|
+
const appdata = path.join(home, 'AppData', 'Roaming');
|
|
77
|
+
const session = (name, meta, text) => {
|
|
78
|
+
const p = path.join(home, '.codex', 'sessions', '2026', '09', '03', `${name}.jsonl`);
|
|
79
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
80
|
+
fs.writeFileSync(p, jsonl([{ type: 'session_meta', payload: meta }, { type: 'event_msg', payload: { type: 'user_message', message: text } }]));
|
|
81
|
+
};
|
|
82
|
+
try {
|
|
83
|
+
session('ide', { originator: 'codex_vscode', source: 'vscode' }, 'typed in the IDE');
|
|
84
|
+
session('desktop', { originator: 'Codex Desktop', source: 'vscode' }, 'typed in the desktop app');
|
|
85
|
+
session('tui', { originator: 'codex-tui', source: 'cli' }, 'typed in the terminal');
|
|
86
|
+
session('from-claude', { originator: 'Claude Code', source: 'vscode' }, 'dispatched by another agent');
|
|
87
|
+
session('exec', { originator: 'codex_exec', source: 'exec' }, 'an exec lane prompt');
|
|
88
|
+
session('ide-exec', { originator: 'codex_vscode', source: 'exec' }, 'another exec prompt');
|
|
89
|
+
session('subagent', { originator: 'codex_vscode', source: { subagent: { thread_spawn: {} } } }, 'a sub-agent prompt');
|
|
90
|
+
session('no-meta', null, 'a session without metadata');
|
|
91
|
+
const chat = path.join(appdata, 'Code', 'User', 'workspaceStorage', 'w', 'chatSessions', 's.jsonl');
|
|
92
|
+
fs.mkdirSync(path.dirname(chat), { recursive: true });
|
|
93
|
+
fs.writeFileSync(chat, jsonl([{ kind: 0, v: { requests: [
|
|
94
|
+
{ message: { text: '[Terminal 808808ce-309f notification: command completed with exit code 0]' } },
|
|
95
|
+
{ message: { text: 'a real chat prompt' } }] } }]));
|
|
96
|
+
assert.deepEqual(texts(collect.readSources({ home, appdata })), texts([
|
|
97
|
+
{ text: 'typed in the IDE' }, { text: 'typed in the desktop app' }, { text: 'typed in the terminal' }, { text: 'a real chat prompt' }]));
|
|
98
|
+
} finally { fs.rmSync(home, { recursive: true, force: true }); }
|
|
99
|
+
});
|
|
100
|
+
|
|
72
101
|
test('S1-C102 filters, redaction and deduplication', () => {
|
|
73
102
|
assert.equal(collect.keep('go'), true);
|
|
74
103
|
assert.equal(collect.keep('x'.repeat(1024)), true);
|
|
@@ -89,6 +89,10 @@ test('S1-L05 CLI labels through the configured command, resumes, checks the hold
|
|
|
89
89
|
const rows = fs.readFileSync(out, 'utf8').trim().split('\n').map(l => JSON.parse(l));
|
|
90
90
|
assert.ok(rows.every(r => r.gold === 'tier2' && r.labeler.model === 'sonnet' && /^[0-9a-f]{16}$/.test(r.labeler.rulesSha256)));
|
|
91
91
|
assert.deepEqual(JSON.parse(cli(['label', '--in', input, '--out', out]).stdout), { labeled: 0, failed: 0, total: 5 });
|
|
92
|
+
const partial = path.join(dir, 'partial.jsonl');
|
|
93
|
+
assert.deepEqual(JSON.parse(cli(['label', '--in', input, '--out', partial, '--batch', '2', '--max-batches', '1']).stdout), { labeled: 2, failed: 0, total: 5 });
|
|
94
|
+
assert.deepEqual(JSON.parse(cli(['label', '--in', input, '--out', partial, '--batch', '2', '--max-batches', '1']).stdout), { labeled: 2, failed: 0, total: 5 }, 'resumes with the next batch');
|
|
95
|
+
assert.equal(fs.readFileSync(partial, 'utf8').trim().split('\n').length, 4);
|
|
92
96
|
const report = path.join(dir, 'check.json');
|
|
93
97
|
const check = cli(['check-holdout', '--out', report]);
|
|
94
98
|
assert.equal(check.status, 0, check.stderr);
|
|
@@ -27,6 +27,10 @@ Rules:
|
|
|
27
27
|
2. Label the work requested, not the words used. Searching every repository and
|
|
28
28
|
reporting is `tier1`; changing every repository is `tier3`.
|
|
29
29
|
3. Pick the smallest tier that covers the whole request.
|
|
30
|
+
A question, a confirmation, a discussion point, or a request to restate,
|
|
31
|
+
reformat or extend the assistant's previous answer without changing files is
|
|
32
|
+
`tier1`. A requested change to code or configuration, however small, is at
|
|
33
|
+
least `tier2`. Only the smallest doc fixes listed in the table stay `tier1`.
|
|
30
34
|
4. Explicit workflow words ("use fable", "no subagents") do not change the gold.
|
|
31
35
|
Precedence is a router policy, not a label.
|
|
32
36
|
5. Never derive gold from the lexical router or any model output. A reviewer may
|
|
@@ -42,8 +42,11 @@ The following are dropped:
|
|
|
42
42
|
- Session-continuation summaries ("This session is being continued…").
|
|
43
43
|
- Empty text.
|
|
44
44
|
|
|
45
|
-
Codex sessions
|
|
46
|
-
|
|
45
|
+
Codex sessions are kept only when they are interactive, meaning `session_meta` has a
|
|
46
|
+
`source` of `vscode` or `cli` and an originator that is neither `Claude Code` nor
|
|
47
|
+
`codex_exec`. Exec sessions, sub-agent threads and sessions another agent started contain
|
|
48
|
+
prompts written by an agent, not by the owner. VS Code terminal notifications
|
|
49
|
+
(`[Terminal … notification …`) are dropped as well.
|
|
47
50
|
|
|
48
51
|
## Filters, families and splits
|
|
49
52
|
|
|
@@ -80,7 +83,9 @@ their source, because Harness routes them in Codex too.
|
|
|
80
83
|
sessions never become collectable history), `--tools ""` and a JSON schema.
|
|
81
84
|
- The instructions contain the gold table and rules from
|
|
82
85
|
[system-one-corpus.md](system-one-corpus.md).
|
|
83
|
-
- Prompts go in batches of 100.
|
|
86
|
+
- Prompts go in batches of 100. `--max-batches N` stops after N batches so a
|
|
87
|
+
memory-constrained host can label in short foreground runs that resume from the
|
|
88
|
+
labels already written. Every returned index must be labeled exactly once with
|
|
84
89
|
`tier1`, `tier2`, `tier3` or `null`. A malformed batch is retried once and then
|
|
85
90
|
recorded as failed. It is never partially accepted.
|
|
86
91
|
- **Labeler check**: the labeler labels the 215 holdout prompts once, before any training
|
|
@@ -88,9 +93,14 @@ their source, because Harness routes them in Codex too.
|
|
|
88
93
|
- Labeling proceeds only when agreement is at least 80%.
|
|
89
94
|
- The instructions are never tuned on the holdout. If the check fails, the owner reviews
|
|
90
95
|
the disagreements and decides how to proceed.
|
|
91
|
-
- **Owner spot-check**: a
|
|
92
|
-
review page, and the disagreement rate is reported.
|
|
93
|
-
|
|
96
|
+
- **Owner spot-check**: a deterministic sample of the labeled training data is reviewed on
|
|
97
|
+
the review page, and the disagreement rate is reported.
|
|
98
|
+
- Each case shows the preceding prompts from the same session as read-only context.
|
|
99
|
+
Without it, short replies read as confirmations: the first spot-check (103 cases,
|
|
100
|
+
no context) disagreed 51% and was not used to override labels.
|
|
101
|
+
- A checkpoint may be trained before the spot-check, but it is released only when
|
|
102
|
+
disagreement is below 20%.
|
|
103
|
+
- Decisions made with context replace the LLM labels for those cases.
|
|
94
104
|
|
|
95
105
|
## Training and calibration
|
|
96
106
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "harness-everything",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.25.0",
|
|
5
5
|
"description": "Invariant-first engineering harness for routing, verification, and failure recovery while preserving agent autonomy.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Miya Daniel",
|
package/sbom.cdx.json
CHANGED
|
@@ -2,23 +2,23 @@
|
|
|
2
2
|
"$schema": "https://cyclonedx.org/schema/bom-1.7.schema.json",
|
|
3
3
|
"bomFormat": "CycloneDX",
|
|
4
4
|
"specVersion": "1.7",
|
|
5
|
-
"serialNumber": "urn:uuid:
|
|
5
|
+
"serialNumber": "urn:uuid:a66915ec-6b2f-51ca-a5d4-4a642ce3a914",
|
|
6
6
|
"version": 1,
|
|
7
7
|
"metadata": {
|
|
8
|
-
"timestamp": "2026-09-
|
|
8
|
+
"timestamp": "2026-09-23T15:52:59.593Z",
|
|
9
9
|
"tools": [
|
|
10
10
|
{
|
|
11
11
|
"vendor": "Harness Everything",
|
|
12
12
|
"name": "generate-sbom.js",
|
|
13
|
-
"version": "0.
|
|
13
|
+
"version": "0.25.0"
|
|
14
14
|
}
|
|
15
15
|
],
|
|
16
16
|
"component": {
|
|
17
17
|
"type": "application",
|
|
18
|
-
"bom-ref": "pkg:npm/harness-everything@0.
|
|
18
|
+
"bom-ref": "pkg:npm/harness-everything@0.25.0",
|
|
19
19
|
"name": "harness-everything",
|
|
20
|
-
"version": "0.
|
|
21
|
-
"purl": "pkg:npm/harness-everything@0.
|
|
20
|
+
"version": "0.25.0",
|
|
21
|
+
"purl": "pkg:npm/harness-everything@0.25.0"
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
"components": [
|
|
@@ -1999,7 +1999,7 @@
|
|
|
1999
1999
|
]
|
|
2000
2000
|
},
|
|
2001
2001
|
{
|
|
2002
|
-
"ref": "pkg:npm/harness-everything@0.
|
|
2002
|
+
"ref": "pkg:npm/harness-everything@0.25.0",
|
|
2003
2003
|
"dependsOn": [
|
|
2004
2004
|
"pkg:npm/%40commitlint/cli@19.8.1",
|
|
2005
2005
|
"pkg:npm/%40commitlint/config-conventional@19.8.1",
|
|
@@ -12,7 +12,9 @@ const REPO = path.resolve(__dirname, '..');
|
|
|
12
12
|
const MAX_BYTES = 1024;
|
|
13
13
|
const VALIDATION_PERCENT = 15;
|
|
14
14
|
// Whole-text wrappers injected by hosts or hooks; text that starts with one is not typed by the owner.
|
|
15
|
-
const WRAPPER =
|
|
15
|
+
const WRAPPER = /^(<(environment_context|user_instructions|recommended_plugins|send_user_message_question_reply|command-|local-command|task-notification|bash-|turn_aborted|user_shell_command|skill)|\[Terminal [0-9a-f-]+ notification)/i;
|
|
16
|
+
// Codex sessions typed by the owner: interactive IDE/desktop/terminal ones, not exec lanes, sub-agents or agent-started sessions.
|
|
17
|
+
const interactiveCodex = meta => !!meta && ['vscode', 'cli'].includes(meta.source) && !['Claude Code', 'codex_exec'].includes(meta.originator);
|
|
16
18
|
// Blocks a host inserts inside typed text; they are removed and the rest is kept.
|
|
17
19
|
const INSERTED = /<(system-reminder|ide_[a-z_]+)>[\s\S]*?<\/\1>/gi;
|
|
18
20
|
const sha = text => createHash('sha256').update(text, 'utf8').digest('hex');
|
|
@@ -61,12 +63,14 @@ function fromClaude(file) {
|
|
|
61
63
|
return rows;
|
|
62
64
|
}
|
|
63
65
|
function fromCodex(file) {
|
|
64
|
-
const events = []; const items = [];
|
|
66
|
+
const events = []; const items = []; let meta = null;
|
|
65
67
|
for (const line of readLines(file)) {
|
|
66
68
|
const e = parse(line); if (!e || !e.payload) continue;
|
|
69
|
+
if (e.type === 'session_meta' && !meta) { meta = e.payload; if (!interactiveCodex(meta)) return []; continue; }
|
|
67
70
|
if (e.type === 'event_msg' && e.payload.type === 'user_message') { const t = typed(e.payload.message); if (t) events.push(t); }
|
|
68
71
|
if (e.type === 'response_item' && e.payload.role === 'user') for (const c of e.payload.content || []) { const t = typed(c && c.text); if (t) items.push(t); }
|
|
69
72
|
}
|
|
73
|
+
if (!interactiveCodex(meta)) return [];
|
|
70
74
|
// Event messages are the typed text; response items repeat it with injected context, so they are a fallback only.
|
|
71
75
|
return events.length ? events : items;
|
|
72
76
|
}
|
|
@@ -39,9 +39,9 @@ function validateReply(batch, reply) {
|
|
|
39
39
|
}
|
|
40
40
|
return out;
|
|
41
41
|
}
|
|
42
|
-
async function labelAll(data, { run, rules, batchSize = 100, concurrency = 4, done = new Set(), onBatch = () => {}, onFailure = () => {}, retryDelayMs = 30000 }) {
|
|
42
|
+
async function labelAll(data, { run, rules, batchSize = 100, concurrency = 4, done = new Set(), onBatch = () => {}, onFailure = () => {}, retryDelayMs = 30000, maxBatches = Infinity }) {
|
|
43
43
|
const todo = data.filter(d => !done.has(d.id));
|
|
44
|
-
const batches = []; for (let i = 0; i < todo.length; i += batchSize) batches.push(todo.slice(i, i + batchSize));
|
|
44
|
+
const batches = []; for (let i = 0; i < todo.length && batches.length < maxBatches; i += batchSize) batches.push(todo.slice(i, i + batchSize));
|
|
45
45
|
const labeled = []; const failed = []; let next = 0;
|
|
46
46
|
// Every failed attempt is reported with its reason; a thrown run (rate limit, timeout) waits before the retry.
|
|
47
47
|
const attempt = async batch => {
|
|
@@ -127,7 +127,8 @@ async function main(argv) {
|
|
|
127
127
|
const onBatch = rows => fs.appendFileSync(out, rows.map(r => `${JSON.stringify({ ...r, labeler })}\n`).join(''), { mode: 0o600 });
|
|
128
128
|
// Failure log: first ID, size and reason only, never prompt text.
|
|
129
129
|
const onFailure = (batch, reason) => fs.appendFileSync(`${out}.failures.jsonl`, `${JSON.stringify({ firstId: batch[0].id, size: batch.length, reason, at: new Date().toISOString() })}\n`);
|
|
130
|
-
const
|
|
130
|
+
const maxBatches = Number(opt('--max-batches', 'Infinity'));
|
|
131
|
+
const { labeled, failed } = await labelAll(data, { run, rules, batchSize, concurrency, done, onBatch, onFailure, maxBatches });
|
|
131
132
|
console.log(JSON.stringify({ labeled: labeled.length, failed: failed.length, total: data.length }));
|
|
132
133
|
} else if (op === 'check-holdout') {
|
|
133
134
|
const out = opt('--out'); if (!out) throw new Error('check-holdout needs --out');
|