Update the ledger safely
TRENDS.md is the single source of truth and later sessions parse it. The
structure is a contract.
File contract (do not change)
- Header:
# Trend ledger — AI Radar, then Last updated: YYYY-MM-DD, then the
stage legend.
- Sections, in this order:
## Active trends, ## observation_queue,
## source_rotation, ## strategy_notes, ## study_shelf, ## calibration.
## source_rotation, ## strategy_notes and ## calibration are POINTER stubs only: their real
append-only content lives in logs/source_rotation.md and logs/calibration.md
respectively. Keep the two stub headers (the section order is the contract) but
NEVER inline log lines back into TRENDS.md — appends go to the logs/ files.
- Trend block:
### [id: slug-NNN] Title with fields alias, optional
pinned: true, stage, confidence, first_observed, last_evidence,
evidence: (list), notes:.
- Evidence line:
- YYYY-MM-DD — URL — one line of context.
Rules
- Match findings to existing trends via id and
alias before creating a new
trend. New trends take the next free NNN and start at seed or emerging.
- ROUTE a captured primary, don't default to "queue it": (a) if it lands on an
EXISTING trend's axis, append it as EVIDENCE there — a single primary suffices
for an existing trend; the ≥3-source bar is only for CREATING a trend; (b) if
the queue now holds ≥3 independent groups on one untracked sub-theme, promote
that cluster to a
seed trend; (c) else it stays a queue item. Leaving an
on-axis primary in the queue (hoarding evidence) or a named primary in report
prose only is a routing failure.
- Max 10 evidence items per trend — drop the oldest. Keep
last_evidence equal
to the newest evidence date.
- Stage moves: at most ONE stage up per trend per day, only on new independent
evidence, justified in
notes. Demotions are always allowed. 21+ days without
evidence → dormant; at 45+ days the weekly pass moves the entry to
ARCHIVE.md as a one-line post-mortem.
- Pinned trends (
pinned: true): NEVER auto-archived, no matter how long
without evidence — they are the curator's standing-watch axes. They still
follow the normal stage rules, INCLUDING going dormant when quiet (the
ledger stays truthful about activity); they simply never leave the board.
Only the curator adds/removes a pin (or the agent proposes it via amendment).
observation_queue items are dated and marked "unverified" unless opened. It
is a WORKING SET (signals pending verification), not a knowledge store — keep it
bounded to a soft cap of ~25 live items by a CAP-DRIVEN burndown that runs every
session, including quiet/no-evidence passes: while the queue is OVER the cap,
resolve the oldest items toward the cap that run regardless of what the scan
found; at/under the cap it stops on its own (resolve only the 1–2 oldest if
stale). This is owed every run, never deferred to the weekly — a no-evidence
pass is not a no-op for the queue. Items leave ONLY by resolution: promoted to a
trend (the signal is captured there) or dropped with a one-line reason in the
day's/week's report (write-once, permanent). NEVER silently delete — because
every removal is either a promotion or a recorded drop, shrinking the queue
loses no knowledge. Re-date an item only if it is genuinely still worth watching.
- Queue-line format (amendment W35-P1, applied 2026-09-05 W36): a queue entry
holds ONLY genuine unresolved signals, one line per signal (or one tightly
bundled line per day listing just the still-open below-bar/adjacent/unverified
items), in the file's own stated
date — description — link shape. It must
NEVER restate what a lane already routed to trend evidence, the day's dormancy
enumeration, the capture-leak count, or source-rotation narration — that audit
trail already lives permanently in reports/YYYY-MM-DD.md; duplicating it here
is a bloat failure, not thoroughness (it drove TRENDS.md from 41KB at W24
baseline to ~650KB by W36, with individual daily queue lines reaching 7-21KB).
When in doubt, ask "does this line name something still awaiting a decision?" —
if not, it belongs in the report only.
- Append one dated line per session to
logs/source_rotation.md (the coverage
log; not the TRENDS.md stub). Append dated corrections to logs/strategy_notes.md
(the strategy log; not the TRENDS.md stub); never delete curator entries.
study_shelf: newest first, format date — [name](url) — one line of why;
single-artifact items allowed (the trend bar does not apply), opened primary
sources only.
calibration (now logs/calibration.md) is append-only and written by weekly
runs only (see the radar-self-eval skill); daily runs never touch it.
- Notes compaction (amendment W35-P2, applied 2026-09-05 W36): once a
trend's
notes field exceeds roughly 1500 words, the NEXT run that touches
that trend's notes (daily or weekly) compacts older Update YYYY-MM-DD
entries into one running-summary paragraph — preserving the founding/
anchor reasoning and the most recent 2-3 updates verbatim — rather than
accumulating every update verbatim forever. State in that day's/week's
report that a compaction happened and roughly how much was condensed;
nothing is lost (the pre-compaction notes text remains readable in the git
history of this file). This mirrors the precedent that already externalized
source_rotation/calibration out of TRENDS.md for the same size reason.
- Update the
Last updated line. Keep everything in English.
Validate before commit
grep -n '^## ' TRENDS.md
# expected, in order: Active trends, observation_queue, source_rotation, strategy_notes, study_shelf, calibration
grep -c '^### \[id: ' TRENDS.md # trend count matches expectations
grep -nE '^ - [0-9]{4}-[0-9]{2}-[0-9]{2} — ' TRENDS.md | head -3 # evidence format
grep -n '^Last updated:' TRENDS.md # date is today
# the three externalized logs must exist and only grow (append-only):
for f in source_rotation strategy_notes calibration; do
test -f logs/$f.md && printf '%-16s ' $f && tail -1 logs/$f.md | head -c 70 && echo
done
# TRENDS.md must NOT have regrown a log body — all three stay short POINTER stubs.
# A stub over ~10 lines means a run wrote the log INTO the ledger instead of logs/:
awk '/^## /{if(s)printf " %-16s %d lines%s\n",s,n,(n<10?" ok":" <- REGROWN, move it to logs/");s="";n=0}
/^## (source_rotation|strategy_notes|calibration)/{s=substr($0,4)} {n++}
END{if(s)printf " %-16s %d lines%s\n",s,n,(n<10?" ok":" <- REGROWN, move it to logs/")}' TRENDS.md
If a check fails, fix the file before committing. Commit and push per the
conventions in AGENTS.md.
1---2name: radar-ledger-update3description: Safely update TRENDS.md (the AI Radar ledger): append evidence, move stages, manage observation_queue, source_rotation and strategy_notes without breaking the file contract. Use every time TRENDS.md is edited, before committing radar updates, and when promoting or archiving trends.4---56# Update the ledger safely78`TRENDS.md` is the single source of truth and later sessions parse it. The9structure is a contract.1011## File contract (do not change)1213- Header: `# Trend ledger — AI Radar`, then `Last updated: YYYY-MM-DD`, then the14 stage legend.15- Sections, in this order: `## Active trends`, `## observation_queue`,16 `## source_rotation`, `## strategy_notes`, `## study_shelf`, `## calibration`.17- `## source_rotation`, `## strategy_notes` and `## calibration` are POINTER stubs only: their real18 append-only content lives in `logs/source_rotation.md` and `logs/calibration.md`19 respectively. Keep the two stub headers (the section order is the contract) but20 NEVER inline log lines back into TRENDS.md — appends go to the `logs/` files.21- Trend block: `### [id: slug-NNN] Title` with fields `alias`, optional22 `pinned: true`, `stage`, `confidence`, `first_observed`, `last_evidence`,23 `evidence:` (list), `notes:`.24- Evidence line: `- YYYY-MM-DD — URL — one line of context`.2526## Rules2728- Match findings to existing trends via id and `alias` before creating a new29 trend. New trends take the next free NNN and start at `seed` or `emerging`.30- ROUTE a captured primary, don't default to "queue it": (a) if it lands on an31 EXISTING trend's axis, append it as EVIDENCE there — a single primary suffices32 for an existing trend; the ≥3-source bar is only for CREATING a trend; (b) if33 the queue now holds ≥3 independent groups on one untracked sub-theme, promote34 that cluster to a `seed` trend; (c) else it stays a queue item. Leaving an35 on-axis primary in the queue (hoarding evidence) or a named primary in report36 prose only is a routing failure.37- Max 10 evidence items per trend — drop the oldest. Keep `last_evidence` equal38 to the newest evidence date.39- Stage moves: at most ONE stage up per trend per day, only on new independent40 evidence, justified in `notes`. Demotions are always allowed. 21+ days without41 evidence → `dormant`; at 45+ days the weekly pass moves the entry to42 `ARCHIVE.md` as a one-line post-mortem.43- Pinned trends (`pinned: true`): NEVER auto-archived, no matter how long44 without evidence — they are the curator's standing-watch axes. They still45 follow the normal stage rules, INCLUDING going `dormant` when quiet (the46 ledger stays truthful about activity); they simply never leave the board.47 Only the curator adds/removes a pin (or the agent proposes it via amendment).48- `observation_queue` items are dated and marked "unverified" unless opened. It49 is a WORKING SET (signals pending verification), not a knowledge store — keep it50 bounded to a soft cap of ~25 live items by a CAP-DRIVEN burndown that runs every51 session, including quiet/no-evidence passes: while the queue is OVER the cap,52 resolve the oldest items toward the cap that run regardless of what the scan53 found; at/under the cap it stops on its own (resolve only the 1–2 oldest if54 stale). This is owed every run, never deferred to the weekly — a no-evidence55 pass is not a no-op for the queue. Items leave ONLY by resolution: promoted to a56 trend (the signal is captured there) or dropped with a one-line reason in the57 day's/week's report (write-once, permanent). NEVER silently delete — because58 every removal is either a promotion or a recorded drop, shrinking the queue59 loses no knowledge. Re-date an item only if it is genuinely still worth watching.60- **Queue-line format (amendment W35-P1, applied 2026-09-05 W36):** a queue entry61 holds ONLY genuine unresolved signals, one line per signal (or one tightly62 bundled line per day listing just the still-open below-bar/adjacent/unverified63 items), in the file's own stated `date — description — link` shape. It must64 NEVER restate what a lane already routed to trend evidence, the day's dormancy65 enumeration, the capture-leak count, or source-rotation narration — that audit66 trail already lives permanently in `reports/YYYY-MM-DD.md`; duplicating it here67 is a bloat failure, not thoroughness (it drove TRENDS.md from 41KB at W2468 baseline to ~650KB by W36, with individual daily queue lines reaching 7-21KB).69 When in doubt, ask "does this line name something still awaiting a decision?" —70 if not, it belongs in the report only.71- Append one dated line per session to `logs/source_rotation.md` (the coverage72 log; not the TRENDS.md stub). Append dated corrections to `logs/strategy_notes.md`73 (the strategy log; not the TRENDS.md stub); never delete curator entries.74- `study_shelf`: newest first, format `date — [name](url) — one line of why`;75 single-artifact items allowed (the trend bar does not apply), opened primary76 sources only.77- `calibration` (now `logs/calibration.md`) is append-only and written by weekly78 runs only (see the `radar-self-eval` skill); daily runs never touch it.79- **Notes compaction (amendment W35-P2, applied 2026-09-05 W36):** once a80 trend's `notes` field exceeds roughly 1500 words, the NEXT run that touches81 that trend's notes (daily or weekly) compacts older `Update YYYY-MM-DD`82 entries into one running-summary paragraph — preserving the founding/83 anchor reasoning and the most recent 2-3 updates verbatim — rather than84 accumulating every update verbatim forever. State in that day's/week's85 report that a compaction happened and roughly how much was condensed;86 nothing is lost (the pre-compaction notes text remains readable in the git87 history of this file). This mirrors the precedent that already externalized88 `source_rotation`/`calibration` out of TRENDS.md for the same size reason.89- Update the `Last updated` line. Keep everything in English.9091## Validate before commit9293```bash94grep -n '^## ' TRENDS.md95# expected, in order: Active trends, observation_queue, source_rotation, strategy_notes, study_shelf, calibration96grep -c '^### \[id: ' TRENDS.md # trend count matches expectations97grep -nE '^ - [0-9]{4}-[0-9]{2}-[0-9]{2} — ' TRENDS.md | head -3 # evidence format98grep -n '^Last updated:' TRENDS.md # date is today99# the three externalized logs must exist and only grow (append-only):100for f in source_rotation strategy_notes calibration; do101 test -f logs/$f.md && printf '%-16s ' $f && tail -1 logs/$f.md | head -c 70 && echo102done103# TRENDS.md must NOT have regrown a log body — all three stay short POINTER stubs.104# A stub over ~10 lines means a run wrote the log INTO the ledger instead of logs/:105awk '/^## /{if(s)printf " %-16s %d lines%s\n",s,n,(n<10?" ok":" <- REGROWN, move it to logs/");s="";n=0}106 /^## (source_rotation|strategy_notes|calibration)/{s=substr($0,4)} {n++}107 END{if(s)printf " %-16s %d lines%s\n",s,n,(n<10?" ok":" <- REGROWN, move it to logs/")}' TRENDS.md108```109110If a check fails, fix the file before committing. Commit and push per the111conventions in AGENTS.md.