Skip to main content

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 init before bootstrap, 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:

FieldSemantics
eventsOrdered list of invocation records (append-only)
tool_versionA2C CLI version that last wrote the file
updated_atISO-8601 UTC timestamp of the last append

Each event:

FieldSemantics
atISO-8601 UTC timestamp
tool_versionA2C CLI version at invocation
commandSpace-separated command path (e.g. validate, list epics, metrics collect)
argvSerializable option/argument map (paths as strings; omit None; never log stdin bodies)
successtrue when exit code is 0
resolvedOptional 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 version outside any A2C repository).
  • Do not skip failed commands — failures are often the events most needed for debugging.
  • init and bootstrap journal to the target path even before root markers exist, using the same -C / --path resolution 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

SituationJournal root
Command is init or bootstrapResolved target directory (-C / --path or cwd)
Any other commandfind_repo_root(-C / cwd) when inside an A2C repository
No root foundNo 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 successful init (without a prior successful bootstrap)
  • bootstrap-first — first successful bootstrap

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

ArtifactRole
.a2c/adoption.yamlFrozen adoption anchor and drift detection
.a2c/cli-journal.yamlAppend-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 a2c command 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 constant
  • a2c_core.services.cli_journal — load, append, infer entry path