Skip to content

feat(android): Android host baseline + AGENTS.md remediation - #62

Merged
verlyn13 merged 2 commits into
mainfrom
feat/android-host-baseline
Aug 13, 2026
Merged

feat(android): Android host baseline + AGENTS.md remediation#62
verlyn13 merged 2 commits into
mainfrom
feat/android-host-baseline

Conversation

@verlyn13

Copy link
Copy Markdown
Member

Two commits, reviewable independently.

1. feat(android) — Android host-capability baseline

Extends the existing chezmoi / mise / ng-doctor / Homebrew / system-update
mechanisms; no parallel android/ subsystem, no universal package manifest.

  • docs/android-development.md — host owns capabilities, the repository owns
    build policy (AGP, Gradle, Kotlin, Java, compileSdk/targetSdk, NDK, CMake).
  • home/dot_androidrc.tmpl — canonical SDK root as the Android CLI default,
    gated on the android machine-data key through .chezmoiignore.
  • ng-doctor android [project] — 7 read-only checks. The project form reads
    only repository-owned declarations; it never edits, installs, or builds.

Implementation choices worth review

Launcher vs payload. The Homebrew cask ships a stub that downloads the real
CLI to $ANDROID_USER_HOME/bin/android-cli on first run. A cask receipt is
therefore not evidence the CLI exists or has ever parsed ~/.androidrc, and the
doctor reports the two states separately. The default is ~/.androidnot
~/.android/cli, which Android Studio already owns for its IPC handshake. This
was established empirically by planting stubs at each candidate path and
observing which the launcher exec'd.

Tap provenance. Google's android/tap is real and is the only route Google
documents. This baseline still chooses Homebrew's core cask, for stated reasons:
pinned version + real SHA-256, and no postflight — the tap's postflight runs
the payload download unattended during brew install, collapsing the
launcher/payload boundary the doc depends on.

Parsers ignore comments and recurse. A superseded declaration left behind as
a comment cannot shadow the live one, and modules are found at any depth
(.git, .gradle, build, node_modules pruned).

CI installs chezmoi. tests/android/run.sh renders managed templates and
hard-fails when chezmoi is absent — deliberate, since a suite that skips in CI
asserts nothing. The runner has none, so the workflow installs it pinned to
2.72.0, matching the workstation.

2. docs(agents) — AGENTS.md remediation

AGENTS.md: 300 → 106 lines, 19,944 → 5,674 bytes. The annotated doc index
(8 KB on its own) moves to a new docs/README.md, which is now complete —
50 top-level docs plus every subtree entry point, against 42 before. Eleven
docs were unindexed, including the incident that justifies the GitHub-MCP
containment the old file treated as important.

Hazards that were buried in index annotations are lifted into an explicit
## Hazards block as imperatives. Nothing was deleted without a destination.

Resolves a live self-contradiction: the file required hasKey in one section,
mandated | default in Definition of done, and prescribed | default as the
fix for map has no entry for key — the error | default produces.

Validation

  • scripts/validate-repo.sh: PASS (at both commits)
  • tests/android/run.sh: 28 passed, 0 failed (was 19)
  • Mutation-tested rather than trusted: reverting the payload-path fix → 1 failure;
    reverting the bash 3.2 empty-array guard → 2 failures
  • Live ng-doctor android: 4 passed, 2 failed, 1 skipped — both failures are
    documented operator actions with remediation in the doc
  • Deployed chezmoi targets: zero-byte chezmoi diff
  • All doc links in AGENTS.md and docs/README.md resolve
  • scripts/check-instruction-bridge.sh passes; CLAUDE.md stays under the
    byte-ratio floor

Remaining risks

  • The CI chezmoi install is unexercised until this PR's first run — that is the
    main thing to watch on the checks.
  • ng-doctor now carries two standing Android failures. Nothing in the repo
    consumes its exit code, so no automated path turns red, but the host goes
    from 3 to 5 standing failures until an operator runs android info and
    removes the incomplete ndk/29.0.13599879 remnant.
  • ~/.claude/CLAUDE.md (user-global, loads ahead of every repo file) contains
    several ghost tools and a stale repo name. Out of scope here; worth filing
    against docs/ai-tool-config-ownership.md §7.7.
  • docs/host-capability-substrate/templates/{AGENTS,CLAUDE}.md are copy-me
    templates wearing live instruction-file names, so both runtimes load them as
    instructions in that subtree. Renaming to *.template would neutralise them
    but changes an established HCS contract — operator decision.

Extend the existing chezmoi, mise, ng-doctor, Homebrew, and system-update
mechanisms rather than adding a parallel android/ subsystem.

- docs/android-development.md states the host/project ownership split:
  system-config owns host capabilities, the repository owns build policy.
- home/dot_androidrc.tmpl deploys the canonical SDK root as the Android CLI
  default, gated on the `android` machine-data key via .chezmoiignore.
- ng-doctor gains an `android [project]` category (7 checks) reporting host
  capability and, optionally, a project's declared requirements read-only.

The doctor separates launcher installation from payload initialization: the
Homebrew cask ships a stub that downloads the real CLI to
$ANDROID_USER_HOME/bin/android-cli on first run, so a cask receipt is not
evidence the CLI exists or has ever parsed ~/.androidrc.

Parsers ignore commented-out declarations and search modules at any depth,
so a superseded value left behind as a comment cannot shadow the live one.

tests/android/run.sh adds 28 assertions and is wired into the gate; the
workflow now installs a pinned chezmoi, without which the suite's deliberate
hard-fail would redden CI on every push.
…/README.md

AGENTS.md had grown to 300 lines / 19.9 KB, 53% of the always-on instruction
context a Claude session loads before reading a line of code. Roughly half of
it was derivable (a directory tree, a restatement of validate-repo.sh's steps,
an MCP inventory `jq` prints) or duplicated from an ancestor file.

The annotated doc index alone was 8 KB — 132% of a 6 KB budget for the whole
file — so it moves to docs/README.md, which has no budget, can carry the long
annotations verbatim, and is now complete: 50 top-level docs plus every subtree
entry point, against 42 before. Eleven docs were previously unindexed,
including the incident that justifies the GitHub-MCP containment.

Hazards embedded in index annotations are lifted into an explicit `## Hazards`
block and stated as imperatives. An annotation only reaches an agent that has
already decided to open that doc; the agent about to delete the MCP disable
marker did not arrive via the index.

Resolves a live self-contradiction: the file required `hasKey` in one section,
mandated `| default` in Definition of done, and prescribed `| default` as the
fix for `map has no entry for key` — the error `| default` produces. Stated
once now: chezmoi runs missingkey=error, `android` is a required key so
reading it bare is correct, and `hasKey` is for genuinely optional keys.

Also corrected: the gate description claimed shellcheck covers every `.sh`
(it is tracked-only, deliberately) and called the fish check a grep (it is a
directory test); `chezmoi apply --dry-run` needs `--force` to complete
non-interactively; README's docs count and index pointer.

AGENTS.md: 300 -> 106 lines, 19,944 -> 5,674 bytes.
@verlyn13
verlyn13 requested a review from a team as a code owner August 13, 2026 05:42
@verlyn13
verlyn13 merged commit 1302b8e into main Aug 13, 2026
2 checks passed
@verlyn13
verlyn13 deleted the feat/android-host-baseline branch August 13, 2026 05:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant