worktrust 0.7.5 → 0.7.6
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 +1 -0
- package/log-session.mjs +3 -2
- package/package.json +1 -1
- package/preserve-lines.mjs +3 -0
- package/stretch-evidence.mjs +25 -1
- package/worktrust.mjs +1 -1
package/README.md
CHANGED
|
@@ -164,6 +164,7 @@ nothing it does not:
|
|
|
164
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) |
|
|
165
165
|
| `context`, `routing` | how often the context was compacted and which context commands you used (compact, clear, resume, context, model, memory; never a command of your own), how many models answered and how often the model changed (0.7.4) |
|
|
166
166
|
| `steering` | the moments you stepped in while the agent worked (stopping it, or a message mid-task), how many changed what the agent did next, and how many were followed by a passing check (0.7.5) |
|
|
167
|
+
| `tools`, `complexity` | how many different tools the agent used, and the stretch's task complexity C1 to C5 by the rule complexity/1 (points for layers touched, tools, subagents, duration, a recovered failure, kinds of check and a delivery; the rule is in stretch-evidence.mjs), with its points and the rule's version (0.7.6) |
|
|
167
168
|
| `collector_version` | the CLI version that measured it |
|
|
168
169
|
| `seq`, `prev`, `hash` | the line's place, the hash of the line before it, and its own hash |
|
|
169
170
|
|
package/log-session.mjs
CHANGED
|
@@ -211,7 +211,7 @@ const excluded = (path) => excludes.some((text) => text && path.includes(text));
|
|
|
211
211
|
const { CODEX_ROLLOUT = /(?!)/, codexIdOf = (file) => String(file).split(/[\\/]/).at(-1).replace(/\.jsonl$/, ""), antigravityIdOf = (file) => String(file).split(/[\\/]/).at(-4), codexLines, codexRolloutFiles = function* () {}, codexCwd = () => null, ANTIGRAVITY_TRANSCRIPT = /(?!)/, antigravityLines, antigravityRoots = () => [], antigravityTranscripts = function* () {}, antigravityContext = () => ({}), rememberAntigravity = () => null } = (await import("./transcript-readers.mjs").catch(() => null)) ?? {};
|
|
212
212
|
// THE STRETCH'S DERIVED RECORD (0.7.4: split from this file): tool calls named by kind, verification, recovery, delegation,
|
|
213
213
|
// context and routing, for the local archive only. A copy without the module still measures and sends exactly as before.
|
|
214
|
-
const { callOf = (block) => ({ id: block.id, kinds: [], family: String(block.name), digest: "" }), deriveStretch = () => ({}) } = (await import("./stretch-evidence.mjs").catch(() => null)) ?? {};
|
|
214
|
+
const { callOf = (block) => ({ id: block.id, kinds: [], family: String(block.name), digest: "" }), deriveStretch = () => ({}), complexityOf = null } = (await import("./stretch-evidence.mjs").catch(() => null)) ?? {};
|
|
215
215
|
const { DATABASE_SESSION = /(?!)/, databaseLines = () => null, databaseSessions = function* () {} } = (await import("./session-databases.mjs").catch(() => null)) ?? {};
|
|
216
216
|
const DATABASE_CLIENTS = ["hermes", "goose", "opencode", "openclaw", "cursor", "copilot"]; // the registry's keys, the name each line carries
|
|
217
217
|
const LIVE_SOURCE = new RegExp(`^(codex|antigravity|${DATABASE_CLIENTS.join("|")}):`); // a sweep entry's id → the client it names (every database client, 0.6.16)
|
|
@@ -623,7 +623,8 @@ function payloadFor(stretch) {
|
|
|
623
623
|
at: new Date(stretch.to).toISOString(),
|
|
624
624
|
};
|
|
625
625
|
// WHAT STAYS ON THIS COMPUTER (0.7.1): the stretch's derived record rides beside the payload for the local archive, never in it.
|
|
626
|
-
|
|
626
|
+
// 0.7.6: and the stretch's complexity class, read from what the hook knows here (layers, subagents, duration) and the record.
|
|
627
|
+
if (stretch.derived) DERIVED.set(payload, { ...stretch.derived, ...(complexityOf ? { complexity: complexityOf(stretch.derived, { layers: Math.max(layers.length, layer ? 1 : 0), agentRuns: stretch.agents?.runs ?? 0, agentPeak: stretch.agents?.peak ?? 0, seconds: stretch.seconds }) } : {}) });
|
|
627
628
|
return payload;
|
|
628
629
|
}
|
|
629
630
|
|
package/package.json
CHANGED
package/preserve-lines.mjs
CHANGED
|
@@ -80,6 +80,9 @@ export function archiveLine(entry, behaviour = null, { ids = {}, collector } = {
|
|
|
80
80
|
const { moments, changed_course: changed, effective } = entry.steering;
|
|
81
81
|
if ([moments, changed, effective].every(whole) && moments > 0 && changed <= moments && effective <= changed) line.steering = { moments, changed_course: changed, effective };
|
|
82
82
|
}
|
|
83
|
+
// TOOL BREADTH AND COMPLEXITY (0.7.6): distinct tools; a class C1–C5 with its points and the rule's version.
|
|
84
|
+
if (whole(entry.tools) && entry.tools > 0) line.tools = entry.tools;
|
|
85
|
+
if (entry.complexity && /^C[1-5]$/.test(entry.complexity.class ?? "") && whole(entry.complexity.points) && /^complexity\/\d+$/.test(entry.complexity.rule ?? "")) line.complexity = { class: entry.complexity.class, points: entry.complexity.points, rule: entry.complexity.rule };
|
|
83
86
|
// The behaviour signals of this stretch (0.7.0): keys of the counter's rubric and whole counts, never a word of a turn.
|
|
84
87
|
if (behaviour && behaviour.signals && typeof behaviour.analyzer_version === "string" && /^counter@\d+\.\d+\.\d+$/.test(behaviour.analyzer_version)) {
|
|
85
88
|
const kept = Object.entries(behaviour.signals).filter(([key, count]) => SIGNAL.test(key) && Number.isInteger(count) && count > 0).sort();
|
package/stretch-evidence.mjs
CHANGED
|
@@ -171,8 +171,32 @@ function steeringOf(messages, { isHumanTurn, INTERRUPTED, textOf }) {
|
|
|
171
171
|
return { moments: moments.length, changed_course: changed.length, effective: changed.filter((moment) => moment.effective).length };
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
+
/**
|
|
175
|
+
* TASK COMPLEXITY C1 TO C5 (0.7.6; framework §14 "Task complexity C1-C5"), by a VERSIONED rule, `complexity/1`, every
|
|
176
|
+
* point of it stated here and in the README so anyone can recount a class. Proposed, not calibrated: it weighs evidence,
|
|
177
|
+
* it is not a score of anyone.
|
|
178
|
+
* layers touched ≤1: 0 · 2: 1 · 3+: 2 distinct tools used <3: 0 · 3–6: 1 · 7+: 2
|
|
179
|
+
* subagents none: 0 · ran: 1 · 3+ at once: 2
|
|
180
|
+
* measured duration <30 min: 0 · 30–120 min: 1 · >120 min: 2
|
|
181
|
+
* a failure recovered 1 kinds of check run 0: 0 · 1–2: 1 · 3+: 2
|
|
182
|
+
* something delivered 1
|
|
183
|
+
* points 0–1 → C1 · 2–3 → C2 · 4–6 → C3 · 7–9 → C4 · 10+ → C5
|
|
184
|
+
*/
|
|
185
|
+
export const COMPLEXITY_RULE = "complexity/1";
|
|
186
|
+
export function complexityOf(derived, { layers = 0, agentRuns = 0, agentPeak = 0, seconds = null } = {}) {
|
|
187
|
+
const step = (value, low, high) => (value >= high ? 2 : value >= low ? 1 : 0);
|
|
188
|
+
const points = step(layers, 2, 3) + step(derived.tools ?? 0, 3, 7) + (agentPeak >= 3 ? 2 : agentRuns > 0 ? 1 : 0)
|
|
189
|
+
+ (seconds === null ? 0 : seconds > 7200 ? 2 : seconds >= 1800 ? 1 : 0) + ((derived.recovery?.recovered ?? 0) > 0 ? 1 : 0)
|
|
190
|
+
+ step(Object.keys(derived.verification ?? {}).length, 1, 3) + (derived.delivery ? 1 : 0);
|
|
191
|
+
const tier = points >= 10 ? 5 : points >= 7 ? 4 : points >= 4 ? 3 : points >= 2 ? 2 : 1;
|
|
192
|
+
return { class: `C${tier}`, points, rule: COMPLEXITY_RULE };
|
|
193
|
+
}
|
|
194
|
+
/** How many different tools the stretch's agent used (framework L11: tool breadth); null without a tool call. */
|
|
195
|
+
const toolsOf = (messages) => { const names = new Set(); for (const message of messages) for (const call of message.calls ?? []) names.add(call.family.split("|")[0]); return names.size > 0 ? names.size : null; };
|
|
196
|
+
|
|
174
197
|
/** The stretch's whole derived record; `helpers` are the hook's own readers of a human turn, so both read it the same way. */
|
|
175
198
|
export function deriveStretch(messages, helpers) {
|
|
176
199
|
const context = contextOf(messages, helpers), routing = routingOf(messages), steering = steeringOf(messages, helpers);
|
|
177
|
-
|
|
200
|
+
const tools = toolsOf(messages);
|
|
201
|
+
return { ...verificationOf(messages, helpers), ...(context ? { context } : {}), ...(routing ? { routing } : {}), ...(steering ? { steering } : {}), ...(tools ? { tools } : {}) };
|
|
178
202
|
}
|
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.
|
|
74
|
+
const CLI_VERSION = "0.7.6";
|
|
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");
|