← adimendelowitz.dev
POST 1 / 6 SKILLS THAT REMEMBER 9 MIN READ

I Built an AI Reviewer That Remembers Its Last Review

A workflow for separating issues found, patches proposed, and fixes actually accepted

View source on GitHub
TL;DR
  • Review one target using several independent lenses, each checking a different angle.
  • Record evidence-backed findings and propose a separate patched copy.
  • On the next run, reconcile old findings as fixed, still present, or withdrawn.

In this post

  1. 01AI review is narrow and forgetful
  2. 02What critique does
  3. 03Inside the folder
  4. 04Found, patched, promoted
  5. 05What it checks
  6. 06The review log
  7. 07How it connects to other skills
  8. 08Design decisions
  9. 09A real example
  10. 10Best practices
  11. 11Next

Two things happen here: several lenses check one file at once, and every finding's status carries forward to the next run.

flowchart LR
    T[One file] --> L[Several lenses, each a different angle]
    L --> F[Anchored findings]
      
flowchart LR
    F[Findings] --> P[Patch proposed]
    P --> M{Promoted?}
    M -->|No| S[Stays open next run]
    M -->|Yes| R[Reconciled next run]
      

AI review is narrow and forgetful

Ask a model to review a file and it runs one unstructured pass, catching whatever happens to occur to it. It might flag a security issue and miss that the document never states its own purpose. It rarely asks what breaks six months out, or who benefits if the whole thing turns out to be wrong. Whether an issue gets covered at all comes down to chance.

That's one gap. The other only shows up once the same file gets reviewed a second time.

Say a review catches a real defect, and someone fixes it, or means to. Nothing records that the fix happened, so run the review again later and the model has no way to tell a resolved issue from one that simply went unnoticed twice: either way, it re-derives the same finding from scratch, spending the time and the tokens to redo work that was already done. Each pass gets treated as an island. Nothing the process learns on one run carries forward into the next.

What critique does

I needed something that would review a target from several angles while checking what it had already found, so it wouldn't rehash the same mistakes time and again. To do that, I created the critique skill, which runs an adversarial review against one file at a time, whether that's code, a document, a prompt, or a design doc.

Up to 10 lenses can run against a single file. Five run every time:

LensAsks
purpose/productDoes it state its own purpose?
evidence-integrityDo its claims have evidence behind them?
falsificationCan its own conclusions be falsified?
pre-mortemWhat breaks in six months?
red-teamWho benefits if the whole thing is wrong?

The remaining slots are domain-specific and stack on top: security and testability for code, leakage and baselines for ML.

Ordinary AI reviewcritique
One unstructured passMultiple lenses, every run
Starts freshReads the prior review first
May rediscover defectsReconciles prior findings
Blurs proposed and accepted editsRequires a promotion step
Gives broad impressionsRequires evidence anchors
May over-report to appear thoroughTreats a clean result as valid

Inside the folder

critique/
├── README.md
├── SKILL.md
├── bundles/
│   ├── code.md
│   ├── docs.md
│   ├── systems.md
│   ├── ml.md
│   └── multifile.md
└── evals/
    └── README.md

Each file has one job:

Only one primary bundle loads per run, so a forty-line prompt review never pays to load the exec/eval/subprocess checks meant for source code, and a code review never loads the leakage checks meant for a model write-up.

Found, patched, promoted

Each finding moves through three stages: found, patched, promoted.

StageWhat happens
FoundA problem is identified, with a quote or line behind it
PatchedA versioned copy proposes the fix
PromotedA person reviews the patch and replaces the real file with it

The patch and the fix stay separate on purpose. A patch is a proposal, versioned apart from the file it replaces, and a person still decides whether to adopt it.

Key rule

A patch is not a fix until it is promoted.

What it checks

What counts as a real finding adapts to the kind of file under review.

A claim with nothing to compare it against isn't a result. The review says so instead of taking it at face value.

The review log

flowchart LR
    L[(critique log)] -->|read first| A[Adversarial pass runs]
    A --> B[Findings ranked, patched]
    B -->|new line appended| L
      

The log gates the run on one end and receives its result on the other. Nothing about the adversarial pass itself changes; what changes is whether that pass starts from zero or from what the last one already settled.

How it connects to other skills

The log isn't a dead record.

flowchart LR
    H[handoff] -->|triggers a run| C[critique]
    C -->|writes| L[(critique log)]
    L -->|counters block| T[token-aware]
    L -->|evidence source| R[retrospective]
      

Design decisions

A clean review is a valid result. A review that comes back clean can look like it didn't try hard enough, and that pressure is what pushes a model to invent a finding just to seem thorough. critique trusts the clean run instead, as long as the adversarial pass actually happened: checks fixed in advance, budget spent before a clean verdict is allowed.

Evidence anchors are mandatory. Every finding needs a quote, a line reference, or a named absence. The review's own conclusions don't count as evidence on their own. Without something concrete to point back at, a finding can't be checked later, so it gets discarded, however plausible it sounds.

