agent-bios 0.9.3 → 0.9.4

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.
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  name: workhorse
3
3
  description: WORKHORSE tier — bounded implementation, fixes, tests, and per-item judgment. Spawn decision-complete work with frozen scope/interfaces and a machine-checkable done-when; two or more independent items spawn in parallel.
4
- model: claude-sonnet-5
5
- effort: high
4
+ model: claude-opus-5
5
+ effort: medium
6
6
  ---
7
7
 
8
8
  Complete one bounded implementation, fix, or per-item judgment from a packet naming objective, frozen scope and inputs, allowed actions, output, done-when, and verification. Preserve out-of-scope behavior; batch independent reads; escalate missing decisions or authority instead of resolving them. Stage output for the main's acceptance — no external irreversible actions (push, install, credential, or remote mutation). Run the narrowest reliable changed-path check. Report: status, files_or_items_touched, evidence, verification or gap, risks_or_escalations.
@@ -162,7 +162,7 @@ Binding (2026-07-25):
162
162
  |---|---|---|
163
163
  | FRONTIER | Claude Fable 5 · GPT-5.6 Sol (read-only; max default, task-fit effort including Ultra) | bounded hardest decisions and verdicts |
164
164
  | HELM | Claude Opus 5 (xhigh) · GPT-5.6 Sol (xhigh main; main Ultra requires explicit selection; bounded FRONTIER Ultra allowed) | standing main; Codex defaults bypass, explicit sandbox narrows |
165
- | WORKHORSE | Claude Sonnet 5 · GPT-5.6 Terra (high) | implementation and per-item judgment |
165
+ | WORKHORSE | Claude Opus 5 (medium) · GPT-5.6 Terra (high) | implementation and per-item judgment |
166
166
  | SWEEP | Claude Haiku 4.5 · GPT-5.6 Luna (low) | clear repeatable scans and mechanical work |
167
167
  | VERIFIER-A | onto-mcp review | logic/authority kind; tier units per funnel |
168
168
  | VERIFIER-B | `ultracode-for-codex` CLI v0.4.5 (Codex-backed; callable from Claude or Codex) | code/execution kind |
@@ -187,7 +187,7 @@ Dispatch packets:
187
187
  | GPT-5.6 Terra WORKHORSE | outcome, frozen scope/inputs, authority, done-when, evidence/report, escalation; high |
188
188
  | GPT-5.6 Luna SWEEP | exact search space, rules, ambiguity behavior, stop, output; low; no architecture/debugging |
189
189
  | Claude Opus 5 HELM | xhigh for agentic work; high minimum for sensitive judgment; lower only when bounded/cost-led |
190
- | Claude Sonnet 5 WORKHORSE | exact scope, apply-to-all rules, tools, verification, report; high default |
190
+ | Claude Opus 5 WORKHORSE | exact scope, apply-to-all rules, tools, verification, report; high default |
191
191
  | Claude Haiku 4.5 SWEEP | closed, high-volume, latency-sensitive work with exact schema/examples |
192
192
 
