tryharness 0.7.23 → 0.7.25

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