← Field Notes
Published Last updated 13 min read

The Mistakes I Record After Every Project

The retrospective format I use to turn failed assumptions into better tests, guardrails, and documentation without rewriting the project into a cleaner story than it really was.

In this article
  1. I start with the incorrect assumption
  2. The evidence decides whether a mistake belongs
  3. I classify the outcome before I call it a mistake
  4. I do not require a neat root cause
  5. I separate personal error from system weakness
  6. A worked retrospective makes the method easier to audit
  7. The guardrail is the part that makes the retrospective valuable
  8. I track where the guardrail actually landed
  9. I write the first note before the project is finished
  10. Public retrospectives need a second edit
  11. I also record mistakes in the writing itself
  12. My current retrospective template
  13. The goal is not to become afraid of mistakes
  14. Related articles
  15. AI transparency

The most useful project notes are often the details I am tempted to remove from the final story.

The helper was in the wrong build scope. The application started before its storage dependency was ready. Several settings changed before I knew which one mattered. A draft described future work with more certainty than the evidence supported.

None of those details make a project look especially polished.

That is why I keep them.

A clean final configuration tells me what exists now. It does not necessarily explain which assumptions failed on the way there, which tests actually narrowed the problem, or which guardrails would make the next project safer.

I have started treating that difference as an operational requirement. When a project changes the way I work, I want a record of the mistake that caused the change.

Not a confession. Not a dramatic postmortem. A usable retrospective.

I start with the incorrect assumption

“The build failed” is an event.

The reusable lesson usually lives one layer deeper: what did I believe before the evidence proved otherwise?

That question has produced better notes than starting with the error message.

Some examples from my own work look like this:

  • If a helper exists in the source file, build-time code can use it.
  • If a directory exists, the expected remote filesystem must be mounted there.
  • If a process is running, the service is healthy.
  • If remote traffic appears in a log, the client completed the session.
  • If a change fixed the symptom once, I understand why it worked.
  • If a draft sounds plausible, I can finish the missing evidence later without changing its premise.

The software changes from project to project. The failed mental models repeat.

That is why I record the assumption instead of only the implementation detail.

A future project may use a different framework, storage system, service manager, or network path and still contain the same reasoning error.

The evidence decides whether a mistake belongs

Not every inconvenience deserves a retrospective.

A typo that cost thirty seconds usually does not need to become a lesson. A scope mistake that changes how I validate production builds probably does.

I keep a mistake when the evidence changed a later decision, test, or operating rule.

My working record started with six fields:

  1. Assumption: What did I believe was true?
  2. Signal: What first suggested that belief might be wrong?
  3. Test: What did I do to narrow the explanation?
  4. Result: What did the test actually establish?
  5. Change: What did I change, or what uncertainty remained?
  6. Guardrail: What should make the same failure less likely next time?

That structure is intentionally stricter than a normal project journal.

It forces me to separate observation from interpretation.

If I cannot describe the evidence, I do not promote the explanation into a lesson.

That same discipline appears in The Test Matrix I Use Before I Trust a Change. A useful test has a defined claim. If I do not know what a result proves, I can easily let a green check or successful command support far more certainty than it deserves.

I classify the outcome before I call it a mistake

One change I have made to the retrospective itself is to stop using “mistake” as the label for every bad outcome.

Different failures deserve different responses.

ClassificationWhat it meansWhat I do with it
MistakeA decision, assumption, omission, or process weakness under my control materially contributedTurn it into a better test, guardrail, or operating rule
SurpriseThe system exposed behavior or a dependency I did not reasonably understand beforehandDocument the dependency and improve the next validation path without manufacturing blame
UnresolvedThe available evidence is not strong enough to support one root causePreserve known facts, unknowns, and the evidence I need next time
NoiseA low-cost typo or one-off inconvenience produced no reusable changeFix it and move on

That classification matters because retrospectives can become dishonest in two opposite directions.

I can minimize a real process failure as “bad luck,” or I can turn every surprising system behavior into a personal failure because the article feels cleaner when somebody is clearly at fault.

Neither helps the next project.

A retrospective should improve the next decision, not invent blame for every bad outcome.

I do not require a neat root cause

One of the easiest ways to make technical writing less trustworthy is to improve the ending after the fact.

Real troubleshooting is often messy. Several explanations may remain plausible. A later change may make the symptom disappear without proving which earlier condition caused it. Sometimes the system gets rebuilt before the original failure can be isolated cleanly.

That does not make the work worthless.

It only changes what I am allowed to claim.

An unresolved incident can still produce a better test sequence, a missing prerequisite, a new monitoring check, or a clearer understanding of where evidence stopped.