Scope is intentionally limited. critique reviews only the artefact in front of it: never a build, a test suite, or anything outside the file. A finding about a contradiction in a prompt says only that the prompt contradicts itself. It says nothing about whether the program reading it actually works.

That boundary applies to the skill's own protocol too. A retrospective run against this project's audit trail once found the installed copy of critique running an older protocol version against a repo that had already moved on. A normal review run wouldn't catch that on its own. It checks the target it's pointed at. It doesn't check the process running it.

And this is how it all connects together, from the first log check to the last line written →

A real example

I decided it would be best to run a meta-analysis of my skills usage to update and optimize them before sharing them publicly. I first ask Claude:

I want you to /critique the following prompt, fix everything about it, and repeat the critique process until all personas are satisfied and all issues are resolved:

I'm collecting data about how my retrospective, critique, handoff, token-aware and kb-search skills have been working. go through the entire project history and do meta analysis of my skills. Include insights, implicit and explicit patterns, best and common practice, best and worst features, under-utilized or ignored features, what am i missing or misunderstanding. draw conclusion on what could make them run smoother, faster, better, more efficiently and affectively, and would can make them most cost-effective and have optimized ROI for every token.

Which resulted in this detailed prompt →

Running critique against it turned up issues like these:

IssueWhy it matteredWhat changed
Entire project history left undefinedThe review couldn't tell what evidence was even in scopeScope was named explicitly and the finding was patched
A cost claim stated with no way to measure itA quantitative claim with no observable method behind itThe claim was either dropped or given a stated method
Output path missing from the workflowNowhere was defined for the workflow's own result to goAn output path was added and the finding was patched

The full run found 14 issues and proposed a patch for each, in one pass. The count isn't the interesting part. Every row had a quote, a line, or a named absence behind it. That's evidence a second run can actually check later instead of taking it on faith.

14 findings, 3 SEV1 / 10 SEV2 / 1 SEV3, 0 cut, all patched in one pass

See all 14 findings
IDSevLensFindingStatus
F1SEV1purpose/productentire project history undefinedpatched
F2SEV1sequencingquestion then run both, same turnpatched
F3SEV1self-reference"complete list," no budget givenpatched
F4SEV2purpose/productno output artefact or metricpatched
F5SEV2evidence-integrityROI per token, unmeasuredpatched
F6SEV2domain-terminologyoverlapping, undefined categoriespatched
F7SEV2falsification"missing" vs. "misunderstanding," unanchoredpatched
F8SEV2injectionreads history, no data-not-instructions clausepatched
F9SEV2red-team"any other operating .md," open scopepatched
F10SEV2pre-mortemno owned actions past six monthspatched
F11SEV3QA"affectively"/"would"/"can" typospatched
F12SEV2QAplaceholder left in a project-root fieldpatched
F13SEV2domain-terminologyno retrieval policy namedpatched
F14SEV2purpose/productoutput path missingpatched

Archived log line, reformatted. The compact log persists severity, lens, and a short anchor per finding; per-finding confidence and fix-size grades exist in the live response but aren't written to the archive.

Best practices

Limit

A clean review means the selected checks found no anchorable issue. It does not prove that the software works, the claims are true, or the system is safe.

Next

NEXT Handoff - a structured record of what happened across an entire session, covering every file touched.
Technical detail: stages, schema, and regression cases

Stages and budget

A run moves through a fixed sequence, P0 through P7: load context, select the applicable bundle, run each lens against the target, grade every finding for severity and confidence, propose a patch, reconcile against the prior log entry if one exists, write the new log line, and report a short summary. Tool-call and tier budgets are fixed per run so a review can't quietly balloon in cost, and a clean verdict is only valid once that budget has actually been spent on the adversarial pass.

Exact log line

Each entry is one JSON object:

{"v":"<protocol>","ts":"<iso8601>","t":"<path>","sz":[<lines>,<bytes>],"tier":"<t>","mode":"<normal|self>","lens":[...],"atoms":<n>,"pass":<n>,"f":[["<id>","SEV<n>","<lens>","<anchor slug, 6 words max>","<patched|backlog|withdrawn|still-present>"]],"cut":<n>,"promoted":false,"counters":{"calls":<n>,"cap":<n>,"bytes":<n>,"out_chars":<n>,"sev":{"1":<n>,"2":<n>,"3":<n>},"new":<n>,"carried":<n>},"out":"<patched filename or null>"}

Regression harness

evals/README.md lays out three regression cases for anyone changing the protocol or a bundle: a clean document that shouldn't pick up manufactured findings, a document with two planted, unambiguous defects that both versions should catch, and a target carrying a prior unpromoted log entry that should reconcile as still-present by ID, without being re-derived. The exact file format for evals.json itself isn't fixed, that's left to whoever's running the harness.