3
Methodology/Calibration
oleks edited this page 2026-07-29 17:36:49 +03:00
This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Calibration — static pass (bin/plugin-inventory), 2026-07-29

First calibration run of the static pass against four real plugins from this workspace, per design/tasks.md 2.5. Default thresholds from references/signals-catalog.md were used as-is — no tuning was needed; they already produce the ordering the design doc predicted.

Raw numbers

Plugin Skills Agents Skill body words Agent body words Script LOC Script coverage Duplicated blocks Hook/prose drift pairs
token-budget 3 1 2932 686 606 0.167 0 0
worktree-discipline 5 0 4903 0 1730 0.353 0 7
anxious 6 5 9622 18290 1477 0.053 1 3
memory 1 1 1303 647 1202 0.616 0 3

The compound smell check

design/spec.md §5.1 defines the loudest static smell as verb_ratio > 0.6 (a skill's prose is script-verb-dominated) co-occurring with low overall script_coverage (< 0.15, i.e. little of that intent is actually backed by a script). Checking each plugin:

  • token-budget: 2 skills trip verb_ratio > 0.6 (session-hygiene, token-audit) but overall script_coverage is 0.167 — above the low-coverage threshold. Reads as: the plugin talks like it has procedures, but 606 LOC of cc-tokens already backs them. Matches design/spec.md's own worked example verbatim: "already cut."
  • anxious: 1 skill trips verb_ratio > 0.6 (kanban-flow), AND overall script_coverage is 0.053 — well under the low-coverage threshold. This is the only plugin of the four where the compound smell actually fires. Matches design/spec.md's own worked example: "real candidates," headlined by agents/steward.md's label-taxonomy reconciliation.
  • worktree-discipline: no skill trips verb_ratio > 0.6, script_coverage is high (0.353). Not a static-pass candidate by the verb/coverage smell — but 7 hook/prose-drift pairs fired (own-worktree-creation restates the WTD_* env-var contract from policy.sh/worktree-create.sh/etc. in prose), a different finding shape: not "should be a script" but "two sources of truth for the same script's contract."
  • memory: no skill trips verb_ratio > 0.6, script_coverage is highest of the four (0.616). 3 drift pairs (mempalace skill restates add_drawer/kg_add/etc. identifiers from its own hooks) — same "two sources of truth" shape as worktree-discipline, not a script-offload candidate.

Result

token-budget cleanest, anxious richest in candidates — the ordering design/spec.md §5.1 predicted by hand, reproduced mechanically by the compound smell check with zero threshold tuning. verb_ratio_high: 0.6 and script_coverage_low: 0.15 in references/signals-catalog.md are confirmed as-is; no changes made.

Open finding for Phase 4: the hook/prose-drift signal (worktree-discipline: 7 pairs, memory: 3, anxious: 3, token-budget: 0) tracks a different failure mode than the verb/coverage smell — restated configuration contracts, not un-scripted algorithms — and the rubric/classification agent should treat it as a distinct candidate category rather than folding it into the same verb-ratio-driven scoring.


Calibration — dynamic pass (bin/offload-scan), 2026-07-29

Real-history sanity run, --plugin anxious --days 30, against the live ~/.claude/projects (1.7 GB, ~4800 transcript files). Per design/tasks.md 3.9.

Raw numbers

Measure Value
Wall clock 94 s
Peak RSS 29 MB
Processes 1 (streaming, no fan-out)
Sessions touched by target 165
Attributed turns 4,915
Candidate turns (coverage denominator) 237,900
Attribution coverage 0.021
Audited weighted tokens 32.6 M
Plugin-wide mechanical share 0.101
Invocations reconstructed 665

29 MB peak over a 1.7 GB history confirms the O(attributed turns + sessions) bound (spec S8). Independent verification during review: --days 3 (tighter window) ran in 8 s; --days 30 re-run varied 90 s to a 180 s timeout on a separate attempt — consistent with real system-load variance on a shared, multi-session laptop (this environment routinely runs several concurrent Claude Code sessions), not a script defect. No fan-out or stuck processes observed in either case.

Two spec deviations, both forced by what the real transcripts contain (not shortcuts)

  1. Agent attribution is attributionAgent, not agentName. agentName exists but lives on a separate type: "agent-name" line mapping a sessionId to a human display label (a Workflow session name) — it never appears on an assistant line. The real field is attributionAgent on subagent sidechain transcripts (<session>/subagents/*.jsonl), which also carry attributionPlugin, so the plan's assumed dependency on plugin-inventory's agent list turned out to be unnecessary.
  2. attributionSkill is sometimes bare, sometimes plugin-qualified. Normalized: an unqualified value is prefixed with the attributed plugin.

cc-tokens dependency: import, not shell-out — resolution order held

Resolution order matches decision 0.1 exactly (PATH → cache-glob newest semver → fail loudly, never vendored). But cc-tokens' real CLI surface (daily | sessions | projects | models | composition | hogs | context) has no query shaped like "weighted tokens for this specific set of turns" — context --json is per-session and omits the message.id/requestId join key needed for the FR-3.2 dedup. Shelling out cannot express the query, so offload-scan imports the cc_tokens module directly (guarded — a missing Rec/price_for/parse_day fails loudly) and calls Rec.cost/Rec.weighted for every number. Pricing table and tier normalization still have exactly one home; nothing is reimplemented.

This makes the plan's proposed long-term fix concrete: cc-tokens attribute --by skill|plugin|agent --json upstream in token-budget would let offload-scan drop the import for a subprocess call. Tracked as Phase 8.3 (optional).

Open finding for Phase 4: coverage denominator

Coverage of 0.021 is a real finding (FR-3.4 doing its job), not a bug — this environment's sessions are long multi-topic marathons, so one skill invocation inside a 5,000-turn session drags the ratio down hard. The dynamic-pass agent (Phase 4) should lead with this number and treat a low-coverage dynamic pass as weak evidence; consider also reporting a second, tighter denominator (turns within the invocation windows themselves) alongside the session-wide one, so "we saw 2% of the sessions" isn't confused with "we saw 2% of the plugin's work." Left as a Phase 4 design decision, not resolved here.

Also observed: turns attributed to anxious can execute inside another plugin's subagent (e.g. repo-worker, cluster:gitea-agent) — reported honestly rather than discarded, likely relevant to Phase 4's fan-out analysis. fanout_multiplier is reported unclamped and can read below 1 (0.20.66 observed) — a tightly-briefed subagent can genuinely carry less context than a marathon main session. Diagnostic only; deliberately excluded from offload_value.


Calibration — rubric gate (bin/boundary-classify), 2026-07-29

Per design/tasks.md 4.4 — the load-bearing gate. Both checks below must pass before Phase 5/6 may start; both do.

Gate 1 — token-budget → zero high-confidence candidates

PASS.

candidates: 2 | high_confidence: 0 | to_file: 0
conclusion: "nothing to offload here"

token-budget/token-audit/opening-command-sequence     -> pure-inference / low / no-offload
token-budget/token-audit/finding-to-remediation-table -> pure-inference / low / no-offload

Two candidates were surfaced and both declined on the rubric, rather than none being examined. The opening-sequence candidate fails T4: which diagnostic to open with depends on what the user asked, which is not in the inputs — no overrule case is producible because a human would overrule it often (rubric §5's inverse paragraph: frequent overrule means it isn't a position-1 script at all). The dispatch-table candidate fails T1/T2/T4 (routing a prose finding depends on user intent).

Static signals that could have produced a false positive and did not: verb ratios of 0.667 and 0.714, both above the 0.6 smell threshold from the Phase 2 calibration. They don't fire here because the smell is a conjunction — high verb ratio with no bin/ script behind it — and every command these skills prescribe already invokes the 606-LOC cc-tokens.

Gate 2 — worktree-discipline with bin/worktree-audit masked out → known cut rediscovered at high confidence

PASS.

candidates: 3 | high_confidence: 1 | to_file: 1 | drift_notes: 1

worktree-discipline/sweep-worktrees/worktree-safety-classification
    -> llm-over-script-digest / HIGH / file   (T1-T5 all pass, triple complete)
worktree-discipline/dev-server-sync/read-amplification
    -> pure-inference / low / no-offload
worktree-discipline/own-worktree-creation/env-contract-restated
    -> hook-prose-drift / low / drift-note

The mask (tests/calibration/mask-worktree-audit.py, reproducible against the real sibling checkout, never touches it) drops script_loc 1730→407 and script_coverage 0.353→0.083, and removes the command block that invoked the masked script. What's left in sweep-worktrees is the raw plumbing, including the recorded correction git for-each-ref --format='%(upstream)' refs/heads/<branch> # must be refs/remotes/… — this is why the cut is rediscoverable from the inventory JSON alone, without appealing to outside knowledge of the incident.

The overrule case supplied for this candidate: a worktree that is clean, fully pushed, and ahead=0 classifies as "reclaimable" by the script, but is a sibling session's live checkout that simply hasn't written anything to disk yet — a competent human says "no, not that one, it's in use," and the script cannot see session liveness because it isn't in git state.

Two negative controls in the same run matter as much as the positive one. dev-server-sync is the loudest cost signal in the target — 76% of audited spend, read_amplification 392.5 — and the rubric declines it: the amplification comes from reading the user's project files, not a procedure the plugin owns (T1/T2/T4 all fail, MTR 0.057, no recurring n-gram). Scripting it would be premature crystallization. Hook/prose drift is carried as its own category with a drift-note verdict (fix: point at hooks/policy.sh instead of restating its env-var contract in prose) — it never competes on token value against real offload candidates.

One real iteration — recorded honestly

The first passing run graded the masked worktree candidate high confidence but returned boundary-question rather than file, because thin dynamic evidence (1 invocation, 43 turns) was blocking filing outright. That was wrong: measurement gates the value claim, not the correctness claim — under FR-2.4 a plugin with zero transcript history must stay auditable on its definition alone. Fixed so measured (≥3 invocations, ≥30 attributed turns) applies the §5.2.7 2%-of-spend threshold as written, while thin/unmeasured evidence still files on the static case with the value claim explicitly marked unproven. Both gates still pass; the known-correct cut now correctly reaches file.

Coverage-denominator decision (the Phase 3 open finding)

Decided: keep the session-wide denominator, add no second one, relabel what it measures. A tighter "turns within invocation windows" denominator is near-tautological — an invocation window is a contiguous run of attributed turns, so that ratio is ~1.0 by construction; it would read as reassuring while measuring nothing. The session-wide ratio doesn't measure completeness — it measures dilution (how much of those sessions was other work), which is the real content of the 0.021 finding against anxious. The analyst agent reports it as dilution, and reports completeness separately via absolute counts plus named structural blind spots (hook-driven work carries no attribution at all — the agent must name the target's hooks and say their cost is invisible).

Result

Both calibration gates pass, with one honestly-recorded iteration. bin/boundary-classify makes the FR-4.2 filing gate (no overrule case → boundary question, never filed) mechanically enforced rather than merely asserted in agent prose — the determinism-test outcomes and falsifiability triple are irreducibly inference (T2/T4 are semantic, judged by the analyst against real plugin-inventory/offload-scan output), but grading them into a confidence and file/don't-file verdict is a pure lookup table (rubric §6 + §5.2.7), and leaving that in prose would have been the exact anti-pattern this plugin reports on. tests/classify.test.sh: 23 assertions including both gates, bash tests/run-all.sh: 67 assertions total, exit 0.

Phase 5 and 6 are unblocked.