mtech-ai-local-runner 0.1.23 → 0.1.24
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/README.md
CHANGED
|
@@ -10,6 +10,19 @@ The package stores safe runner configuration locally and keeps OAuth refresh cre
|
|
|
10
10
|
|
|
11
11
|
Public npm installation requires no npm account or publishing OTP. Setup requires Gateway OAuth login, and local Claude Code must already be authenticated (`claude auth status`).
|
|
12
12
|
|
|
13
|
+
## 0.1.24: bounded report identity diagnostics
|
|
14
|
+
|
|
15
|
+
Failed report validation records pair counts for same/different wire item IDs
|
|
16
|
+
and exact text, using at most 64 transient keyed samples. Raw IDs, text, keys
|
|
17
|
+
and hashes are never included in these diagnostics. Sampling does not limit
|
|
18
|
+
actual task duration or messages. Multiple reports still fail; none are chosen,
|
|
19
|
+
merged or deduplicated.
|
|
20
|
+
|
|
21
|
+
These observations distinguish wire-output patterns, not model-generation
|
|
22
|
+
identity: the inspected exec serializer assigns fresh CLI IDs. Earlier failures
|
|
23
|
+
cannot be reclassified without missing identity evidence. Publication and
|
|
24
|
+
foreground installation do not rerun Codex or update the daemon.
|
|
25
|
+
|
|
13
26
|
## 0.1.23: separate progress from the final report
|
|
14
27
|
|
|
15
28
|
Codex receives native-message instructions: optional progress is plain text and
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHmac, randomBytes } from "node:crypto";
|
|
1
2
|
import { completionEnvelope, completionEvent } from "../completion-report.js";
|
|
2
3
|
function record(value) {
|
|
3
4
|
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
@@ -22,6 +23,8 @@ export class CodexStreamParser {
|
|
|
22
23
|
report;
|
|
23
24
|
messages = 0;
|
|
24
25
|
candidates = 0;
|
|
26
|
+
identityKey = randomBytes(32);
|
|
27
|
+
reportSamples = [];
|
|
25
28
|
parse(line) {
|
|
26
29
|
if (this.stopped)
|
|
27
30
|
return [];
|
|
@@ -50,8 +53,17 @@ export class CodexStreamParser {
|
|
|
50
53
|
if (event.type === "item.completed" && item.type === "agent_message") {
|
|
51
54
|
this.messages += 1;
|
|
52
55
|
this.report = finalReport(item.text);
|
|
53
|
-
if (["completed", "blocked"].includes(this.report.eventType))
|
|
56
|
+
if (["completed", "blocked"].includes(this.report.eventType)) {
|
|
54
57
|
this.candidates += 1;
|
|
58
|
+
// Bounded diagnostic sample only. Neither raw IDs nor text digests
|
|
59
|
+
// leave this parser, and sampling never changes report acceptance.
|
|
60
|
+
if (this.reportSamples.length < 64) {
|
|
61
|
+
const digest = (domain, value) => createHmac("sha256", this.identityKey).update(domain).update(value).digest("hex");
|
|
62
|
+
const id = typeof item.id === "string" && item.id.length > 0 && item.id.length <= 256
|
|
63
|
+
? digest("id:", item.id) : undefined;
|
|
64
|
+
this.reportSamples.push({ id, text: digest("text:", String(item.text)) });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
55
67
|
}
|
|
56
68
|
}
|
|
57
69
|
if (event.type !== "turn.completed")
|
|
@@ -89,11 +101,41 @@ export class CodexStreamParser {
|
|
|
89
101
|
return { eventType: "failed", summary: summaries[code], payload: { completion_report: {
|
|
90
102
|
version: "codex-completion-report-v1", code, agent_message_count: this.messages,
|
|
91
103
|
valid_report_count: this.candidates, invalid_message_count: this.messages - this.candidates,
|
|
104
|
+
identity: this.reportIdentity(),
|
|
92
105
|
} } };
|
|
93
106
|
}
|
|
107
|
+
reportIdentity() {
|
|
108
|
+
const counts = { same_item_same_text_pairs: 0, same_item_different_text_pairs: 0,
|
|
109
|
+
different_item_same_text_pairs: 0, different_item_different_text_pairs: 0 };
|
|
110
|
+
for (let i = 0; i < this.reportSamples.length; i++) {
|
|
111
|
+
const a = this.reportSamples[i];
|
|
112
|
+
if (!a.id)
|
|
113
|
+
continue;
|
|
114
|
+
for (let j = i + 1; j < this.reportSamples.length; j++) {
|
|
115
|
+
const b = this.reportSamples[j];
|
|
116
|
+
if (!b.id)
|
|
117
|
+
continue;
|
|
118
|
+
if (a.id === b.id) {
|
|
119
|
+
if (a.text === b.text)
|
|
120
|
+
counts.same_item_same_text_pairs++;
|
|
121
|
+
else
|
|
122
|
+
counts.same_item_different_text_pairs++;
|
|
123
|
+
}
|
|
124
|
+
else if (a.text === b.text)
|
|
125
|
+
counts.different_item_same_text_pairs++;
|
|
126
|
+
else
|
|
127
|
+
counts.different_item_different_text_pairs++;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return { version: "codex-report-identity-v1", sampled_reports: this.reportSamples.length,
|
|
131
|
+
unsampled_reports: this.candidates - this.reportSamples.length,
|
|
132
|
+
missing_item_id_reports: this.reportSamples.filter(sample => !sample.id).length, ...counts };
|
|
133
|
+
}
|
|
94
134
|
finish(event) {
|
|
95
135
|
this.stopped = true;
|
|
96
136
|
this.report = undefined;
|
|
137
|
+
this.reportSamples.length = 0;
|
|
138
|
+
this.identityKey.fill(0);
|
|
97
139
|
return [event];
|
|
98
140
|
}
|
|
99
141
|
}
|
|
@@ -3,6 +3,24 @@ const MAX_EVIDENCE_ITEMS = 20;
|
|
|
3
3
|
const MAX_EVIDENCE_CHARS = 500;
|
|
4
4
|
const MAX_REPORT_ENVELOPE_CHARS = 16_000;
|
|
5
5
|
const REPORT_FAILURE_CODES = ["CODEX_COMPLETION_REPORT_MISSING", "CODEX_COMPLETION_REPORT_INVALID", "CODEX_COMPLETION_REPORT_MULTIPLE", "CODEX_COMPLETION_REPORT_NOT_FINAL", "CODEX_TURN_INCOMPLETE"];
|
|
6
|
+
/** Pair counts only; no item IDs, text, stable digests or arbitrary keys. */
|
|
7
|
+
function reportIdentityDiagnostic(value, valid) {
|
|
8
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
9
|
+
return undefined;
|
|
10
|
+
const d = value;
|
|
11
|
+
const keys = ["sampled_reports", "unsampled_reports", "missing_item_id_reports", "same_item_same_text_pairs",
|
|
12
|
+
"same_item_different_text_pairs", "different_item_same_text_pairs", "different_item_different_text_pairs"];
|
|
13
|
+
if (d.version !== "codex-report-identity-v1" || keys.some(key => typeof d[key] !== "number" || !Number.isSafeInteger(d[key]) || Number(d[key]) < 0))
|
|
14
|
+
return undefined;
|
|
15
|
+
const sampled = Number(d.sampled_reports), missing = Number(d.missing_item_id_reports);
|
|
16
|
+
if (sampled !== Math.min(valid, 64) || Number(d.unsampled_reports) !== valid - sampled || missing > sampled)
|
|
17
|
+
return undefined;
|
|
18
|
+
const pairs = keys.slice(3).map(key => Number(d[key]));
|
|
19
|
+
const identified = sampled - missing, expected = identified * (identified - 1) / 2;
|
|
20
|
+
if (pairs.some(count => count > expected) || pairs.reduce((sum, count) => sum + count, 0) !== expected)
|
|
21
|
+
return undefined;
|
|
22
|
+
return { version: "codex-report-identity-v1", ...Object.fromEntries(keys.map(key => [key, d[key]])) };
|
|
23
|
+
}
|
|
6
24
|
/** Diagnostic metadata only, never completion authority. Copy no provider text. */
|
|
7
25
|
export function completionReportDiagnostic(value) {
|
|
8
26
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
@@ -18,7 +36,9 @@ export function completionReportDiagnostic(value) {
|
|
|
18
36
|
|| code === "CODEX_COMPLETION_REPORT_MULTIPLE" && valid < 2
|
|
19
37
|
|| code === "CODEX_COMPLETION_REPORT_NOT_FINAL" && (valid !== 1 || invalid === 0))
|
|
20
38
|
return undefined;
|
|
21
|
-
|
|
39
|
+
const identity = reportIdentityDiagnostic(d.identity, valid);
|
|
40
|
+
return { version: "codex-completion-report-v1", code, agent_message_count: messages, valid_report_count: valid, invalid_message_count: invalid,
|
|
41
|
+
...(identity ? { identity } : {}) };
|
|
22
42
|
}
|
|
23
43
|
export const COMPLETION_REPORT_NOTICE = "Do the assigned work yourself using the available tools; do not delegate or start background work. " +
|
|
24
44
|
"Do not report completed while waiting for results, tests, or another agent. " +
|