Skip to content

[adoption] reconcile --json ok/drift fields are undocumented, and ok means something different than it does for init --migrate --json #258

Description

@chrisdpurcell

Summary

project-standards reconcile --check --json reports "ok": true while exiting 1 on a plan with pending mutations. The top-level ok and drift fields that reconcile --json emits are not documented, and ok does not carry the same meaning it carries for init --migrate --json, where docs/usage.md explicitly promises it does.

Context

  • Adoption mode: fresh adoption (Catalog 5, no prior standards authority)
  • Project Standards version: 5.29.0, installed from git+https://github.com/L3DigitalNet/project-standards@v5.29.0
  • Selected packages: adr (latest -> 1.6), agent-handoff (latest -> 1.17)
  • Relevant options: adr.config.require_sections = true; agent-handoff.config = { contract_version = "1.1", startup = "automatic", harnesses = ["claude-code", "codex"] }
  • OS / Python: Linux x86_64, Python 3.14.7, installed with uv tool install
  • Harness: an agent following docs/adoption-prompt-blank.md

Reproduction

project-standards init --catalog 5
project-standards standards enable adr --version latest
project-standards standards enable agent-handoff --version latest
# add the two [standards.*.config] blocks from the adoption guides
project-standards reconcile --check --json

Expected

Either the ok field tracks readiness the way the documented init --migrate --json contract does, or docs/usage.md documents what ok and drift mean for reconcile --json so a consumer can tell which field is the readiness signal.

Actual

Exit code 1, with:

{ "ok": true, "drift": true, "mode": "check", "plan": { "findings": [] } }

findings is empty. After reconcile --apply, the same command returns exit 0 with {"ok": true, "drift": false}.

Why this is confusing

docs/usage.md documents the two commands differently:

  • For init --migrate: "the JSON ok and applicable fields carry the same readiness signal as the exit code."
  • For reconcile: the --json option is described only as emitting "stable plan, action, finding, recovery, or apply fields". Neither ok nor drift is defined, and the exit-status line ("1 drift/findings/apply failure") is the only readiness contract.

So the same field name means "ready" in one command and "no findings" in the other. That difference is what issue #23 fixed for init --migrate; the same reading trap remains for reconcile.

Consumer consequence

Non-blocking, but it costs review time and invites a wrong automation. An agent or CI step that learned ok == readiness from the init --migrate contract will read a pending, unapplied reconcile as complete and skip the apply. The official agent adoption prompt has to coach around this explicitly — it tells the operator to "verify that JSON still reports ok: true" while treating --check drift as expected — which is evidence that the field pair needs a written contract rather than per-prompt guidance.

Suggested resolution

Document the reconcile --json top-level fields in docs/usage.md under reconcile, stating explicitly that ok reports the absence of findings/conflicts and drift reports pending mutations, and that the exit code tracks drift || !ok. Cross-link #23 so the two contracts read together.

Workaround

Read drift (or the exit code) rather than ok when deciding whether an apply is still pending. No functional impact; the tool behaved correctly throughout the adoption.

Related: #23.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions