worktrust 0.7.2 → 0.7.3

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
@@ -161,6 +161,7 @@ nothing it does not:
161
161
  | `signals`, `analyzer_version` | the behaviour signals of that stretch as keys and counts from the local counter's rubric (framing, steering, verification, recovery), and the rubric's version; derived on this computer from your own turns, never a word of them (0.7.0) |
162
162
  | `verification`, `delivery` | per kind of check run in the stretch (test, typecheck, lint, build, the project's gate, CI) how many ran and how many failed; per delivery step (commit, PR, push, deploy) how many succeeded, and whether a check had passed before the first; named from each command on this computer, never the command itself (0.7.1) |
163
163
  | `recovery` | of the tool calls that failed in the stretch, how many a later call of the same kind recovered, the middle time that took, how many were retried unchanged and how many with a different approach; inputs compared on this computer by digest, never kept (0.7.2) |
164
+ | `delegation` | the longest and the middle chain of actions the agent took on its own between your turns (or your stopping it), and how often it stopped to ask you a question or to have a plan approved (0.7.3) |
164
165
  | `collector_version` | the CLI version that measured it |
165
166
  | `seq`, `prev`, `hash` | the line's place, the hash of the line before it, and its own hash |
166
167
 
package/log-session.mjs CHANGED
@@ -512,8 +512,34 @@ function verificationOf(messages) {
512
512
  }
513
513
  }
514
514
  const any = (record) => Object.keys(record).length > 0;
515
- const recovery = recoveryOf(messages);
516
- return { ...(any(checks) ? { verification: checks } : {}), ...(any(delivered) ? { delivery: { ...delivered, verified_first: passedFirst } } : {}), ...(recovery ? { recovery } : {}) };
515
+ const recovery = recoveryOf(messages), delegation = delegationOf(messages);
516
+ return { ...(any(checks) ? { verification: checks } : {}), ...(any(delivered) ? { delivery: { ...delivered, verified_first: passedFirst } } : {}), ...(recovery ? { recovery } : {}), ...(delegation ? { delegation } : {}) };
517
+ }
518
+
519
+ /**
520
+ * DELEGATION AND CHECKPOINTS PER STRETCH (0.7.3; framework L3, L5): how many tool actions the agent took on its own
521
+ * between two moments the person stepped in (their own turn, or stopping it), as the longest and the middle chain; and
522
+ * how often the agent stopped for the person on purpose: a question it asked them, a plan it asked them to approve.
523
+ * Null when the stretch made no tool call.
524
+ */
525
+ function delegationOf(messages) {
526
+ const chains = [];
527
+ let chain = 0, calls = 0, questions = 0, plans = 0;
528
+ for (const message of messages) {
529
+ if (message.bridge) continue;
530
+ const stepIn = message.type === "user" && !message.meta && message.kind !== "tool_result" && (isHumanTurn(message.content) || INTERRUPTED.test(textOf(message.content).trim()));
531
+ if (stepIn) { if (chain > 0) chains.push(chain); chain = 0; continue; }
532
+ for (const call of message.calls ?? []) {
533
+ const tool = call.family.split("|")[0];
534
+ calls += 1; chain += 1;
535
+ if (tool === "AskUserQuestion") questions += 1;
536
+ if (tool === "ExitPlanMode") plans += 1;
537
+ }
538
+ }
539
+ if (chain > 0) chains.push(chain);
540
+ if (calls === 0) return null;
541
+ chains.sort((a, b) => a - b);
542
+ return { chain_max: chains.at(-1), chain_median: chains[Math.floor((chains.length - 1) / 2)], questions, plans };
517
543
  }
518
544
 
519
545
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "worktrust",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "Couple this computer to WorkTrust: approve a code in your browser, and every AI app here reports what you built. Metadata only, no dependencies.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -63,6 +63,11 @@ export function archiveLine(entry, behaviour = null, { ids = {}, collector } = {
63
63
  const { failures, recovered, blind_retries: blind, strategy_changed: changed, median_seconds: median } = entry.recovery;
64
64
  if ([failures, recovered, blind, changed].every(whole) && failures > 0 && recovered <= failures && blind + changed <= failures && (median === undefined || whole(median))) line.recovery = { failures, recovered, blind_retries: blind, strategy_changed: changed, ...(median !== undefined ? { median_seconds: median } : {}) };
65
65
  }
66
+ // DELEGATION (0.7.3): the longest and middle chain of the agent's own actions between the person's steps, questions, plans.
67
+ if (entry.delegation && typeof entry.delegation === "object") {
68
+ const { chain_max: most, chain_median: middle, questions, plans } = entry.delegation;
69
+ if ([most, middle, questions, plans].every(whole) && most > 0 && middle <= most) line.delegation = { chain_max: most, chain_median: middle, questions, plans };
70
+ }
66
71
  // The behaviour signals of this stretch (0.7.0): keys of the counter's rubric and whole counts, never a word of a turn.
67
72
  if (behaviour && behaviour.signals && typeof behaviour.analyzer_version === "string" && /^counter@\d+\.\d+\.\d+$/.test(behaviour.analyzer_version)) {
68
73
  const kept = Object.entries(behaviour.signals).filter(([key, count]) => SIGNAL.test(key) && Number.isInteger(count) && count > 0).sort();
package/worktrust.mjs CHANGED
@@ -71,7 +71,7 @@ const command = args.find((arg, at) => !arg.startsWith("--") && !(at > 0 && VALU
71
71
  const flag = (name) => { const at = args.indexOf(`--${name}`); return at >= 0 ? args[at + 1] : undefined; };
72
72
  const has = (name) => args.includes(`--${name}`);
73
73
  /** This CLI's version, said to the door so the app can tell which computer runs an old one (check-cli-package holds it equal to package.json). */
74
- const CLI_VERSION = "0.7.2";
74
+ const CLI_VERSION = "0.7.3";
75
75
  const ORIGIN = (flag("origin") ?? process.env.WORKTRUST_ORIGIN ?? "https://app.worktrust.io").replace(/\/$/, "");
76
76
  const MCP = flag("url") ?? process.env.WORKTRUST_MCP_URL ?? `${ORIGIN}/api/mcp`;
77
77
  const HOME_DIR = join(homedir(), ".worktrust");