The project's episodic memory: a timestamped ledger of rules paid for with real outages and near-misses, one entry per incident. Load WHENEVER you write or review a DB migration or schema change, touch deploy/release workflows (.github/workflows/deploy-*, promote.yml, vercel config), plan a promote/release, respond to a prod incident, or when another skill references a learning. ALSO load after resolving any incident or near-miss: it must leave a new ledger entry in the same session.
Installs into .claude/skills of the current project.
Are you the author of Learnings?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/kortix-ai-learnings)
---
name: learnings
description: "The project's episodic memory: a timestamped ledger of rules paid for with real outages and near-misses, one entry per incident. Load WHENEVER you write or review a DB migration or schema change, touch deploy/release workflows (.github/workflows/deploy-*, promote.yml, vercel config), plan a promote/release, respond to a prod incident, or when another skill references a learning. ALSO load after resolving any incident or near-miss: it must leave a new ledger entry in the same session."
---
# Project learnings: the episodic ledger
Every rule this repository paid for with downtime or a near-miss is one entry in a
timestamped, append-only ledger. The ledger is the full history, in the order it was
learned.
| Path | What it is |
| --- | --- |
| `MEMORY.md` | The index. One line per entry, newest first: recorded time (UTC) and the rule. Generated. |
| `entries/<YYYY-MM-DDTHHMMSSZ>-<slug>.md` | One entry. The filename timestamp is when it was recorded. |
| `scripts/new-entry.sh` | Starts a new entry stamped with the current UTC time and rebuilds the index. |
| `scripts/index.sh [--check]` | Rebuilds `MEMORY.md` from `entries/`, or fails if it is stale. |
Entries recorded before 2026-09-25 were split out of the old single-file register. Their
`recorded` time is the commit that first wrote them (`commit` in the frontmatter).
## Recall: before you touch a surface
1. Search the index and the full text for the surface you are about to change:
```bash
grep -i '<keyword>' .agents/skills/learnings/MEMORY.md
grep -ril '<keyword>' .agents/skills/learnings/entries/
```
Use the words of the surface: `migration`, `CONCURRENTLY`, `deploy-dev`, `promote`,
`wake`, `Stop`, `gateway`, `preview`, the file or route name.
2. Read every matching entry in full. Obey its **Rule**, and keep its **Enforcement** green.
Done when every entry that names the surface you touch has been read.
## Record: after an incident or near-miss resolves
Record in the same session. An incident that leaves no entry is not finished.
1. Start the entry:
```bash
.agents/skills/learnings/scripts/new-entry.sh "<the rule, as an imperative>" [incident-date]
```
2. Fill the four sections the script writes:
- **Rule:** the imperative a developer can obey while coding.
- **Trigger surface:** what someone is doing when it applies.
- **Incident:** date, version or PR, blast radius, in one to three lines.
- **Enforcement:** the test, lint, or CI gate that goes red when the rule breaks. An
entry with an enforcer is a fact. One without is a TODO: name the enforcer to build.
3. Commit the entry and `MEMORY.md` in the same commit.
Done when `scripts/index.sh --check` exits 0 and the entry is committed.
## Ledger rules
- **Append-only.** After an entry merges, its text does not change. When a rule changes,
or an Enforcer moves or is retired, record a new entry. Put
`supersedes: <entry filename>` in its frontmatter and state what changed.
- **One entry, one file, one timestamp.** `recorded` in the frontmatter matches the
filename. It is the time of recording, never the incident date. The incident date goes
in `incident_date`.
- **`MEMORY.md` is generated.** Run `scripts/index.sh` after any entry change. It merges
with git's `union` driver, so two branches that each add an entry do not conflict. A
GitHub squash merge keeps a branch's index line where the branch put it, so the order
on `main` can drift until the next `index.sh` run. `index.sh --check` and
`tests/unit/learnings-ledger.test.ts` compare the lines, not their order: they fail on a
missing, extra, or retitled index line, or a malformed entry.
- **Keep an entry short: about 8 to 20 lines.** Deep detail belongs in the PR body.
Cite the PR number (`PR #1234`).
- **An entry is self-contained.** The ledger in `entries/` is the only incident record.
Do not write a separate incident, RCA, spec, or runbook file, and do not link one.
The repository has no `docs/` tree, and the pre-commit hook rejects new files under it.
- **Synthetic identifiers only.** An entry is committed text, so the AGENTS.md customer-data
rule applies. Write "a customer", "an enterprise workspace", `<session_id>`.
Files in this skill
MEMORY.md97.7 KB
SKILL.md4.2 KB
entries/2026-08-10T191010Z-bot-pushed-release-prs-and-repo-actions-approval-policy.md655 B
entries/2026-08-10T191010Z-cancel-the-ci-run-before-killing-its-db-backend.md541 B
entries/2026-08-10T191010Z-cost-every-pending-prod-migration-before-promoting.md677 B
entries/2026-08-10T191010Z-never-backfill-data-inside-a-single-transaction-migration.md984 B
entries/2026-08-10T191010Z-node-pg-migrate-checkorder-is-index-wise-on-ledger-run-order.md648 B
entries/2026-08-10T191010Z-the-prod-frontend-must-never-deploy-before-the-api-serves-th.md820 B
entries/2026-08-10T191010Z-verify-ci-assertions-against-the-real-artifact-format-on-the.md692 B
entries/2026-08-10T194745Z-an-audit-reconstruction-trigger-is-only-safe-with-its-dedup.md681 B
entries/2026-08-10T194745Z-one-create-index-concurrently-per-table-at-a-time.md845 B
entries/2026-08-10T194745Z-the-vercel-prod-build-must-be-handed-the-release-version.md774 B