Borrowing it
Nothing to install: this file belongs to zkysar1/Claude-Mind. Take a copy, put it at the same path in your own repository, and replace the rules that are about this project with yours.
curl -O https://raw.githubusercontent.com/zkysar1/Claude-Mind/main/.claude/skills/agent-completion-report/SKILL.mdgit clone --depth 1 https://github.com/zkysar1/Claude-MindWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/zkysar1/claude-mind/agent-completion-report)<a href="https://agentmods.dev/skills/zkysar1/claude-mind/agent-completion-report"><img src="https://agentmods.dev/badge/skills/zkysar1/claude-mind/agent-completion-report/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/zkysar1/claude-mind/agent-completion-report"><img src="https://agentmods.dev/badge/skills/zkysar1/claude-mind/agent-completion-report.svg" alt="Reviewed on agentmods" width="80" height="20"></a>- NVIDIA SkillSpector pass
What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00112 | $0.15390 |
| Opus 5 | $0.00056 | $0.07695 |
| Sonnet 5 | $0.00022 | $0.03078 |
| Haiku 4.5 | $0.00011 | $0.01539 |
Grade A, and why
agent-completion-report scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured today.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 902 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Agent Completion Report
Displays a delta summary of what changed since the last status report.
Valid from ANY state. User-invocable AND agent-callable. Writes the single latest-pointer file agents/<agent>/COMPLETION-REPORT.md (its git history is the permanent archive — there is no timestamped reports/ archive; that directory was abolished by the file-model normalization).
Step 0: Load Conventions — Bash: load-conventions.sh with each name from the conventions: front matter. Read only the paths returned (files not yet in context). If output is empty, all conventions already loaded — proceed to next step.
Phase 1: Determine Report Window
1. Determine "since" timestamp (first match wins):
a. If --since argument provided: use that timestamp
b. Read agents/<agent>/session/last-report-timestamp → use if present
c. Read agents/<agent>/session/handoff.yaml → use session_start if present
d. If none found:
since = null → show lifetime totals only, skip deltas
Label report as "Lifetime" instead of delta window
1.5. Positive-state audit (verify-before-assuming.md Positive File-State Claims):
Any narrative reference in the generated report to a specific framework file
(`handoff.yaml`, `aspirations.jsonl`, `self.md`, `program.md`, etc.) that
describes its current state or contents MUST be preceded by an in-turn Read
of that file. Do not narrate from prior-session memory or from the
aspirations-compact index — read the actual file before stating what it says.
Recommended probe at report-generation time, for each referenced file:
```bash
py core/scripts/positive-state-gate.py --claim "<narrative sentence>" --evidence "<concatenated Read outputs from this turn>"
Exit 1 = re-read the file and re-state the claim from fresh evidence.
## Phase 2: Gather Delta Data
All data comes from framework scripts — no direct JSONL reads.
-
Journal entries since last report Bash: bash core/scripts/journal-read.sh --recent 10 → Filter entries where date >= since date → Extract goals_completed, goals_attempted, key_events
-
Aspirations completed since last report Bash: bash core/scripts/aspirations-read.sh --archive → Filter where completed_at >= since date → Count and list titles
⚠ THIS IS A WINDOW COUNT AND ONLY A WINDOW COUNT. When
sinceis null (the"Lifetime" branch at step 0) the filter goes vacuous and this degrades into a
RECORD ENUMERATION over archive ∪ live — which no longer reaches the lifetime
population. The 2026-08-14T12:56 metric-neutral eviction moved 5,003 terminal
goal records out of the live world queue into each aspiration's
archived_census, and the evictor DELIBERATELY does not re-append them to thearchive store (its docstring says why), so they survive only in .history blobs.
Measured cc-08 2026-08-15 (g-001-04): enumeration over archive(370 asps) +
live(30 world, 1 agent) = 2,679 completed, against 7,084 done of 9,854 from the
census-folded
--summaryat step 3 — a 4,405-goal gap, all of it invisible here.RULE: take LIFETIME totals from step 3's
--summary, which folds the census;keep this enumeration for the WINDOW count, where it stays exact. Window safety
was verified separately: of the 4,972 goals present in the 08-14T12:53 .history
blob but absent from BOTH live and archive, ZERO have completed_at >=
2026-08-13T20:25:22. Lifetime figures are NOT comparable across the 2026-08-14
boundary by either method — say that, rather than reporting a drop.
-
Active aspirations progress Bash: bash core/scripts/aspirations-read.sh --summary
3b. Goal details for completed goals From the compact aspirations data (step 8) and archive data (step 2), resolve each goal ID from goals_completed into {id, title, aspiration_id, aspiration_title}. Group by aspiration. This provides the detailed goal listing for Phase 3.
3c. Knowledge-debt closures in the report window
From the same completed-goal set as 3b, collect goals where
closes_knowledge_debt is a non-empty list. For each, record
{goal_id, title, closes_knowledge_debt}. Aggregate:
debt_closure_events= count of such goalsdebt_closure_node_keys= unique union of node_keys closeddebt_closure_sample= up to 3 {goal_id, title, node_keys} entries This surfaces the semantic override firings from aspirations-execute Phase 4-post ("DEBT-CLOSURE OVERRIDE") without requiring log scanning.
-
Hypotheses resolved since last report
BOTH stages are REQUIRED — a record can be archived within the report
window, so a resolved-only fetch UNDERCOUNTS any multi-day report while
staying exact for a same-session one. That split is why this site is the
least visible of the four and survived longest. Measured 2026-08-04T03:33
(bravo, hostname cc-05, uname -r 6.8.0-136-generic): of the scoreable
records in each trailing window,
--stage resolvedalone sees 100% at 2dbut only 75.9% at 7d and 29.8% at 30d — i.e. a week-long report silently
drops a quarter of its own subject matter. (g-115-4866.)
⚠ THOSE PERCENTAGES HAVE DECAYED — RE-MEASURE, DO NOT QUOTE THEM. Two
independent measurements on 2026-08-15, hours apart on different boxes,
each carrying its denominator (guard-3542 — a coverage rate over a moving n
is meaningless without it):
bravo, cc-05, 6.8.0-137-generic, 216.1h window: 47 of 199 = 23.6% at 9d.
Store split at that instant: 50 resolved vs 1,127 archived.
alpha, cc-08, 6.8.0-137-generic, 48.5h window: 22 of 35 = 62.9% at 2d.
Store split at that instant: 34 resolved vs 1,148 archived.
THE SECOND ONE IS THE LOAD-BEARING DATAPOINT, and it breaks the model the
rest of this comment implies. The 2026-08-04 row reads coverage as a
function of WINDOW WIDTH (100% at 2d, degrading to 29.8% at 30d), which
invites the reading that a short report is safe. It is not: the 2-DAY
figure itself fell 100% -> 62.9% in eleven days. A same-session report is
the ONLY case still near-exact, and even that is not guaranteed to hold.
So the resolved stage is not a time window with a fixed width; its
effective lookback is set by ARCHIVAL CADENCE, and that cadence keeps
tightening (2026-08-04: 86 resolved over ~4.5d; 2026-08-15: 50 then 34,
both over ~2.3d or less, at a HIGHER resolution rate).
RE-MEASURED 2026-08-18 (echo, cc-03, 6.8.0-137-generic, 15.35h report
window). Store split at that instant: 49 resolved vs 1,204 archived.
same-day (2026-08-18): 6 of 6 = 100%
spanning 08-17 (~39h): 27 of 38 = 71.1%
lifetime: 47 of 811 = 5.8%
THE 2-DAY FIGURE WENT BACK UP — 62.9% (08-15) -> ~71% (08-18). So the
decay narrated above is NOT monotonic, and reading it as a trend line is
the wrong model: it oscillates with archival cadence. Do not "correct" the
08-15 row toward this one; both are true readings of a quantity that moves
in both directions, which is exactly why the instruction is to re-measure
rather than to quote.
AND DISCOUNT THE 100% (guard-2303 — check the instrument's resolution
before reporting a change-detection result):
outcome_dateis DATE-ONLY,so a same-DAY window and the field's granularity are the same size. A
same-day 100% is partly the instrument saying "I cannot resolve inside
this window", not purely the store being complete. The 71.1% row spans two
calendar days and is the more informative one.
SERIES — each entry (date, window, resolved-stage coverage, denominator).
APPEND YOUR READING HERE; do not add another dated paragraph. Five had
accumulated by 2026-08-21 and the sixth would have cost more to read than
the number is worth (learning-philosophy.md rule 5):
08-04 2d 100% (n≈?) · 08-15 2d 62.9% (n=35) · 08-18 39h 71.1% (n=38)
08-19 79.6h 73.5% (n=68) · 08-21 20.2h 81.1% (n=37, split 44/1261)
08-21 9.7h 65.0% (n=20, split 48/1262) <- SECOND 08-21 reading, ~8h later
08-21 9.5h 75.0% (n=28, split 56/1262) <- THIRD 08-21 reading, ~2h later
08-22 25h(date-floored) 100% (n=22, split 60/1262)
08-22 15.2h(date-floored 16.2h) 100% (n=14, split 62/1278)
08-24 32.5h(date-floored 48.8h) 86.2% (n=29, split 73/1279) <- 3 CALENDAR DAYS
08-24 34.8h(date-floored 48.8h) 87.5% (n=32, split 76/1279) <- SAME DAY, ~13min later, DIFFERENT BOX
08-24 63.3h(date-floored 83.9h) 83.3% (n=66, split 78/1279)
08-25 13.3h(date-floored 25.3h) 63.0% (n=27, split 40/1335) <- BACKLOG DRAINED 78->40, COVERAGE FELL WITH IT
08-29 49.4h(date-floored 3 calendar days) 90.3% (n=31, split 50/1397)
08-30 99.94h(date-floored 5 calendar days) 93.3% (n=60, split 58/1397) <- WIDEST WINDOW AND HIGHEST NON-100%, TOGETHER
08-31 102.5h 48.7% (n=39, split 22/1554) <- WIDER THAN 08-30 AND HALF ITS COVERAGE, ONE DAY LATER
08-31 29.9h(date-floored 46.8h) 100% (n=14, split 22/1554) <- SAME BOX-DAY, IDENTICAL STORE SPLIT, NARROWER WINDOW
09-02 27.85h(date-floored 2 calendar days) 100% (n=16, split 24/1577) <- NEAR-EXACT REPLICATION OF THE ROW ABOVE, 2 DAYS LATER
09-02 21.2h(date-floored 37.2h) 100% (n=16, split 24/1577) <- SMALLEST BACKLOG SINCE 08-31 (24), STILL 100% ON A ~1-DAY WINDOW; consistent with the 08-31 narrow row, not with the wide one
09-02 9.76h(date-floored 1 calendar day) 100% (n=20, split 31/1577) <- THIRD 09-02 READING. Backlog GREW 24->31 and coverage HELD at 100%; the within-window backlog model predicts UP and 100% is the ceiling, so this row is SATURATED and tests nothing. Same-day window, so guard-2303 discounts it too. Recorded for the denominator, not as evidence.
09-05 28.06h(date-floored 2 calendar days) 100% (n=21, split 57/1588) <- FOURTH consecutive 100%. Backlog GREW 31->57 (largest since 08-24's 78) and coverage HELD at the ceiling, which the within-window backlog model already predicts -- so this row is SATURATED and tests nothing, exactly like the 09-02 row above. Window spans 2 calendar days, so guard-2303's date-floor discount does NOT excuse it. Recorded for the denominator.
09-07 21.5h(date-floored 2 calendar days) 100% (n=7, split 35/1619) <- FIFTH consecutive 100%, and the FIRST row where the backlog DRAINED (57->35) without coverage falling with it. Both prior drains fell (08-25 78->40 -> 63.0%; 08-31 58->22 -> 48.7%), so this is counter-evidence to the within-window backlog model -- but n=7 is the SMALLEST denominator in the series and one archival sweep moves it tens of points. Recorded for the denominator, NOT as a refutation.
THE 08-30/08-31 PAIR IS THE CLEANEST WIDTH-CONTROLLED TEST IN THIS SERIES AND IT
SETTLES THE ARGUMENT: 99.94h -> 93.3%, then 102.5h -> 48.7% ONE DAY LATER. The
window got WIDER and coverage HALVED, so width cannot be the driver in either
direction (08-30 already falsified 'wider drives coverage down'; this falsifies
the converse too). The resolved backlog drained 58 -> 22 across that same day and
coverage tracked it down -- the identical signature as the 08-25 row. Backlog is
the driver; width is noise. Note also this window's outcome mix, which no prior
row records: 159 in-window records but only 39 SCOREABLE (26 CONFIRMED, 13
CORRECTED) against 113 EXPIRED + 7 UNRESOLVABLE. Compute coverage over SCOREABLE
only or the row is not comparable to any other -- an all-records count here would
have reported 12.6% and silently entered a different quantity into the series.
THE 08-30 ROW FALSIFIES THE WIDTH HALF OF THAT MODEL. It is the WIDEST window
in the series (99.94h, 1.6x the prior widest) and scored the HIGHEST non-100%
(93.3%) -- so "a window wide enough to cross the horizon pulls in archived rows
and drives coverage DOWN" is not a law. Only 4 of its 60 in-window records had
reached the archived stage at all, against a 58-deep resolved backlog. Backlog,
not width, is what the series keeps measuring.
THE THIRD 08-24 ROW REFINES THE BACKLOG MODEL THE OTHER TWO PROPOSED, and it is the
only row that can: it carries the HIGHEST backlog yet recorded (78 resolved) and still
scored the LOWEST of the three, because its window is ~1.7x wider and reaches back past
the archival horizon into days already swept. So backlog is not the sole driver either.
Reconcile them this way: WITHIN a fixed window, coverage tracks the backlog (the 13-min
pair proves that); ACROSS window widths, a window wide enough to cross the horizon pulls
in archived rows and drives coverage DOWN regardless of backlog. Both effects are real at
different scales, and neither licenses quoting a row — which is what the series already says.
THE TWO 08-24 ROWS CONFIRM THE DRIVER DIRECTLY, and they are the cleanest pair in
the series for it: 13 minutes apart, DIFFERENT BOXES (cc-0x, then foxtrot on
LAPTOP-3IOFCNEO / WSL2 6.18.33.2), near-identical window width, and coverage ROSE
86.2% -> 87.5% while the resolved stage grew 73 -> 76 against an unchanged 1279
archived. Coverage tracked the BACKLOG, not the window and not the box. If window
width or box identity set coverage, these two would not move together like that.
THE FIRST 08-24 ROW IS THE HIGHEST NON-100% READING BEFORE IT AND IT IS NOT A
DATE-FLOOR ARTIFACT: it spans three calendar days, so guard-2303 does not
explain it. It is high because the RESOLVED STAGE WAS BACKED UP -- 73 resolved
against 44-62 in every prior row -- i.e. coverage rose because ARCHIVAL fell
behind, not because the instrument improved. Same driver, opposite direction
from the 08-15 low. Nothing here predicts your run; measure your own.
THE TWO 08-22 ROWS ARE BOTH 100% AND NEITHER MEANS THE INSTRUMENT IMPROVED: both
windows are SAME-DAY, and outcome_date is date-only, so the floor swallows the
whole window and the field cannot resolve inside it (guard-2303). The second row
scored 100% on a window 10h NARROWER than the first — read together with the
08-21 trio, that is a fourth demonstration that width is not the driver.
THE THREE 08-21 ROWS ARE THE CHEAPEST PROOF OF THE INSTRUCTION BELOW: same day,
same box. 81.1% (20.2h) -> 65.0% (9.7h) -> 75.0% (9.5h). If window width set
coverage, the two NARROW rows would agree — they are 0.2h apart and they differ
by TEN POINTS, while the WIDEST row scored highest of all three. The store
barely moved across the whole day (44/1261 -> 48/1262 -> 56/1262). Archival
cadence is the only driver, so no row predicts any other.
READ THE SERIES, NEVER A ROW. It is not monotonic and not a function of
window width — a 3.3-DAY window (73.5%) beat a 2-DAY one (62.9%), and a
20.2h window beat both. Only archival cadence sets it, so a NARROW window
buys you nothing and no row here predicts your run.
The instruction is unchanged and is now stronger: read BOTH stages. What
changes is that no fixed percentage here can be trusted as guidance — the
number is a snapshot of a moving quantity (guard-390: an artifact
describing external state must cite what keeps it current; nothing does
here). COMPUTE the coverage in your own run — you already hold both
populations — and correct this comment in passing when it has moved again.
Bash: bash core/scripts/pipeline-read.sh --stage resolved Bash: bash core/scripts/pipeline-read.sh --stage archived → Filter the UNION where outcome_date >= since date → Count confirmed vs corrected
-
Overall pipeline accuracy Bash: bash core/scripts/pipeline-read.sh --accuracy
-
Knowledge tree stats Bash: bash core/scripts/tree-read.sh --stats
-
Guardrails / reasoning bank / pattern signatures counts Bash: bash core/scripts/guardrails-read.sh --count Bash: bash core/scripts/reasoning-bank-read.sh --count Bash: bash core/scripts/pattern-signatures-read.sh --count → Each returns {"count": N} — a RECORD count. 56 bytes for all three. They feed exactly one line of the report (## Knowledge); the CONTENT of these stores is never used here.
WAS
--summary+ "Count lines from each" until 2026-08-29 (g-115-6742):2,106,400 bytes loaded at EVERY /stop to produce three integers, two of
them WRONG. Counting summary LINES is not a record count, and it errs in
BOTH directions at once — which is why it read as a small single-store
defect for ten days instead of a defect in all three:
+N a field carrying an embedded newline emits a continuation line
(3 guardrails today;
rule[:80]in reasoning_bank.py truncatesbut does not strip \n — corroborated by guardrail-manifest.sh
--stats, which independently reports "3 wrapped-text ... folded")
-1 NONE of the three outputs ends with a trailing newline, and
wc -lcounts NEWLINES — so every store undercounts by 1Measured 2026-08-29 (alpha, cc-07): guardrails 5194 real lines / 5191
records, where wc -l said 5193 because the two errors partially
cancelled; reasoning-bank and pattern-signatures were BOTH off by -1,
though the goal that filed this had recorded them as delta 0.
Do NOT reintroduce a line count. --summary still exists if the CONTENT
is ever genuinely needed; this section has never needed it.
-
Pending questions + user goals Bash: bash core/scripts/pending-questions-read.sh --status pending → JSON array of pending entries. This reader is shape-tolerant (flattens the dict-wrapper / list-with-wrapper / bare / mixed on-disk shapes via the same _load_questions logic the sweep sibling uses, rb-1786). Do NOT hand-roll a naive top-level
status == "pending"scan of the raw YAML — it silently SKIPS entries nested inside a{questions: [...]}wrapper (g-115-3039). Bash: bash core/scripts/load-aspirations-compact.sh → IF path returned: Read it (compact data has IDs, titles, statuses, participants — no descriptions/verification) Filter goals with participants containing "user"⚠ AND NO completed_date — ON ANY RECORD, INCLUDING THE COMPLETED ONES. So a
window-scoped completion count computed from this index returns 0 regardless of
actual activity, and the 0 reads as a quiet fleet rather than as a missing field
(rb-245 class). Measured cc-08 2026-08-17: 2,685 goals / 23 aspirations, 694 at
status=completed, and a one-record schema probe of a completed goal shows only
title/status/priority/category/participants/skill/discovered_by/filed_by_agent/
work_class/id/started — no completion timestamp of any kind, while
aspirations-read.sh --summaryreported asp-115 alone at 4,422 done. Use thisindex for IDENTITY and STATUS only; take every dated or counted figure from the
full store.
-
Blocked goals analysis Bash: bash core/scripts/goal-selector.sh blocked → Parse JSON → store as blocked_data → blocked_data.bottlenecks = root bottlenecks with downstream counts → blocked_data.summary.total_blocked, blocked_data.summary.bottleneck_count
-
Message board activity since last report For each channel in [general, findings, coordination, decisions]: IF since is not null: Calculate hours = ceil((now_epoch - since_epoch) / 3600) Bash: bash core/scripts/board-read.sh --channel --since {hours}h --json ELSE (lifetime): Bash: bash core/scripts/board-read.sh --channel --json → The output is JSONL — one object per LINE, NOT a JSON array. A whole-stream json.load raises JSONDecodeError("Extra data: line 2 column 1"). Parse line-by-line: [json.loads(l) for l in out.splitlines() if l.strip().startswith("{")] → A bare
exceptaround that parse is FORBIDDEN. It launders the raise into 0, and the report then states the board was silent — a claim about fleet coordination health. Measured 2026-08-03 (foxtrot): general 23 / findings 248 / coordination 436 / decisions 13 = 720 messages reported as 0. The 2026-08-02 report hit the identical zero and correctly diagnosed it in its NARRATIVE, and the next run reproduced it unchanged — because the narrative is not what the next agent executes; this file is. That is why the fix belongs here and not in another report. → POSITIVE-CONTROL a zero before believing it (guard-2421). This defect is self-concealing: an empty board is a plausible reading, so nothing prompts a second look. If a channel returns 0, re-read it at a wide window (--since 720h) or check for a known post-id. Cheapest check first: if you already hold a prior measurement that contradicts the empty, believe the prior one and re-read. → store messages per channel → Skip channels that output "is empty or does not exist" Cap: max 10 most recent messages per channel. If more exist, note: "... and {N} earlier messages" Store as board_messages = {channel: [messages], ...} (Any channel with zero messages is omitted from output) -
System Health Metrics
Structural health indicators surfaced for meta-awareness
11a. Decompose candidates (tree nodes exceeding growth threshold)
Bash: bash core/scripts/tree-read.sh --decompose-candidates → Parse output as JSON → decompose_candidate_count = len(result)
11b. Encoding drift (from session signals if available)
Bash: bash core/scripts/wm-read.sh loop_state --json → Extract goals_since_last_tree_update from loop_state.signals (if exists) → If WM has no loop_state (between sessions): encoding_drift = "N/A (between sessions)"
11c. Reflection ROI (from meta/reflection-strategy.yaml)
Bash: meta-read.sh reflection-strategy.yaml → If file exists: extract roi_history (last 5 entries) → If file missing: reflection_roi = "not initialized"
11d. Routine-to-productive ratio (from loop_state if available)
→ If loop_state exists: routine_ratio = loop_state.signals.routine_count_total / loop_state.goals_completed → Else: routine_ratio = "N/A"
11e. Knowledge debt items (aggregate + per-entry detail)
Bash: bash core/scripts/wm-read.sh knowledge_debt --json → knowledge_debt_count = count of items (0 if empty/null) → knowledge_debt_high = count where priority == "HIGH" → knowledge_debt_oldest_age_days = max(now - item.created) across items, or 0 if empty → knowledge_debt_entries = up to 5 items sorted by sessions_deferred DESC then age DESC, each as {node_key, priority, source_goal, age_days, sessions_deferred}
11f. Hypothesis pipeline flow
Uses pipeline counts already gathered in step 4/5
Bash: bash core/scripts/pipeline-read.sh --stage active → time_gated = count hypotheses where formed_date + horizon window > now → flowing = total active - time_gated
-
Outcome Delta (Tranche C — rb-390)
Reads the outcome-metrics snapshot populated by the outcome-observation
hook in aspirations-state-update Step 8.12 (Pattern B hook slot — see
core/config/conventions/domain-hooks.md). Fail-open: missing snapshot
means outcome_delta_available = false and the section shows
"no outcome signal configured" — never an error.
goals_completed_count = len(goals_completed) # from step 1 (list of ids) Bash: source core/scripts/_paths.sh && test -f "$WORLD_DIR/outcome-metrics.yaml" && echo "exists" IF exists: Read "$WORLD_DIR/outcome-metrics.yaml" → outcome_now = parsed YAML outcome_delta_available = true # Prior snapshot: saved alongside the report-timestamp marker so the # delta is computed against the last completion report, not the live # file (which the outcome-observation hook mutates every goal). IF agents//session/last-outcome-snapshot.yaml exists: Read it → outcome_prior = parsed YAML # BASELINE-CORRESPONDENCE ASSERTION (g-001-04, 2026-08-24). The delta # window is defined by
last-report-timestamp; the baseline it diffs # against is this file. NOTHING guarantees they correspond, and when # they do not the report states a delta over the WRONG interval while # looking completely normal. Two independent ways they decorrelate: # (1) a prior run wrote the timestamp and skipped this snapshot — # Phase 4 step 3's|| truemakes a skip, a failed cp and a # success byte-identical after the fact; # (2) sync-tier split:last-report-timestampis sync_tier #continuity(crosses machines) while this file is #machine_local(does not) — session-manifest.yaml:397/896. # A multi-box agent reporting from box B diffs against box B's # last LOCAL snapshot, not against its own last report. # MEASURED 2026-08-24 (foxtrot, LAPTOP-3IOFCNEO): baseline # updated_at 2026-08-21T03:16:14 / mtime Aug 21 03:53 against a # last-report-timestamp of 2026-08-22T16:53:06 — a 3-DAY baseline # presented as a 35-hour delta. Cause was (1), proven by three # same-directory Phase-5/5.5 siblings (fleet-digest.md/.html, # digest-notes.md) all written 2026-08-22 16:55:08-09 on this box # while this file was not touched. baseline_age_note = None # GATE ON THE SNAPSHOT'S MTIME, NOT ITS updated_at — corrected # 2026-08-24 (echo, cc-03) on this assertion's FIRST live run, which # is what exposed it.updated_atrecords when the COLLECTOR last # wrote world/outcome-metrics.yaml; the snapshot is COPIED from that # file at report time, so updated_at is necessarily EARLIER than the # report timestamp on every healthy run andupdated_at < since# fires ALWAYS. Measured here: updated_at 2026-08-21T20:00:07 against # since 2026-08-21T20:23:35 — a 23m28s collector interval rendered as # a window violation worth 0.6% of a 63.3h window. An assertion that # fires on every healthy run trains its reader to skip it, which is # precisely how the real 3-day case below would get missed. # MTIME is the right signal because it records when the snapshot was # TAKEN. It matchedsinceto the second here (20:23:35.714 vs # 20:23:35), and it still catches the foxtrot failure case # decisively (mtime Aug 21 03:53 vs since 2026-08-22T16:53 = 37h). # Writers enumerated before trusting an mtime (guard-1504, rb-190): # session-manifest.yaml:898 names exactly ONE writer # (agent-completion-report Phase 4) at sync_tier machine_local, so no # sync layer and no background writer can move it. If that ever gains # a second writer, this gate is void — re-enumerate before trusting it. snapshot_mtime = mtime of agents//session/last-outcome-snapshot.yaml IF since is not null AND snapshot_mtime is more than 60s BEFORE since: # The snapshot was not taken at the last report: a prior run wrote # the timestamp and skipped the copy. The delta spans MORE than the # report window, so every "moved" is over-stated. baseline_age_note = ("baseline snapshot was TAKEN {t} but the report " "window starts {s} — a prior run wrote the timestamp and skipped " "the snapshot, so this delta spans {d} extra hours and " "OVER-STATES movement").format(...) #updated_atremains useful as SECONDARY colour (how stale the metrics # themselves were at snapshot time). Report it; never gate on it. # Do NOT suppress the section and do NOT silently widen the window: # print baseline_age_note verbatim in the Outcome Delta section # (guard-2841 — a silently-dropped row is indistinguishable from a # source that was never read). ELSE: outcome_prior = {} # first report — deltas appear as "initial" baseline_age_note = None # Compute per-source deltas. Each source contributes exactly these # four keys (consumer contract — do not omit any): # available: bool — was the source present in outcome_now? # moved: bool — did any observable field change value vs prior? # substantive: bool — is that move a real event rather than a # COLLECTION ARTIFACT? (guard-2306) # delta_summary: str — one-line human description for the report #substantiveexists because "it moved" has two indistinguishable # causes: something genuinely happened, or the measured population # EMPTIED / REFILLED / the collector changed shape — which alters every # field at once. Set substantive = false when the move is an artifact of # collection rather than of the product. The discriminator is the # DENOMINATOR (same one guard-2049 uses for the mirror case): # - the source's own denominator (runs_total, row count, sample size) # crossed zero in EITHER direction — 2->0 or 0->6 alike; a window # that empties and a window that refills are both the collector # talking, not the product; # - every observed field changed at once and at least one landed on # zero / null / empty; # - the source's shape changed (fields appeared or disappeared). # BOTH DIRECTIONS ARE MEASURED, do not treat this as the empty case # only: ci 2->0 suppressed the warning on 2026-08-01 (g-001-04 run 74, # 23 goals) and ci 0->6 suppressed it again on 2026-08-06 (alpha, cc-04, # 55.8h window). # KEEP delta_summary HONEST EITHER WAY: still say the field changed, and # say why it does not count — a suppressed number that is never printed # is how this defect stayed invisible for three reproductions. # Never error if a key is missing from outcome_prior or outcome_now — # the source shape is domain-specific and may change. # Sources nest under the top-levelsources:key in outcome-metrics.yaml # (header written by outcome-metrics-collect.sh). A top-level .get("git") # returns {} for BOTH sides, every source reads moved=false, and the # divergence warning fires FALSELY on any >=5-goal window (observed # 2026-07-16 g-001-04 run — caught by reading the raw file before trusting # the empty delta). prior_src = outcome_prior.get("sources", {}) or {} now_src = outcome_now.get("sources", {}) or {} git_delta = compute_source_delta(prior_src.get("git", {}), now_src.get("git", {})) ci_delta = compute_source_delta(prior_src.get("ci", {}), now_src.get("ci", {})) operator_delta = compute_source_delta(prior_src.get("operator", {}), now_src.get("operator", {})) # Process-vs-outcome divergence flag: # IF goals_completed_count >= 5 AND no source moved → divergence. # This is the exact signal that caught "77 goals done and nothing # material moved." Magic number 5 is the minimum window under which # divergence is noise not signal. any_outcome_moved = any( d.get("moved") for d in [git_delta, ci_delta, operator_delta] ) # Gate on SUBSTANTIVE movement, never on baremoved— a collection # artifact reads moved=true and satisfies-away the very warning that # exists to catch "lots of work, nothing happened" (guard-2306). any_substantive_move = any( d.get("substantive") for d in [git_delta, ci_delta, operator_delta] ) # AND require at least one source to have been READ. This is the OTHER # direction, and it must be checked in the same edit or the fix simply # swings the bug back: g-115-2394 fixed a variant where every source # read {} on both sides, so nothing could ever move and divergence fired # FALSELY on every >=5-goal window. "Could not measure" is not the same # claim as "nothing happened", and onlyavailableseparates them. any_source_available = any( d.get("available") for d in [git_delta, ci_delta, operator_delta] ) divergence = ( goals_completed_count >= 5 and any_source_available and not any_substantive_move ) ELSE: outcome_delta_available = false divergence = false -
Recurring-goal lifetime substantive-hit data (FW-5/R1 -- g-317-16)
Feeds the "Contribution" recognition section (Phase 3), which frames
recurring/sweep goals that returned routine THIS window. g-317-02 shipped a
lifetime substantive-hit tally WRITTEN by recurring-close.sh onto each
recurring goal record:
substantive_runs = denominator, advances on EVERY close
substantive_hits = numerator, GENUINE-deep closes only (a forced
anti-drift flip is NOT a real catch, so it is excluded)
last_substantive_at = date of the most recent genuine catch
The slim aspirations-compact index (step 8) does NOT carry these fields, so
gather them from the goal records for the recurring goals completed this
window (the set the report already lists).
substantive_data = {} # goal_id -> {hits, runs, last, rate} FOR EACH goal_id in goals_completed (from step 1) that is recurring: # Resolve aspiration_id via step 3b's goal_id -> aspiration mapping. Bash: bash core/scripts/aspirations-read.sh --source {source} --id {aspiration_id} → find the goal by goal_id; read substantive_hits / substantive_runs / last_substantive_at. Default 0 / 0 / null when the fields are ABSENT (legacy goals, or goals never closed via recurring-close.sh since the g-317-02 writer shipped -- the expected early-data case). runs = int(substantive_runs or 0); hits = int(substantive_hits or 0) rate = round(hits / runs, 3) if runs > 0 else None substantive_data[goal_id] = {"hits": hits, "runs": runs, "last": last_substantive_at, "rate": rate}
ALTERNATIVE aggregate/chronic view (ALL recurring goals, not just this
window):
bash core/scripts/cargo-cult-detector.py --audit-all --dry-runcomputes the same per-goal lifetime_hit_rate across world+agent queues and
flags chronic-low-rate rows. Use it when the report wants the full upkeep
track record rather than only this-window goals; parse its markdown table
(--dry-run suppresses the Idea-goal filing side effect).
Fail-open: a read error for any goal defaults that goal to runs=0 (graceful
omit in Phase 3) -- never error the report on missing substantive data.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- today Changed · +45 lines 3671bfa31d19
- 5d ago Changed · +76 lines c41be8ad1df1
- 9d ago First seen · 781 lines · 112 tokens per session scan A 8dc011e67035
agent-completion-report is a skill published in the GitHub repository zkysar1/Claude-Mind (5 stars, last pushed yesterday), licensed MIT. It adds 112 tokens to every session and 15,390 once invoked, about $0.0006 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.
Other skills, from other repositories
hive.browser-automation
Required before any hive-browser CLI command. The browser is driven from the terminal by running hive-browser ... --json via terminalexec — not via MCP tools. Teaches the browser lifecycle rules (the bridge attaches to the USER'S running Chrome — never kill or launch browser processes; timeouts are transport issues…
hive.linkedin-automation
Read before automating LinkedIn with browser tools. LinkedIn combines shadow DOM (#interop-outlet), strict Trusted Types CSP that silently drops innerHTML, Lexical composer, native beforeunload dialogs that hang the bridge, and aggressive spam filters — each has bitten us at least once. Verified flows for profile…
hive.worker-delegation
Concrete patterns for breaking colony work into parallel worker jobs via runplaybook — when fan-out helps, how to model the goal as a tracker table, write the worker skill, author the playbook, pilot, and let convergence retry/resume the gap.
hive.x-automation
Read before automating X / Twitter with browser tools. Verified flows for post, reply, delete, search-and-engage, plus the Draft.js compose quirks that silently disable the send button. Includes the daily-reply and job-market-reply playbooks. Requires hive.browser-automation for the underlying screenshot + coordinate…
hive.slack-notifications-setup
Set up a Slack notification channel (Sentinel) for a colony by driving the browser — reuse or create the "Hive Sentinel" Slack app from a JSON manifest, install it, capture the bot + app tokens, create/select the channel via the Slack API, and turn Sentinel on so the colony can ping the user on Slack and accept…
hive.writing-hive-skills
Author a new Agent Skill for a Hive agent that conforms to the Agent Skills specification (SKILL.md with YAML frontmatter, optional scripts/references/assets directories). Use when the user asks to create, scaffold, add, or package a new skill for a Hive agent.