tryharness 0.7.23 → 0.7.26
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/assets/opencode-plugin.js +48 -11
- package/assets/pi-extension.ts +105 -26
- package/cli.mjs +1238 -322
- package/lib/activity.mjs +197 -40
- package/lib/adapters.mjs +337 -54
- package/lib/agentnode.mjs +175 -35
- package/lib/atlas.mjs +383 -83
- package/lib/cards.mjs +174 -40
- package/lib/claudemem.mjs +74 -18
- package/lib/commands.mjs +13 -5
- package/lib/context.mjs +409 -71
- package/lib/control-client.mjs +5 -2
- package/lib/coordinator.mjs +274 -57
- package/lib/daemon.mjs +5268 -1024
- package/lib/desktop.mjs +149 -35
- package/lib/digest.mjs +54 -13
- package/lib/environment.mjs +103 -21
- package/lib/files.mjs +246 -13
- package/lib/firewall.mjs +169 -35
- package/lib/folders.mjs +179 -36
- package/lib/frames.mjs +214 -40
- package/lib/inference.mjs +463 -126
- package/lib/learn.mjs +78 -16
- package/lib/live.mjs +286 -61
- package/lib/localmodels.mjs +424 -83
- package/lib/mcp-stdio.mjs +868 -151
- package/lib/media.mjs +138 -28
- package/lib/members.json +1 -1
- package/lib/members.mjs +35 -9
- package/lib/models.mjs +342 -80
- package/lib/network.mjs +201 -42
- package/lib/notify.mjs +49 -12
- package/lib/nudge.mjs +184 -33
- package/lib/ocr.mjs +223 -60
- package/lib/onboard.mjs +321 -70
- package/lib/parsers.mjs +132 -41
- package/lib/paths.mjs +33 -10
- package/lib/personal.mjs +51 -13
- package/lib/phones.mjs +384 -60
- package/lib/places.mjs +555 -107
- package/lib/provenance.mjs +19 -4
- package/lib/receipts.mjs +51 -11
- package/lib/redact.mjs +512 -116
- package/lib/runner.mjs +345 -55
- package/lib/runtime-install.mjs +55 -14
- package/lib/screens.mjs +154 -38
- package/lib/sealed.mjs +157 -28
- package/lib/secrets.mjs +18 -5
- package/lib/service.mjs +170 -34
- package/lib/snippets.mjs +94 -18
- package/lib/speech.mjs +688 -175
- package/lib/store.mjs +1654 -307
- package/lib/swarm.mjs +596 -117
- package/lib/t3.mjs +400 -79
- package/lib/trails.mjs +285 -61
- package/lib/ui.mjs +95 -23
- package/lib/vectors.mjs +5 -2
- package/lib/wakes.mjs +284 -68
- package/lib/watches.mjs +247 -48
- package/lib/worktrees.mjs +186 -38
- package/package.json +3 -3
package/lib/provenance.mjs
CHANGED
|
@@ -6,12 +6,27 @@
|
|
|
6
6
|
|
|
7
7
|
const USER_WRITERS = new Set(["user", "harness"]);
|
|
8
8
|
|
|
9
|
-
export function provenanceFor(
|
|
9
|
+
export function provenanceFor(
|
|
10
|
+
originAgent,
|
|
11
|
+
parent = null,
|
|
12
|
+
claimed = null,
|
|
13
|
+
{ personSession = false } = {}
|
|
14
|
+
) {
|
|
10
15
|
// A claim counts only when it tightens: an 'agent' label and its chain. A claim of 'user' adds nothing.
|
|
11
16
|
const taint = claimed?.trust === "agent" ? claimed : null;
|
|
12
|
-
const chain = [
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
const chain = [
|
|
18
|
+
...(parent?.chain ??
|
|
19
|
+
(Array.isArray(taint?.chain) ? taint.chain.map(String) : [])),
|
|
20
|
+
originAgent,
|
|
21
|
+
].slice(-16);
|
|
22
|
+
const tainted =
|
|
23
|
+
parent?.trust === "agent" ||
|
|
24
|
+
Boolean(taint) ||
|
|
25
|
+
(!USER_WRITERS.has(originAgent) && !personSession);
|
|
26
|
+
return {
|
|
27
|
+
trust: originAgent === "user" || !tainted ? "user" : "agent",
|
|
28
|
+
chain,
|
|
29
|
+
};
|
|
15
30
|
}
|
|
16
31
|
|
|
17
32
|
// What an agent reads before an agent-written brief: who wrote it, mechanically, every time.
|
package/lib/receipts.mjs
CHANGED
|
@@ -11,32 +11,72 @@ const DOC = /\.(?:md|mdx|txt|rst)$/i;
|
|
|
11
11
|
/** { verdict, changed, lastChangeAt, tests: [{ command, ok, at, afterChange }] } for a trail (trails.mjs). */
|
|
12
12
|
export function receipt(trail, { root = trail?.cwd } = {}) {
|
|
13
13
|
const calls = trail?.calls ?? [];
|
|
14
|
-
const code = (call) =>
|
|
14
|
+
const code = (call) =>
|
|
15
|
+
call.edited
|
|
16
|
+
.map((token) => (root ? insideRoot(token, root, trail.cwd) : token))
|
|
17
|
+
.filter((file) => file && !DOC.test(file));
|
|
15
18
|
let lastChange = -1;
|
|
16
|
-
calls.forEach((call, i) => {
|
|
19
|
+
calls.forEach((call, i) => {
|
|
20
|
+
if (code(call).length) lastChange = i;
|
|
21
|
+
});
|
|
17
22
|
const changed = [...new Set(calls.flatMap(code))];
|
|
18
|
-
const tests = calls
|
|
19
|
-
.map((
|
|
23
|
+
const tests = calls
|
|
24
|
+
.map((call, i) => ({ call, i }))
|
|
25
|
+
.filter(({ call }) => call.command && isTestCommand(call.command))
|
|
26
|
+
.map(({ call, i }) => ({
|
|
27
|
+
command: call.command.split("\n")[0].slice(0, 200),
|
|
28
|
+
ok: !call.error,
|
|
29
|
+
at: call.at,
|
|
30
|
+
afterChange: i > lastChange,
|
|
31
|
+
}));
|
|
20
32
|
const after = tests.filter((test) => test.afterChange);
|
|
21
|
-
const verdict = !changed.length
|
|
33
|
+
const verdict = !changed.length
|
|
34
|
+
? "no changes"
|
|
35
|
+
: !after.length
|
|
36
|
+
? "not tested after its last change"
|
|
37
|
+
: after.at(-1).ok
|
|
38
|
+
? "tested"
|
|
39
|
+
: "tests failing";
|
|
22
40
|
// The same test failing again and again is the clearest sign of a run going round in circles.
|
|
23
41
|
let repeated = 0;
|
|
24
42
|
let streak = 0;
|
|
25
|
-
tests.forEach((test, i) => {
|
|
26
|
-
|
|
43
|
+
tests.forEach((test, i) => {
|
|
44
|
+
streak =
|
|
45
|
+
!test.ok &&
|
|
46
|
+
i > 0 &&
|
|
47
|
+
!tests[i - 1].ok &&
|
|
48
|
+
tests[i - 1].command === test.command
|
|
49
|
+
? streak + 1
|
|
50
|
+
: test.ok
|
|
51
|
+
? 0
|
|
52
|
+
: 1;
|
|
53
|
+
repeated = Math.max(repeated, streak);
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
verdict,
|
|
57
|
+
changed,
|
|
58
|
+
lastChangeAt: lastChange >= 0 ? calls[lastChange].at : null,
|
|
59
|
+
tests: after.length ? after : tests.slice(-3),
|
|
60
|
+
repeatedFailures: repeated,
|
|
61
|
+
};
|
|
27
62
|
}
|
|
28
63
|
|
|
29
64
|
/** The line the thread shows for a receipt. */
|
|
30
65
|
export function receiptLine(agentName, result) {
|
|
31
66
|
const line = verdictLine(agentName, result);
|
|
32
|
-
return result.repeatedFailures >= 3
|
|
67
|
+
return result.repeatedFailures >= 3
|
|
68
|
+
? `${line} The same test failed ${result.repeatedFailures} times in a row during the run.`
|
|
69
|
+
: line;
|
|
33
70
|
}
|
|
34
71
|
|
|
35
72
|
function verdictLine(agentName, result) {
|
|
36
73
|
const files = `${result.changed.length} file${result.changed.length === 1 ? "" : "s"}`;
|
|
37
|
-
if (result.verdict === "no changes")
|
|
74
|
+
if (result.verdict === "no changes")
|
|
75
|
+
return `Receipt: ${agentName} changed no files in this run.`;
|
|
38
76
|
const last = result.tests.filter((test) => test.afterChange).at(-1);
|
|
39
|
-
if (result.verdict === "tested")
|
|
40
|
-
|
|
77
|
+
if (result.verdict === "tested")
|
|
78
|
+
return `Receipt: ${agentName} changed ${files}, then ran \`${last.command}\` and it passed.`;
|
|
79
|
+
if (result.verdict === "tests failing")
|
|
80
|
+
return `Receipt: ${agentName} changed ${files}; its last test after the change, \`${last.command}\`, failed.`;
|
|
41
81
|
return `Receipt: ${agentName} changed ${files} and ran no tests after its last change.`;
|
|
42
82
|
}
|