I wrote about that boundary directly in Reachable Is Not the Same as Playable. The Satisfactory connection problem improved the way I reason about network paths even though I never preserved enough evidence to publish one definitive root cause.

That is a valid outcome.

“I do not know exactly why this failed” and “I know how I will investigate this class of failure better next time” can both be true.

I separate personal error from system weakness

Sometimes I simply miss a step.

That matters, but it is not the end of the retrospective.

I ask two different questions:

  • What should I have done differently?
  • What about the process made this easy to miss?

The first question improves judgment. The second improves the system around that judgment.

If an application can start against an empty local directory when a remote filesystem fails to mount, telling myself to “remember to check the mount next time” is weak prevention.

A better guardrail may be a startup dependency, a preflight check, an assertion about expected content, or a monitoring condition that detects the wrong state before the application writes into it.

If a deployment repeatedly depends on somebody remembering an undocumented prerequisite, the problem is no longer just memory.

It is process design.

This is one reason I keep returning to the idea that a healthy system should reduce dependence on perfect attention. Good operations make important conditions visible and important failures difficult to mistake for success.

A worked retrospective makes the method easier to audit

The empty-mount incident is a useful example because the lesson changed how I validate storage dependencies.

The record below is a sanitized retrospective reconstruction of the lesson, not the original incident notebook and not a verbatim terminal transcript. I did not preserve the original command-by-command session, so I am not pretending that I did.

Classification:   Mistake / process weakness

Assumption:       The expected path existed, so the remote filesystem must
                  have been mounted there.

Signal:           Expected files were missing even though the application
                  could still access and write to the directory.

Evidence/artifact:
                  The host path existed while the expected remote filesystem
                  was not mounted at that exact boundary.

Test:             Verify the mount independently of the application and of
                  simple directory existence.

Result:           Directory existence proved only that a directory existed.
                  It did not prove that the required remote filesystem was
                  mounted there.

Change:           Treat storage readiness as an explicit prerequisite instead
                  of inferring it from the application's visible path.

Next guardrail:   Fail closed when the exact mount, expected source, and a
                  known readiness condition cannot be verified.

Guardrail destination:
                  Startup/preflight validation, monitoring, and recovery notes.

Status:           Implemented as an operating rule and documented pattern.

Still unknown:    The original troubleshooting transcript was not preserved,
                  so I do not claim an exact historical command sequence.

The useful part is not that the retrospective has more fields.

It is that every field has a different job.

The assumption records the failed mental model. The signal preserves the first contradiction. The evidence identifies what was actually observed. The test defines the narrower question. The result stops the test from proving more than it proved. The change explains what became different. The guardrail says how the next incident should become cheaper.

And the status tells me whether I actually did anything about it.

The guardrail is the part that makes the retrospective valuable

A retrospective that ends with “be more careful” has not done much work.

The final question is always what should change around the next decision.

That might be:

  • a prerequisite added to a deployment checklist;
  • a health check that validates the user-facing outcome instead of only process state;
  • a mount or storage check before an application starts;
  • a smaller change set so cause and effect remain visible;
  • a test matrix for local, remote, restart, and failure-path behavior;
  • a documentation review trigger before publication;
  • a default that fails closed instead of quietly accepting an ambiguous state;
  • an explicit recovery step before a destructive change.

The best guardrails are usually boring.

That is a compliment.

A small preflight check that prevents a two-hour incident is more valuable than an elaborate retrospective nobody uses again.

I track where the guardrail actually landed

A retrospective can sound complete while the actual system remains unchanged.

“Add a health check” is not a guardrail if it lives only in the notes.

So I now record the destination and status of the follow-up.

Guardrail typeWhere it should land
ChecklistDeployment, update, publication, or recovery checklist
ValidationTest matrix, smoke test, or user-facing acceptance check
AutomationFail-closed preflight, assertion, or repeatable collection script
ArchitectureDependency ordering, isolation boundary, storage/network design, or recovery path
MonitoringAlert or scheduled check for the prerequisite that previously failed silently
DocumentationRunbook, decision record, recovery note, or prerequisite description

I keep the status simple:

captured → planned → implemented → verified

Not every retrospective needs to reach implemented.

Sometimes the right outcome is to record a possible improvement and deliberately reject it because the cost is larger than the risk it addresses. That is still a decision.

What I do not want is a pile of polished lessons whose guardrails never left the article.

A retrospective is not complete because the prose is finished. It is complete when the durable change is implemented, verified, or deliberately rejected with a reason.

I write the first note before the project is finished

Memory straightens the path.

Once a project works, the final sequence starts to feel inevitable. The dead ends seem less important. The first warning looks more obvious than it felt at the time. The successful fix starts absorbing credit for every change that happened near it.

That makes after-the-fact notes dangerous.

I try to capture the first failed assumption while the project is still active.

The note can be tiny:

Assumption: the service was using the remote filesystem because the expected directory existed.

Signal: expected files were missing even though the application could still write there.

Next test: verify the filesystem boundary independently of the application.

That is enough to preserve the uncertainty.

Later, if the issue becomes a Field Note, I can turn that record into a cleaner explanation without pretending the investigation itself was clean.

This approach also fits the troubleshooting method I described in What My Homelab Taught Me About Calm Troubleshooting: preserve evidence first, make the next test narrow, and resist turning the first plausible explanation into the answer.

Public retrospectives need a second edit

My private notes and my public notes are not the same artifact.

The private version may need exact timestamps, hostnames, account names, ticket references, paths, log excerpts, or infrastructure relationships to make the incident supportable.

The public version usually does not.

Before publishing a retrospective, I ask whether each identifier teaches the lesson or merely identifies the environment.

If the lesson is that an application silently used local storage after a dependency disappeared, the public article needs the dependency relationship and the failure mode. It does not need the real server name, storage path, address, share name, user account, or management endpoint.

If a screenshot exposes those details, I would rather reconstruct a clean example than blur half the image and hope I noticed everything.

That boundary is the same one I use in What Goes in Public Documentation, and What Stays Private: preserve the technical relationship, remove the operational identifiers.

A good public retrospective should make the reasoning reusable without making the original environment easier to map.

I also record mistakes in the writing itself

The retrospective process applies to Field Notes too.

A technical article can fail in ways that look different from a broken service but come from the same underlying habits.

A draft can overlap another article so heavily that it adds no new value. A product-specific claim can outlive the version it described. A personal incident can contain more identifying detail than the lesson requires. A confident sentence can outrun the evidence behind it.

Those are editorial failures, but they deserve the same treatment:

assumption → signal → test → result → change → guardrail

For example, if two backlog drafts keep collapsing into the same final argument, the answer is not to publish both with different titles. The guardrail is to review for conceptual overlap before publication and merge, retire, or redirect the weaker idea.

That connects directly to A Backlog Is Not Finished Until the Ideas Are Distinct. Draft count is not the useful metric. Distinct, evidence-backed ideas are.

My current retrospective template

The current version is still short enough that I will actually use it, but it now records provenance and closure too:

Classification: mistake | surprise | unresolved | noise

Assumption:

Signal:

Evidence/artifact:

Test:

Result:

Change:

Next guardrail:

Guardrail destination:

Status: captured | planned | implemented | verified

Still unknown:

Still unknown can be blank when the evidence is complete enough for the claim.

Evidence/artifact does not require a perfect forensic bundle. It can be a log excerpt, screenshot, configuration diff, command output, test result, ticket note, or a simple statement that the original evidence was not preserved and the public example is a reconstruction.

The point is to stop later writing from quietly upgrading memory into evidence.

A longer retrospective can come afterward if the mistake reveals a pattern worth sharing. The short record is what protects the reasoning while it is still fresh.

The goal is not to become afraid of mistakes

I do not record mistakes because I expect a perfect project next time.

That would be a poor use of the exercise.

Complex systems will continue producing surprises. I will continue making assumptions that turn out to be wrong. Tools, dependencies, requirements, and environments change. Sometimes I will simply miss something.

The goal is to make each useful mistake cheaper the second time.

If a failed assumption becomes a better test, the project improved the next investigation.

If a missed prerequisite becomes a guardrail, the project improved the next deployment.

If an unresolved incident teaches me where the evidence stopped, the project improved the next diagnosis.

If a privacy review changes the way I write examples, the project improved the next publication.

That is the standard I care about.

The final system should work, but the final notes should also explain why my process is different now.

Otherwise I fixed the project and threw away part of what it taught me.

AI transparency

AI assisted with organizing and editing the original article and with constructing the classification model, guardrail-status tracking, and the explicitly sanitized retrospective reconstruction added in the September 14, 2026 revision. The underlying examples and retrospective principles are based on my own website, homelab, and support projects. The worked empty-mount record is not presented as the original incident notebook or as a verbatim historical transcript. Environment-specific identifiers and sensitive operational details have been generalized or omitted.

JO

Written by

Jessie Owens

I run Eldritch IT and write about the systems, repairs, infrastructure decisions, and business lessons behind the work.