| name | trail |
| version | 2.5.2 |
| description | Automatic egress service for substantive work. Append a structured entry to .acm/audit-trail.md IN THE TARGET REPO ROOT — recording the interpretation, examination, decisions, actions, and reflection. Destination, Improve, Orient, and Probe apply Trail automatically; the operator should never need to invoke it separately. Direct use remains available for consequential work outside those workflows and independent-writer mode. |
| argument-hint | The target being worked on (repo, file, system) — used to populate the log entry header |
Trail
The record of what actually happened.
ACM role: Writes the core of the memory layer — .acm/audit-trail.md, the append-only record every other skill reads.
Governing principle: Observable Autonomy — The degree of autonomy a system deserves is bounded by the degree of transparency it provides. This skill is how that transparency is produced.
Autonomy without evidence is abdication. When an agent does work autonomously, the question is never "did it do something?" but "can someone who wasn't there reconstruct what happened, why, and whether to trust it?"
A trail that answers this earns the right to more autonomy. A trail that doesn't — or doesn't exist — means autonomy must be constrained regardless of how competent the work was.
Automatic composition contract: In the full suite, Destination, Improve, Orient, and Probe apply Trail automatically whenever they produce a substantive result. The operator should never have to remember or be told to invoke /trail. Direct invocation remains available for consequential conversations or manual work outside those workflows, repairing a missing record, and High-Fidelity Mode where the recorder must be independent from the agent that acted.
Evidence → Trust → Autonomy
The Structure
The trail lives in the root of the target repo being worked on — not in the skills install directory.
If you are improving c:\git\clikit, the trail is c:\git\clikit\.acm\audit-trail.md.
If you are improving ~/projects/myapp, the trail is ~/projects/myapp/.acm/audit-trail.md.
Every repo gets its own trail. The trail is local evidence for that project — it belongs with the project.
One file: .acm/audit-trail.md in the target repo root. Append-only. One ## entry per session, newest at the bottom.
Before any write: create the .acm/ directory in the target repo root if it does not already exist. This applies whether the skill is run alone, as part of a chain, or for the first time on a fresh repo.
If .acm/audit-trail.md does not exist yet, initialise it:
Create .acm/audit-trail.md with this header:
# Audit trail
Append-only ledger of autonomous operations on this repo. Newest entries at the bottom.
---
That's it. Nothing else gets installed into the target repo. The skills repository includes an optional helper at harness/tools/record.py; the one-line skill installer does not copy it. Invoke it from the clone as <skills-repo>/harness/tools/record.py — it writes into the current working directory by default, or whatever $TRAIL_ROOT points to.
After appending to audit-trail.md, regenerate the derived artifacts and commit them together:
python <skills-repo>/harness/tools/record.py history --write
python <skills-repo>/harness/tools/record.py learning --write
git add .acm/audit-trail.md .acm/history.md .acm/learning.md
git commit -m "trail: <slug>"
If history.md/learning.md are not in use for this target (see below — they are optional), the commit needs only .acm/audit-trail.md.
If Orient ran this session and updated .acm/orientation.md, include it in the same commit. .acm/destination.md is operator-managed and is committed only when the operator changes it — never as a side effect of an agent run.
history.md and learning.md are derived from audit-trail.md and are regenerated as part of every Trail commit — they must not lag behind the source. record.py exposes both as standalone subcommands too:
python <skills-repo>/harness/tools/record.py history # timeline to stdout (no write)
python <skills-repo>/harness/tools/record.py learning # markers to stdout (no write)
python <skills-repo>/harness/tools/record.py summary # digest of the most recent run
.acm/
audit-trail.md — append-only ledger, one entry per session (the source of truth; the only Trace-tier artifact required for ACM conformance)
history.md — OPTIONAL. derived run timeline (regenerated by Trail at every commit, if used)
learning.md — OPTIONAL. derived [!REALIZATION] / [!REVERSAL] surface, bounded to a recent window (regenerated by Trail at every commit, if used)
learning-archive.md — OPTIONAL. markers older than the recent window (created once the trail is long enough; regenerated alongside learning.md, if used)
destination.md — operator-held destination (optional; written by Destination, read by Improve, never written by any other skill)
orientation.md — Orient-derived current orientation (written by Orient, read by Improve; optional per ACM but recommended)
sessions/ — legacy: pre-v2.0.0 agent-authored session summaries may exist here from repos with history predating this change; not written to routinely going forward
transcripts/ — verbatim transcript exports (optional but strongly recommended for high-fidelity runs)
Only audit-trail.md is required. Per the Agent Context Memory specification this skillset implements (agent-context-memory SPEC.md §6.1, §6.3), a .acm/ directory is minimally ACM-conformant with just destination.md and audit-trail.md — the spec's own six minimal-conformance criteria are entirely about properties (append-only, author separation, mandate-read-first, interpretation-visible) and never mention history.md, learning.md, or learning-archive.md at all. orientation.md is explicitly optional too, though recommended once a trail is long enough that arc-level synthesis earns its cost.
history.md, learning.md, and learning-archive.md are never hand-written — they exist only as derived reading aids over audit-trail.md for repos where the trail has grown long enough that reading it in full, every run, would be wasteful. A new or small target does not need them: audit-trail.md alone is a fully ACM-conformant trace tier, and step 1 of Improve, Orient, and Intent all already read these files conditionally ("if present" / "if it exists") rather than assuming they exist. Adopt them when audit-trail.md has grown large enough that a compact digest and a bounded learning surface are worth the token cost of maintaining them — not as a default starting point. When adopted, they are exclusively generated by record.py history --write / record.py learning --write, never edited directly, and regenerated at every commit so neither lags behind the source of truth.
learning.md is the compact learning surface — the most recent [!REALIZATION] and [!REVERSAL] markers, in chronological order with date+slug context, bounded to a recent window so the read stays cheap no matter how long the trail gets. Older markers move to learning-archive.md, read only when the recent window doesn't cover what's needed. Improve reads learning.md before audit-trail.md, when present, to act on prior conclusions without re-reading the full history. Both files are regenerated by Trail at every commit, when in use, so neither lags behind audit-trail.md.
Trail does not routinely create agent-authored session summaries. See "Independent capture" for the full-fidelity contract.
Destination and orientation.md are distinct: the destination is the goal the operator holds and rarely changes; orientation.md is the agent's current synthesis of where the target is, rewritten each Orient run. The destination is input to the loop; orientation.md is output.
Both files are committed. record.py is not committed to the target repo — it stays in the skills install.
Each entry in audit-trail.md follows this shape:
## YYYY-MM-DD — <slug>
- target: <what was worked on>
- operator: <who initiated>
- agent: <model / provider>
- skill: <which skill was applied>
- outcome: <what resulted>
- delta: <version before → after, or a one-line summary of change>
### Interpretation of the ask
<What was asked for, verbatim or as close as possible. What the agent understood it to mean.
If , >
[!DECISION]
Condensed entries (when there is no decision to record)
The full template exists to make judgment calls legible — decisions, tradeoffs, rejected alternatives — to an observer who wasn't there. Not every entry contains one. A typo fix, a stale-count correction, or a mechanical find-and-replace with an obviously correct outcome carries no real Decision to justify, no alternative worth rejecting, no prediction worth stating beyond "this will fix X." Forcing the full six-section template onto this class of change adds ceremony without adding observability — the sections would either be trivially restated or padded to look substantive, which is itself a rationalization risk (Principle 2 is concerned with fabricated ceremony as much as with hidden reasoning).
Use the condensed format only when the change involves no genuine judgment call: nothing was weighed against an alternative, no precedent needed checking because there was no decision to check it against, and the outcome was obviously correct once the defect was seen. This is a qualitative test, not a size threshold — a one-line change that involved a real tradeoff still gets the full template, and a multi-file mechanical fix with no judgment call can use the condensed one. If there is any real tradeoff, any rejected alternative worth naming, or any claim a future run might disagree with, use the full template. When in doubt, use the full template — the condensed format is for the absence of a decision, not a way to avoid documenting one that exists.
The condensed shape:
## YYYY-MM-DD — <slug>
- target: <what was worked on>
- operator: <who initiated>
- agent: <model / provider>
- skill: <which skill was applied>
- outcome: <what resulted>
- delta: <version before → after, or a one-line summary of change>
<One paragraph: what was found, what was changed, and how it was verified.
No Decision block — there was no >
...
...
...
...
The four-trigger evaluation and any resulting macro-Hansei are never skipped, even in condensed form — they are the cheapest part of the template and the mechanism most likely to catch a pattern recurring across several small, otherwise-unrelated entries (a worked example: a repo's own trail once found the same "a check's coverage is narrower than its stated purpose" defect four separate times across small, individually-unremarkable fixes in one session — only the trigger evaluation, not any single entry's own reflection, had a chance to name that as a pattern rather than four isolated notes).
Three markers
Insert these inline wherever they occur — inside any section, not only Decision:
[!DECISION] — A choice that could have gone differently. Always include rationale and at least one rejected alternative. Also state a precedent check: whether learning.md (or the equivalent memory-of-realizations artifact) was checked for anything directly relevant to this specific decision, and what was found (or that nothing relevant was found). A read of learning.md at the start of a session is not sufficient insurance against contradicting a precedent recorded earlier in that same session, once a new idea or framing is in play — the check has to happen again, at the point of deciding, not only once at the start.
[!REALIZATION] — Something discovered during the work that changed understanding.
[!REVERSAL] — A decision made and then undone. Both kinds count: reversing a prior run's decision, and backing out of a step planned earlier in the same iteration ("attempted X, then removed it after Y"). Reversals are more valuable than decisions — they show the reasoning evolved. A healthy trail demonstrates consistent reversal density: a long run of entries lacking [!REVERSAL], [!REALIZATION], or outcome-mismatches should be treated as suspect (likely post-hoc rationalization) rather than celebrated as perfection. If your Action and Outcome section narrates "I tried X then removed it," mark it.
[!DECISION] Collapsed six skills to two.
Rationale: the framework's mechanism contradicted its own first principle.
Alternative: keep all six, add cross-references — rejected, complexity without payoff.
Precedent check: learning.md had no prior realization about skill count or collapsing; nothing relevant found.
[!REALIZATION] The debug log captures zero conversation content — only session_start metadata.
[!REVERSAL] Initially planned to keep the PowerShell scripts. Reversed after confirming
they bind the suite to one OS for no reason a few hundred lines of Python won't satisfy.
[!REVERSAL] Within this iteration: added a check_non_canonical_markers() function to verify.py.
Reversed after running it produced 46 false positives from entries that mention marker syntax in prose.
The data-loss problem is solved at the source by the regex fix; the style check needs a better heuristic.
To find every load-bearing decision across all sessions:
grep -rn '\[!DECISION\]\|\[!REALIZATION\]\|\[!REVERSAL\]' .acm/
Independent capture
Trail serves three observer resolutions:
| Resolution | Source | Answers |
|---|
| Digest | outcome and delta in audit-trail.md | What happened? |
| Indexed | [!DECISION], [!REALIZATION], and [!REVERSAL] markers | What changed in the reasoning? |
| Full | A harness ledger or the host's session history | What was the complete interaction, including dead ends? |
The Full source must be captured independently of the audited agent. Trail does not routinely create a second, agent-authored session summary; structured reasoning belongs in audit-trail.md, while full-fidelity telemetry belongs in the harness or host that observed the session.
For every entry:
- Record the prediction before acting.
- Mark within-iteration reversals with
[!REVERSAL].
- Name and reject at least one alternative when a decision exists.
- Prefer literal operator text and tool evidence over paraphrase.
Independent capture is optional for ordinary Trail validity. When the operator wants it surfaced in the repo, link or copy it at .acm/transcripts/<date>-<slug>.md and add transcript-file: plus transcript-fidelity::
verbatim - exact export from an independent source.
verbatim-structural - independent export produced through a structural capture workflow.
reconstructed - legacy self-authored reconstruction; weakest fidelity and never independent.
Never label reconstructed material as verbatim.
When to write an entry
Every session that produces a decision, realization, or finding. This includes conversations. There is no such thing as "just conversation" if a decision was made in it.
The distinction between "doing work" and "having a conversation" is false. A conversation that names a threat, approves a design direction, or rejects an approach is work. If it isn't logged, the next session cannot inherit it. ACM breaks at exactly that boundary.
Write during the session, not after. A trail written from memory compresses and rationalises. The markers belong in context, at the moment the decision or reversal occurs.
If you are unsure whether this session warrants an entry: if a decision was made that the next agent session would need to know about, write the entry. If nothing was decided and nothing was learned, silence is correct.
Multi-iteration runs
Each iteration is a separate trail entry. Append it immediately after that iteration completes — before beginning the next iteration.
Do not buffer entries to write at the end of all iterations. The trail is the checkpoint: if the agent crashes, times out, or the user stops the run after iteration 3 of 10, the first 3 entries must already be committed to audit-trail.md.
The mandatory sequence per iteration:
iteration 1:
1. append entry to .acm/audit-trail.md
2. python <skills-repo>/harness/tools/record.py history --write ← updates .acm/history.md
3. python <skills-repo>/harness/tools/record.py learning --write ← updates .acm/learning.md
4. git add .acm/audit-trail.md .acm/history.md .acm/learning.md && git commit -m "trail: <slug>-1"
↓ only now begin iteration 2
iteration 2:
1. append entry to .acm/audit-trail.md
2. python <skills-repo>/harness/tools/record.py history --write
3. python <skills-repo>/harness/tools/record.py learning --write
4. git add .acm/audit-trail.md .acm/history.md .acm/learning.md && git commit -m "trail: <slug>-2"
↓ only now begin iteration 3
...
Do not begin the next iteration until steps 1–4 are complete. Each commit is a checkpoint — if the agent crashes or the user stops after iteration 3 of 10, the first 3 entries are already committed in all three files. Batching at the end defeats this.
What this skill is not
Not a log of events. A log records what happened. A trail records why — the reasoning that made the action the right choice. Without the why, an observer can see the diff but cannot judge whether it was correct.
Not a post-hoc summary. Better than nothing. Not the same as a trail written in real time.
Not overhead. The three markers take seconds. The cost of skipping them is discovering months later that no one can reconstruct why a critical decision was made.
The test
Can someone who was not present reconstruct what was done, why each significant decision was made, and whether the work achieved what was asked for — using .acm/audit-trail.md alone, or with it plus an independent capture source (harness ledger, host product history, or a linked transcript) when one exists?
If yes, the trail is sufficient. If no, something is missing.
Composing with other skills
Trail is the automatic egress service for the full suite. Destination, Improve, Orient, and Probe invoke it without operator orchestration. When Intent is active, paste its narration verbatim into the "Interpretation of the ask" section of the same entry — Intent and Trail form the ingress/egress envelope around one substantive operation, not two separate records.
Trail also works standalone for consequential conversations, manual operations, or decisions outside another skill's workflow, and as the independent writer in Improve's High-Fidelity Mode.
The optional <skills-repo>/harness/tools/record.py helper can stub a new entry for you:
python <skills-repo>/harness/tools/record.py new --slug=<slug> --target=<target> --skill=trail