108 lines
4.9 KiB
Markdown
108 lines
4.9 KiB
Markdown
---
|
|
name: errorlog-dream
|
|
description: "Lint the fleet error log (errorlog.md): top failure contexts, repeat ref= citations (rules that are not sticking), cross-day noise clusters, resolved entries, machine-name drift; --apply-archive rotates old entries to errorlog-archive/. Triggers: errorlog dream, lint/analyze the error log, errorlog patterns."
|
|
---
|
|
|
|
# Errorlog Dream
|
|
|
|
Sibling of `memory-dream` for `errorlog.md` — the corpus of skill failures,
|
|
user corrections, and self-inflicted friction that CLAUDE.md mandates logging.
|
|
The log exists so we "never pay tokens twice for the same avoidable mistake";
|
|
this skill is the payoff step: it reads the corpus and surfaces what to fix.
|
|
|
|
Read-only by default. The single mutating op (`--apply-archive`) only moves
|
|
old entries into `errorlog-archive/YYYY-MM.md`. Everything judgment-shaped
|
|
lands in a `## PROPOSED` section for the operator.
|
|
|
|
## What it reports
|
|
|
|
`scripts/errorlog_dream.py` parses the canonical entry format
|
|
(`YYYY-MM-DD | MACHINE | skill/context | [type] msg [ctx: ...] (xN)`;
|
|
`(xN)` is the log helper's same-day repeat counter) and produces:
|
|
|
|
1. SUMMARY — totals by type (exec/correction/friction), machine, date span,
|
|
plus a count of unparsed legacy blocks (left untouched, never archived).
|
|
2. TOP CONTEXTS — failure volume by context group, weighted by `(xN)`.
|
|
3. REPEAT REFS — `ref=` citations appearing >=2x. **The highest-value signal:**
|
|
a friction entry citing a documented gotcha means that rule/memory is NOT
|
|
working; repeat citations mean it keeps failing. Checks whether the cited
|
|
memory file actually exists.
|
|
4. NOISE CLUSTERS — same machine + skill + normalized message (ids/numbers
|
|
collapsed) recurring across >=3 days or >=5 weighted hits. These need a
|
|
skill-side fix (expected-condition filter, backoff, health-gate) — not
|
|
more log lines.
|
|
5. RESOLVED — entries carrying a `[RESOLVED ...]` annotation; archive
|
|
candidates regardless of age.
|
|
6. MACHINE-NAME DRIFT — the same machine logged under multiple spellings
|
|
(case drift in identity.json).
|
|
7. ARCHIVE CANDIDATES — entries older than `--days` (default 60).
|
|
8. PROPOSED — `[STRENGTHEN?]` (repeat refs -> add a mechanical guard or
|
|
rewrite the memory), `[SUPPRESS?]` (noise clusters -> fix the skill),
|
|
`[ARCHIVE?]` (resolved entries).
|
|
|
|
## Modes
|
|
|
|
- Default — report only; prints to stdout and writes
|
|
`errorlog-archive/_reports/YYYY-MM-DD-HHMM-dream.md`.
|
|
- `--no-file` — stdout only.
|
|
- `--report-file <path>` — explicit report path.
|
|
- `--days <n>` — archive-age threshold (default 60).
|
|
- `--apply-archive` — move entries older than `--days` into
|
|
`errorlog-archive/YYYY-MM.md` (grouped by entry month, verbatim lines,
|
|
unparsed legacy blocks never moved). Idempotent.
|
|
|
|
## Running it
|
|
|
|
Stdlib only, no pip deps.
|
|
|
|
```bash
|
|
# report only
|
|
bash "$CLAUDETOOLS_ROOT/.claude/scripts/py.sh" "$CLAUDETOOLS_ROOT/.claude/skills/errorlog-dream/scripts/errorlog_dream.py"
|
|
|
|
# rotate out entries older than 60 days
|
|
bash "$CLAUDETOOLS_ROOT/.claude/scripts/py.sh" "$CLAUDETOOLS_ROOT/.claude/skills/errorlog-dream/scripts/errorlog_dream.py" --apply-archive
|
|
```
|
|
|
|
## The operator MUST work the PROPOSED section — that is the run's purpose
|
|
|
|
Same posture as memory-dream: the report is not the deliverable, the fixes
|
|
are. After each run:
|
|
|
|
1. **`[STRENGTHEN?]` repeat refs** — the cited prose rule demonstrably fails
|
|
under flow. Prefer a MECHANICAL guard over more prose: a PreToolUse hook,
|
|
a wrapper that makes the safe path the only path (e.g. `-EncodedCommand`
|
|
for quote-mangling layers), or a script-side preflight. If the cited
|
|
memory file is missing, fix or remove the dangling ref convention.
|
|
2. **`[SUPPRESS?]` noise clusters** — patch the failing skill: filter
|
|
expected/validation responses out of logging (the gz.py pattern +
|
|
`GZ_SUPPRESS_ERRORLOG`-style env flag), add a stop-after-2-identical-
|
|
failures guard, or health-gate a chronically-down backend.
|
|
3. **`[ARCHIVE?]` / archive candidates** — run `--apply-archive`; append
|
|
`[RESOLVED <date>]` to entries you fixed so the next run proposes them.
|
|
4. Commit + `/sync` so the trimmed log and archive reach the fleet.
|
|
|
|
If a proposal needs a decision you can't make, leave it AND say so in your
|
|
summary — don't silently skip the section.
|
|
|
|
## Self-test
|
|
|
|
`scripts/selftest.py` builds a synthetic errorlog in a temp dir and asserts
|
|
every detector fires (counters, repeat refs, noise clusters, resolved,
|
|
machine drift, archive candidates) and that `--apply-archive` moves exactly
|
|
the old entries, splits by month, preserves the marker + unparsed blocks,
|
|
and is idempotent.
|
|
|
|
```bash
|
|
bash "$CLAUDETOOLS_ROOT/.claude/scripts/py.sh" "$CLAUDETOOLS_ROOT/.claude/skills/errorlog-dream/scripts/selftest.py"
|
|
```
|
|
|
|
## Files
|
|
|
|
```
|
|
.claude/skills/errorlog-dream/
|
|
SKILL.md this file
|
|
scripts/errorlog_dream.py the analyzer (report / --apply-archive)
|
|
scripts/selftest.py fixture-based self-test
|
|
errorlog-archive/ rotated months + _reports/ (created on use)
|
|
```
|