193
193
  Use only task-relevant tools; parallelize independent calls. Worker report: `status`, `files_or_items_touched`, `evidence`, `verification`, `risks_or_escalations`. Official basis: OpenAI [model](https://developers.openai.com/api/docs/guides/latest-model?model=gpt-5.6), [migration](https://developers.openai.com/api/docs/guides/upgrading-to-gpt-5p6-sol), [prompting](https://developers.openai.com/api/docs/guides/prompt-guidance-gpt-5p6), [Codex models](https://learn.chatgpt.com/docs/models); Anthropic [subagents](https://code.claude.com/docs/en/sub-agents), [model effort](https://code.claude.com/docs/en/model-config).
@@ -162,7 +162,7 @@ Binding (2026-07-25):
162
162
  |---|---|---|
163
163
  | FRONTIER | Claude Fable 5 · GPT-5.6 Sol (read-only; max default, task-fit effort including Ultra) | bounded hardest decisions and verdicts |
164
164
  | HELM | Claude Opus 5 (xhigh) · GPT-5.6 Sol (xhigh main; main Ultra requires explicit selection; bounded FRONTIER Ultra allowed) | standing main; Codex defaults bypass, explicit sandbox narrows |
165
- | WORKHORSE | Claude Sonnet 5 · GPT-5.6 Terra (high) | implementation and per-item judgment |
165
+ | WORKHORSE | Claude Opus 5 (medium) · GPT-5.6 Terra (high) | implementation and per-item judgment |
166
166
  | SWEEP | Claude Haiku 4.5 · GPT-5.6 Luna (low) | clear repeatable scans and mechanical work |
167
167
  | VERIFIER-A | onto-mcp review | logic/authority kind; tier units per funnel |
168
168
  | VERIFIER-B | `ultracode-for-codex` CLI v0.4.5 (Codex-backed; callable from Claude or Codex) | code/execution kind |
@@ -187,7 +187,7 @@ Dispatch packets:
187
187
  | GPT-5.6 Terra WORKHORSE | outcome, frozen scope/inputs, authority, done-when, evidence/report, escalation; high |
188
188
  | GPT-5.6 Luna SWEEP | exact search space, rules, ambiguity behavior, stop, output; low; no architecture/debugging |
189
189
  | Claude Opus 5 HELM | xhigh for agentic work; high minimum for sensitive judgment; lower only when bounded/cost-led |
190
- | Claude Sonnet 5 WORKHORSE | exact scope, apply-to-all rules, tools, verification, report; high default |
190
+ | Claude Opus 5 WORKHORSE | exact scope, apply-to-all rules, tools, verification, report; high default |
191
191
  | Claude Haiku 4.5 SWEEP | closed, high-volume, latency-sensitive work with exact schema/examples |
192
192
 
193
193
  Use only task-relevant tools; parallelize independent calls. Worker report: `status`, `files_or_items_touched`, `evidence`, `verification`, `risks_or_escalations`. Official basis: OpenAI [model](https://developers.openai.com/api/docs/guides/latest-model?model=gpt-5.6), [migration](https://developers.openai.com/api/docs/guides/upgrading-to-gpt-5p6-sol), [prompting](https://developers.openai.com/api/docs/guides/prompt-guidance-gpt-5p6), [Codex models](https://learn.chatgpt.com/docs/models); Anthropic [subagents](https://code.claude.com/docs/en/sub-agents), [model effort](https://code.claude.com/docs/en/model-config).
@@ -62,8 +62,8 @@ model = "claude-opus-5"
62
62
  effort = "xhigh"
63
63
 
64
64
  [hosts.claude.tiers.workhorse]
65
- model = "claude-sonnet-5"
66
- effort = "high"
65
+ model = "claude-opus-5"
66
+ effort = "medium"
67
67
 
68
68
  [hosts.claude.tiers.sweep]
69
69
  model = "claude-haiku-4-5"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-bios",
3
- "version": "0.9.3",
3
+ "version": "0.9.4",
4
4
  "releaseDate": "2026-07-25",
5
5
  "description": "A thin, low-level instruction layer for LLM CLI agents: one set of principles and behavior whichever model you run. Deploys into $HOME by copy via an explicit `agent-bios install`.",
6
6
  "bin": {
@@ -274,7 +274,7 @@ for tier, (model, effort) in expected_launch_tiers.items():
274
274
  expected_claude_tiers = {
275
275
  "frontier": ("claude-fable-5", "max"),
276
276
  "helm": ("claude-opus-5", "xhigh"),
277
- "workhorse": ("claude-sonnet-5", "high"),
277
+ "workhorse": ("claude-opus-5", "medium"),
278
278
  "sweep": ("claude-haiku-4-5", "low"),
279
279
  }
280
280
  claude_launch_tiers = launch_profile.get("hosts", {}).get("claude", {}).get("tiers", {})
@@ -410,7 +410,7 @@ for guide_name in [
410
410
  for slot, claude_model in (
411
411
  ("FRONTIER", "Claude Fable 5"),
412
412
  ("HELM", "Claude Opus 5"),
413
- ("WORKHORSE", "Claude Sonnet 5"),
413
+ ("WORKHORSE", "Claude Opus 5"),
414
414
  ("SWEEP", "Claude Haiku 4.5"),
415
415
  ):
416
416
  if rows[slot] and claude_model not in rows[slot][1]:
@@ -2,7 +2,8 @@
2
2
  """Aggregate token usage & cost for a Claude Code session (main + subagents).
3
3
 
4
4
  Usage: session-cost.py <session>.jsonl [...]
5
- Reads the session transcript and, if present, <session-dir>/subagents/agent-*.jsonl.
5
+ Reads the session transcript, splitting main-loop from subagent (sidechain)
6
+ usage, and also picks up <session-dir>/subagents/agent-*.jsonl when present.
6
7
  Prints per-source, per-model token sums, modeled cost, and wall-clock span.
7
8
  """
8
9
  import json, sys, glob, os
@@ -28,9 +29,17 @@ def price_for(model):
28
29
  return None
29
30
 
30
31
  def scan(path):
31
- """-> {model: {in,out,cr,cw5,cw1,turns}}, (t_min, t_max)"""
32
- agg, tmin, tmax, seen = {}, None, None, set()
33
- for line in open(path):
32
+ """-> {(scope, model): {in,out,cr,cw5,cw1,turns}}, (t_min, t_max), {scope: agent_ids}
33
+
34
+ A single API response is written to the transcript several times as it
35
+ streams, each line carrying output_tokens *so far* (e.g. 2, 2, 2, 540).
36
+ Keep the record with the LARGEST output_tokens per message id: keeping the
37
+ first one instead under-reports subagent output by ~95%, because sidechain
38
+ messages get snapshotted far more often than main-loop ones do.
39
+ """
40
+ best, tmin, tmax = {}, None, None
41
+ agents = {"main": set(), "sub": set()}
42
+ for line in open(path, errors="replace"):
34
43
  try:
35
44
  d = json.loads(line)
36
45
  except json.JSONDecodeError:
@@ -42,11 +51,17 @@ def scan(path):
42
51
  u, model = m.get("usage"), m.get("model")
43
52
  if not u or not model or model == "<synthetic>":
44
53
  continue
45
- rid = m.get("id") or d.get("requestId")
46
- if rid in seen:
47
- continue # one usage record per API request
48
- seen.add(rid)
49
- a = agg.setdefault(model, dict(inp=0, out=0, cr=0, cw5=0, cw1=0, turns=0))
54
+ scope = "sub" if d.get("isSidechain") else "main"
55
+ if d.get("agentId"):
56
+ agents[scope].add(d["agentId"])
57
+ key = (scope, m.get("id") or d.get("requestId"))
58
+ prev = best.get(key)
59
+ if prev is None or u.get("output_tokens", 0) > prev[1].get("output_tokens", 0):
60
+ best[key] = (model, u)
61
+
62
+ agg = {}
63
+ for (scope, _), (model, u) in best.items():
64
+ a = agg.setdefault((scope, model), dict(inp=0, out=0, cr=0, cw5=0, cw1=0, turns=0))
50
65
  a["inp"] += u.get("input_tokens", 0)
51
66
  a["out"] += u.get("output_tokens", 0)
52
67
  a["cr"] += u.get("cache_read_input_tokens", 0)
@@ -57,7 +72,7 @@ def scan(path):
57
72
  else:
58
73
  a["cw5"] += u.get("cache_creation_input_tokens", 0)
59
74
  a["turns"] += 1
60
- return agg, (tmin, tmax)
75
+ return agg, (tmin, tmax), agents
61
76
 
62
77
  def cost(model, a):
63
78
  p = price_for(model)
@@ -71,19 +86,27 @@ def fmt(n):
71
86
 
72
87
  def report(session_path):
73
88
  base = session_path[:-6] # strip .jsonl
74
- sources = [("main", session_path)]
89
+ sources = [(None, session_path)]
75
90
  sources += [(os.path.basename(f)[:-6], f)
76
91
  for f in sorted(glob.glob(os.path.join(base, "subagents", "*.jsonl")))]
77
92
  print(f"\n=== {os.path.basename(session_path)} ===")
78
93
  grand, unpriced = 0.0, []
79
- hdr = f"{'source':<38}{'model':<22}{'turns':>6}{'input':>9}{'output':>9}{'cache_rd':>10}{'cache_wr':>10}{'cost$':>9}"
94
+ hdr = (f"{'source':<38}{'model':<22}{'turns':>6}{'input':>9}{'output':>9}"
95
+ f"{'cache_rd':>10}{'cache_wr':>10}{'cost$':>9}")
80
96
  print(hdr); print("-" * len(hdr))
81
97
  span_min = span_max = None
82
- for name, path in sources:
83
- agg, (tmin, tmax) = scan(path)
98
+ for label, path in sources:
99
+ agg, (tmin, tmax), agents = scan(path)
84
100
  if tmin:
85
101
  span_min = min(span_min or tmin, tmin); span_max = max(span_max or tmax, tmax)
86
- for model, a in agg.items():
102
+ for (scope, model), a in sorted(agg.items()):
103
+ if label is not None:
104
+ name = label
105
+ elif scope == "sub":
106
+ n = len(agents["sub"])
107
+ name = f"subagents (n={n})" if n else "subagents"
108
+ else:
109
+ name = "main"
87
110
  c = cost(model, a)
88
111
  cs = f"{c:9.2f}" if c is not None else " ?"
89
112
  if c is None: