Skip to content

adf: no repo records whether vendor files are compiled or pointers, so compile --check and tidy disagree forever #318

Description

@stackbilt-admin

Split out from #296, which fixes the immediate data loss. This is the design question underneath it.

The problem

adf compile --write expands .ai/ into the vendor files. adf tidy folds the vendor files back into .ai/. They are exact inverses, and nothing records which one a repo has chosen.

#296 stops tidy from eating compiled output. It does not answer "which mode is this repo in?", and that question has other consequences.

Evidence it is not hypothetical: this repo

Charter's own vendor files are thin pointers:

CLAUDE.md        tracked=yes  pointer (18 lines)
AGENTS.md        tracked=yes  pointer (8 lines)
.cursorrules     tracked=yes  pointer (5 lines)
GEMINI.md        tracked=yes  pointer (8 lines)

And adf compile --target all --check reports all four stale, permanently:

[stale] CLAUDE.md — out of date with .ai/ source.
        Run: charter adf compile --target claude --write
[stale] AGENTS.md — out of date with .ai/ source.
...

That remediation line is wrong for this repo. Running it would replace the deliberate pointers with full compiled content — changing the repo's mode, not fixing drift. --check has no concept of pointer mode; it assumes compiled mode unconditionally and calls any pointer stale.

This is the same root cause #296 reports as a "related symptom", not a separate defect: the reporter saw permanent staleness because tidy had turned their files into pointers.

Why the documented path walks into it

README.md:39 tells every new user:

npx charter adf compile --target all --write

then hook install --pre-commit, then commit — at which point the hook runs tidy. The quickstart puts a fresh repo into the oscillating state. #296 stops that from corrupting .ai/, but the repo still ends up with --check permanently red and a remediation that would flip its mode.

Options

  1. Record the mode in .charter/config.json — e.g. vendor: "compiled" | "pointer". tidy no-ops in compiled mode; compile --write warns in pointer mode; --check only checks compiled-mode repos, and in pointer mode verifies the pointer is intact instead. Explicit, greppable, survives hand-editing. Costs a config migration and a default for existing repos.
  2. Detect per-file from the compile banner — the approach bug(adf tidy): ingests compiled vendor output back into core.adf, duplicating content and reverting deliberate deletions #296 takes. Zero migration, matches what .githooks/pre-commit:16 has done in the field. But a repo can sit mixed indefinitely, and stripping the banner silently flips a file's meaning.
  3. Make them explicit inverses, last writer wins — most honest about intent, largest change, and does not help the pre-commit hook running tidy unattended.

Recommendation recorded during the #296 triage: 2 now (shipped in #296), 1 later. This issue tracks 1.

Also worth fixing when this is picked up

charter adf sync --write is a natural thing to reach for when --check says stale, and it is not the fix — it writes .ai/.adf.lock from declared SYNC: entries and reports Wrote empty lock file (no SYNC entries declared) when there are none. That message is accurate but lands as a dead end for someone chasing a stale compile --check. Worth a pointer in the output toward what staleness actually means once mode is a concept.

Acceptance

  • A repo can state its vendor mode, or it is inferred consistently by every command that cares (compile --write, compile --check, tidy, the generated pre-commit hook, doctor).
  • compile --check does not report a deliberate pointer as stale.
  • No remediation line suggests a command that would silently change the repo's mode.

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