ADR-0014: CLI invocation journal
- Status: Accepted
- Date: 2026-06-21
- Deciders: Michel Gillet
Context
Operators and AI agents debugging A2C adoption issues need a durable, machine-readable audit trail of which a2c commands ran, with what arguments, whether they succeeded, and which tool version was installed at the time.
The migration assistant for legacy superbuilds (eai-supmig) already solves this with .migration/cli-journal.yaml: an append-only event log updated after every CLI invocation. That journal supports entry-path detection (inventory-first vs bootstrap-first) and makes support conversations reproducible without relying on shell history.
A2C has .a2c/adoption.yaml (ADR-0013) for adoption anchors and drift warnings, but nothing records day-to-day CLI usage. Without a journal:
- Support threads cannot reconstruct the sequence that led to a broken bootstrap or missing manifest.
- AI agents cannot infer whether the operator ran
initbeforebootstrap, or only partial setup commands. - Doctor and future workflow tooling lack a canonical source for “last successful command” and adoption entry path.
This ADR mirrors the superbuild journal contract under A2C’s .a2c/ tool-internal namespace.
Decision
1. Append-only journal file
Every a2c command that completes (success or failure) appends one event to .a2c/cli-journal.yaml when a journal root can be resolved (see §3).
Top-level file shape:
| Field | Semantics |
|---|---|
events | Ordered list of invocation records (append-only) |
tool_version | A2C CLI version that last wrote the file |
updated_at | ISO-8601 UTC timestamp of the last append |
Each event:
| Field | Semantics |
|---|---|
at | ISO-8601 UTC timestamp |
tool_version | A2C CLI version at invocation |
command | Space-separated command path (e.g. validate, list epics, metrics collect) |
argv | Serializable option/argument map (paths as strings; omit None; never log stdin bodies) |
success | true when exit code is 0 |
resolved | Optional map with repo_root when known |
The file is tool-internal, like .a2c/config.yaml and .a2c/adoption.yaml. It is intended to be committed so teams and CI share the same audit trail (not listed in .gitignore).
2. When to write
- Write after every subcommand when a journal root is resolved.
- Skip when no journal root applies (e.g.
a2c versionoutside any A2C repository). - Do not skip failed commands — failures are often the events most needed for debugging.
initandbootstrapjournal to the target path even before root markers exist, using the same-C/--pathresolution as other commands.
Journaling is non-blocking: I/O errors append a warning to stderr but do not change the command exit code.
3. Journal root resolution
| Situation | Journal root |
|---|---|
Command is init or bootstrap | Resolved target directory (-C / --path or cwd) |
| Any other command | find_repo_root(-C / cwd) when inside an A2C repository |
| No root found | No journal write |
4. Entry-path inference (optional helper)
a2c_core.services.cli_journal.infer_entry_path() returns the first successful path-setting adoption command:
init-first— first successfulinit(without a prior successfulbootstrap)bootstrap-first— first successfulbootstrap
This mirrors superbuild’s entry-path helper and supports future workflow status output. It is read-only in this ADR; no new CLI subcommand is required.
5. Doctor
a2c doctor reports journal presence and the latest event summary (command, success, timestamp). A missing journal is informational, not a hard failure — legacy repositories gain a journal on the next command.
6. Relationship to ADR-0013
| Artifact | Role |
|---|---|
.a2c/adoption.yaml | Frozen adoption anchor and drift detection |
.a2c/cli-journal.yaml | Append-only audit log of CLI invocations |
.a2c/metrics/ | Historical delivery metrics (M9/M10) |
These serve different purposes and may all coexist under .a2c/.
Consequences
Positive
- Reproducible support and agent debugging from repository state instead of shell history.
- Entry-path inference for init-first vs bootstrap-first adoption flows.
- Consistent pattern with
eai-supmig/ superbuild migration assistant journaling.
Negative
- Journal files grow without bound; a future ADR may add rotation or compaction.
- Sensitive values passed on the CLI (tokens in flags) could be logged if operators pass them inline — prefer env vars and config files for secrets.
- Repositories adopted before this ADR have no history until the next
a2ccommand runs.
References
- docs/cli.md — CLI overview and journal behavior
- ADR-0013 — adoption version record
- Superbuild reference:
eai_supmig.cli_journal—.migration/cli-journal.yaml a2c_core.contracts.paths.CLI_JOURNAL_FILE— path constanta2c_core.services.cli_journal— load, append, infer entry path