# Learn

> Use when durable knowledge is being built, validated or retired — whether a finding is worth a record at all, how confident that record is, which command re-verifies it, and when it has stopped being true.

- Skill: `rubyeyedreaper/learn` (Agent Skill, multi-file: 10 files)
- Install (CLI): `npx skillmds@latest add rubyeyedreaper/learn`
- Raw SKILL.md: https://api.skillmd.com/api/skills/rubyeyedreaper/learn/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: RubyEyedReaper (https://skillmd.com/u/rubyeyedreaper)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/rubyeyedreaper/learn

---


# Learn — what is worth remembering, how sure we are, and when it stops being true

A record earns its place by clearing a **capture bar**, states its confidence as a **rung on a
ladder** rather than a feeling, and carries the **command that would re-check it** — so a later
session can re-run the evidence instead of taking the record's word for it.

This skill adds **no store.** The memory tiers already exist and are described in
[`.claude/docs/odin-memory-standards.md`](../../docs/odin-memory-standards.md). What it adds to a
record in one of them is two fields and a discipline for moving them.

## What this is not for

| The task | Its owner | Why not this skill |
|---|---|---|
| Where a record physically lives, and which class it belongs to | `odin-memory-standards.md` + `odin-memory-guard.sh` | The tiers, the operational/task split and the write guard are settled. This skill is a reader of them. |
| Recording a decision and the reasoning behind it | `architecture-decision-records` | An ADR is a decision record. This is about knowledge that was discovered, not chosen. |
| Domain vocabulary and its definitions | `domain-modeling` | `CONTEXT.md` is the glossary. A term is not a finding. |
| A mistake that needs a mechanical guard | `oops`, then `mistake-to-gate` | Those turn an incident into a check. This one decides whether the *knowledge* is worth keeping. |
| A principle recurring across skills, headed for a rule file | `rules-distill` | A rule is always-on text. A record is recalled on demand. |
| Context bloat, cache buildup, memory surfacing from the wrong project | `leek` | Those are hygiene failures in the environment, not questions about a record's truth. |
| What to work on next | `roadmap` | Knowledge is not a backlog. |

## The two fields

Added to a record in a tier that already exists:

```yaml
confidence: gated
verified_by: bash .claude/tests/safety-guard.test.sh
verified_on: 2026-08-27
```

**`verified_by` names a command, not a person and not a date.** A date says somebody looked. A
command says what would have to be re-run to look again — the difference between a record that can
be re-checked and one that can only be trusted.

The always-loaded memory index has a **300-character-per-line ceiling** (`memory-index-check.sh`,
DEC-0053) because it is read whole into every session in its scope. So the index line carries the
short half only — `· gated 2026-08-27` — and the command lives on the record it links to, which is
unbounded on purpose. The engine renders that marker; it is never hand-assembled.

## The six outcomes

Exactly one per pass over a candidate or a record.

| Outcome | Means |
|---|---|
| `record` | The candidate cleared the bar; write it into the tier it belongs to |
| `merge` | An existing record already covers it; fold the new evidence into that one |
| `promote` | New evidence lifts an existing record a rung |
| `refresh` | The verifying command still passes; the rung holds, the date moves |
| `demote` | The evidence for the current rung no longer holds; the record falls one rung |
| `retire` | The premise is gone; remove the record and say why |

`retire` deletes knowledge on purpose. A record kept past its truth is worse than no record — it is
read with the same confidence as one that is still correct, and nothing about it says otherwise.

## The five confidence tiers

`asserted` → `observed` → `reproduced` → `gated` → `enforced`. Every rung states the evidence that
**promotes** a record into it and the trigger that **demotes** it out; a ladder whose every rung is
a feeling is a vocabulary, not a mechanism. Rung by rung, with the promotion evidence each one
demands and the mistake each rung invites:
[confidence-tiers.md](references/confidence-tiers.md).

The three rungs from `reproduced` up **require** `verified_by`. A record claiming one without a
command is malformed, not merely unverified.

## The capture bar

Five refusal classes, evaluated highest-harm first, **each with its own exit code** so a caller can
tell them apart — five refusals sharing one non-zero code report "no" and nothing else, and the
remedy for a secret is not the remedy for a duplicate.

| # | Class | Exit | Refused because |
|---|---|---|---|
| 1 | credential | 3 | Secret material — matched by key name, or by value shape |
| 2 | personal | 4 | Personal data — an address, an identifier, a phone number |
| 3 | chatter | 5 | True only inside the conversation that produced it |
| 4 | duplicate | 6 | An existing record already covers it → `merge` |
| 5 | derivable | 7 | A restatement of a line the repository already carries |

**A refusal never prints the matched credential.** Not in the message, not in a verbose mode, not in
a fixture's expected output. The caller is told the *key name* or the *pattern name* — what they
need in order to remove it — and nothing more. A refusal that echoes the secret has published it to
every log the caller writes, which is worse than the record it prevented. Masking is not a
substitute: a masked secret is still a secret in every one of those logs.

What each class is keyed on, what it deliberately does not catch, and the false-positive it was
tuned against: [capture-bar.md](references/capture-bar.md).

## The staleness pass

`verify` re-reads a record and decides its rung from the command, not from the calendar. **Age
flags; the command decides.** A record past its max age is marked stale — which means "re-check
this", never "this is wrong".

**Reading a record never executes the command inside it.** Execution is opt-in via `--run`; the
default reports what would run and changes nothing. How a demotion is chosen, why an unresolvable
command falls to `observed` rather than to nothing, and when a pass ends in `retire`:
[staleness-pass.md](references/staleness-pass.md).

## Quick reference

```sh
cd .claude/skills/learn
python3 -m scripts.capture_bar check  --candidate cand.json --root ../../.. --corpus <dir>
python3 -m scripts.capture_bar verify --record rec.json                 # reports; runs nothing
python3 -m scripts.capture_bar verify --record rec.json --run --cwd ../../..
python3 -m scripts.capture_bar tiers
```

| Exit | Means |
|---|---|
| 0 | accepted, or a pass that held the tier |
| 1 | malformed record |
| 2 | usage error |
| 3–7 | refused: credential · personal · chatter · duplicate · derivable |
| 8 | the pass demoted the record one rung |
| 9 | the pass retired the record |

`--corpus` and `--root` are optional, and a class without its input is reported `"skipped"` on
stdout **and** announced on stderr. A check that quietly passes when its subject is missing is
indistinguishable from one that agrees with every input.

## Common mistakes

| Mistake | What happens |
|---|---|
| A `verified_on` with no `verified_by` | The record can be aged but never re-checked. Nothing can ever demote it, so it stays at its rung forever. |
| Claiming `gated` because a check exists | `gated` requires that the check **fails** when the fact stops being true — proved by breaking the fact and watching it red. An unmutated gate is an `observed`. |
| Masking a secret instead of withholding it | Still a secret, now in every log. Report the key name. |
| Refusing every finding as "derivable" | The class is keyed on restatement of one line, not on inference. A fact assembled from three files is a finding. |
| Reading a record with `--run` by habit | Reading a record then executes text stored in it. Default to the reporting pass. |
| Treating a stale flag as a demotion | Age says re-check. Only the command decides the rung. |
| Keeping a record whose premise is gone | It is read with the confidence of a true one. `retire` it and record the reason. |

## Verifying a change to this skill

```sh
cd .claude/skills/learn && python3 -m unittest discover -s tests -t . -v 2>&1 | tail -5
```

Confirm the collected count is **non-zero**. `tests/__init__.py` is what makes it so; without that
file discovery collects nothing and the suite passes having examined nothing.

