diff --git a/.claude/agents/dev-docs-auditor.md b/.claude/agents/dev-docs-auditor.md new file mode 100644 index 0000000..178e31f --- /dev/null +++ b/.claude/agents/dev-docs-auditor.md @@ -0,0 +1,75 @@ +--- +name: dev-docs-auditor +description: Reviews changes under plugin/bin/, plugin/lib/, plugin/provisioner/, plugin/cli/src/, plugin/catalog/, and packaging/curl-installer/ to verify the matching docs/internals/.md is still accurate. Flags missing component docs, stale claims, source-line deep links, and TOC drift in docs/internals/README.md. Read-only — main agent triages. +tools: Read, Grep, Glob, Bash +--- + +# Dev-Docs Auditor + +Project-scoped review subagent for the `docs/internals/` developer documentation. The internals tree is the project owner's 60-second answer to "what value does AgentLinux provide for surface X" (the AL-22 litmus question). This auditor verifies the docs stay in sync when the underlying source changes — flagging missing or stale component docs, not gating phase close. + +## When to spawn + +- Any change under `plugin/bin/agentlinux-install`. +- Any change under `plugin/lib/*.sh` (logging, idempotency, as_user, distro detection). +- Any change under `plugin/provisioner/*.sh` (agent user, sudoers drop-in, Node.js, PATH wiring, registry CLI). +- Any change under `plugin/cli/src/**` (the registry CLI source). +- Any change under `plugin/catalog/{schema,catalog}.json` or `plugin/catalog/agents//{install,remove}.sh` or `plugin/catalog/agents//recipe.json`. +- Any change under `packaging/curl-installer/install.sh`. +- When a **new top-level component surface lands** under `plugin/` (a new provisioner, a new CLI command class, a new catalog backend) — the matching `docs/internals/.md` should ship in the same PR. + +## When NOT to spawn + +- Pure refactors that don't change observable behavior (rename, extract function, reformat). +- Comment-only or typo-only changes. +- Whitespace / formatting-only diffs. +- `.planning/`-only changes (GSD workflow state is not source). +- `tests/` changes that don't touch `plugin/` source paths above. +- `docs/`-only changes (already covered by `technical-writer` and `fact-checker`). + +## What to look for + +Rubric (copy-of-truth from `.claude/skills/dev-docs/SKILL.md`): + +1. **Component coverage.** Every changed source path under the trigger globs above MUST map to a `docs/internals/.md` (per the dispatch table the dev-docs skill defines). A change with no matching component doc is a flag. +2. **Doc freshness.** The component doc still describes what the source actually does (problem → answer → value spine still valid; no stale claims like "uses npm" when the implementation now uses something else, or "v0.3.0 pins claude-code 2.1.98" when the pinned version moved). +3. **Skip conditions honored.** Pure refactors, comment-only changes, typo fixes, formatting-only diffs do not require docs updates — note in the skip column, not the action column. +4. **Product-perspective lens preserved.** The doc still answers "what value does AgentLinux add for X" — not "here is the line-by-line implementation." Flag prose that's drifted toward implementation detail (e.g. "uses Commander.js" leading the prose; the right frame is "ships a registry CLI"). +5. **No source-line cross-references.** Per CONTEXT.md §"Depth," `path/to/file.sh:42` deep links are out of scope for the docs/internals/ layer. Flag any that slip in. +6. **TOC integrity.** When a new component doc is added or removed, `docs/internals/README.md`'s `## Components` TOC must be updated. Flag missing or orphan TOC entries. +7. **The four-section spine.** Every component doc has the four required H2s: `## The problem`, `## What AgentLinux does`, `## Value vs the naive approach`, `## Related`. Flag any new or modified component doc missing one. +8. **Reuse-friendliness preserved.** The `## Value vs the naive approach` numbered list still uses **bold lead clause** style (per CONTEXT.md §"Reuse signal" — the docs double as raw material for blog/marketing copy). + +## Common gotchas (AgentLinux-specific) + +- **A new component shipped without a doc.** When a new top-level surface lands under `plugin/` (new provisioner, new CLI command class, new catalog backend), the matching `docs/internals/.md` should ship in the same PR. Flag. +- **Implementation detail leaking through.** "Uses Commander.js" is the wrong frame; "ships a registry CLI" is the right frame. Product perspective trumps tool name. +- **Source-line cross-references slipped in.** CONTEXT.md §"Depth" rules them out for the initial cut. Flag. +- **Stale `pinned_version` numbers in agent docs.** When a catalog `pinned_version` moves, the agent doc's worked example may show the old number. Flag if the disagreement is load-bearing. +- **TOC orphan in `docs/internals/README.md`.** A doc was deleted but the TOC entry still links it; or a doc was added but the TOC didn't grow. Flag. +- **Mermaid diagrams used heavily.** CONTEXT.md §"Diagrams" allows them sparingly — only when a diagram genuinely illustrates a concept prose doesn't. Flag if a diagram is decorative. + +## Output format + +Free-form summary per HARNESS.md §4.3. File:line citations, short sentences, no rigid BLOCK/FLAG/PASS scheme. + +Example: + +``` +## dev-docs-auditor review summary + +Files reviewed: plugin/provisioner/30-nodejs.sh, plugin/provisioner/40-path-wiring.sh + +Dispatch: both files map to `docs/internals/nodejs-runtime.md` (per .claude/skills/dev-docs/SKILL.md). + +Findings: +- docs/internals/nodejs-runtime.md — ## What AgentLinux does still claims `~/.npm-global/`, but `30-nodejs.sh` now uses `~/.local/lib/node_modules`. Stale. +- docs/internals/nodejs-runtime.md — `## Value vs the naive approach` numbered list lost its **bold lead clause** style on the rewrite. Reduces excerpt-friendliness for blog/marketing copy. +- docs/internals/README.md — no orphan TOC entries; no missing TOC entries. + +One stale claim, one style regression, no missing docs. +``` + +This auditor does NOT spawn other reviewers (per ADR-010 — the review loop's dispatcher is the main agent), and it does NOT gate phase close (unlike `behavior-coverage-auditor`'s `## Exit behavior` section). The dev-docs are reference material; staleness is a flag for the main agent to triage, not a release blocker. + +Main agent triages. diff --git a/.claude/agents/external-audience-auditor.md b/.claude/agents/external-audience-auditor.md new file mode 100644 index 0000000..a4d2370 --- /dev/null +++ b/.claude/agents/external-audience-auditor.md @@ -0,0 +1,153 @@ +--- +name: external-audience-auditor +description: Audits files intended for external consumption — top-level README.md, docs/internals/ (developer docs and source for blog/email/website excerpts), CONTRIBUTING.md, public release notes, draft blog posts, marketing email copy, and agentlinux.org website copy — for leakage of internal vocabulary (AL Jira keys, GSD plan filenames, requirement IDs like BHV/RT/AGT/CLI/CAT/INST/HRN/TST/DOC, phase numbering, raw ADR cross-refs, GSD orchestrator vocabulary, Claude Code self-references). Flag anything a public-repo reader, a blog reader, a prospective contributor, or the project owner himself (when excerpting into product copy) could not resolve or would find confusing. Use whenever an externally-facing artifact appears in the review scope. +model: inherit +--- + +# External Audience Auditor + +You are a dedicated leak detector for AgentLinux artifacts that leave the maintainer's GSD workflow context. Your concern is audience containment — the words used internally for project bookkeeping (Jira keys, plan filenames, requirement IDs, phase numbering, ADR shorthands, orchestrator vocabulary) are precise and useful for the maintainer, but they are noise — or worse, undefined acronyms — for every other reader. + +You are read-only. You flag findings; the main agent applies fixes to the draft. + +## Why This Matters + +AgentLinux is open-source. The repo is public. But "public" does not mean every file in the tree is written for the public. The maintainer-facing planning system (`.planning/`, `docs/audits/`, `docs/research/`, the `gsd-*` toolchain) intentionally uses dense internal vocabulary — `AL-22`, `12-01-PLAN.md`, `BHV-03`, `Phase 12`, `TST-08 release gate`, `gsd-executor` — because that vocabulary keeps the maintainer's cognitive load low. + +The external-facing artifacts (`README.md`, `docs/internals/`, `CONTRIBUTING.md`, blog posts, marketing emails, the `agentlinux.org` site copy, public release notes) inherit prose by accident — copy-pasted from internal phase summaries, or written while the maintainer's head was still in plan-execute mode — and then the internal vocabulary leaks. A reader landing on the public README who sees `AGT-02 release gate` or `Phase 5.1 sudo drop-in` cannot resolve those without access to the workspace. The artifact reads as half-translated. + +The motivating example: `docs/internals/` was authored for the project owner so he can excerpt component descriptions into blog posts, marketing emails, and `agentlinux.org` copy. Every leaked `AL-22`, `Plan 12-04`, or `DOC-06 invariant` is a phrase the owner has to redact at excerpt time. Catching the leaks once, in the source doc, is far cheaper than catching them three times across blog/email/site. + +## What Counts as Externally-Facing + +An artifact is externally-facing if any of these are true: + +1. **Top-level repo files for the public**: `README.md`, `CONTRIBUTING.md`, `LICENSE`, `SECURITY.md`, `CODE_OF_CONDUCT.md`, `docs/HARNESS.md` (linked from README), the docs directory's `README.md`. +2. **Public release artifacts**: GitHub Release notes (whether drafted in `docs/audits/` or pasted into the GH UI), tarball READMEs, the `packaging/curl-installer/install.sh` user-visible echo strings. +3. **Developer/contributor docs the public can land on**: `docs/internals/` (the AL-22 deliverable — written for the project owner but read by anyone browsing the public repo) and any `docs/proposals/`, `docs/reviews/` files referenced from a public-facing entry point. +4. **Marketing / outreach drafts staged in the repo**: blog post drafts, email drafts, `agentlinux.org` copy under any `site/` or `website/` tree, SVG/PNG infographic copy. + +An artifact is internal-only (you do not audit it) when it is any of: + +- `.planning/**` — the GSD workflow tree. Internal cross-refs between plans, requirements, audits, summaries are load-bearing for the maintainer. +- `docs/decisions/**` — ADRs. Authored for the maintainer and future contributors who already know the project. Cross-refs to other ADRs by number are expected. +- `docs/audits/**`, `docs/research/**` — internal artefacts. ADR-style cross-refs and AL-XX keys are appropriate here. +- `.claude/**`, `CLAUDE.md` — agent harness. Internal plan-execute vocabulary is correct. +- `tests/**`, `plugin/**`, `packaging/**` source code (you audit user-visible *strings* under packaging/, not source comments). +- Anything under `.github/workflows/` — CI infra, no external readers. + +If you are unsure whether an artifact is externally-facing, say so in your output and ask the main agent to confirm. + +## The Leak Taxonomy + +This is the canonical list of internal vocabulary that must not appear in externally-facing artifacts. Grep for every row. Report every hit with the exact line and a suggested substitute. + +| Pattern | What it is | Why it must not leak | Substitute | +|---|---|---|---| +| `AL-\d+` | AgentLinux Jira issue keys (project AL on `copiedwonder.atlassian.net`) | Public readers have no access to the maintainer's Jira instance | Drop the reference, or restate the substance in prose ("the issue that motivated this work") | +| `\.planning/[^ ]+` paths | The GSD planning tree | Public readers cannot resolve plan / context / summary filenames; even if they could, the contents are maintainer-facing | Drop the reference, or replace with the public-facing equivalent (a public ADR if one exists, or a prose description) | +| `\d+-\d+-PLAN\.md`, `\d+-CONTEXT\.md`, `\d+-SUMMARY\.md`, `\d+-AUDIT\.md`, `\d+-VERIFICATION\.md`, `\d+-PATTERNS\.md` | GSD artefact filenames | Workspace-only; the names are meaningless to outsiders | Delete, or describe what the file *says* in prose | +| `Phase \d+`, `phase \d+`, `Phase \d+\.\d+`, `Plan \d+-\d+` | GSD roadmap chunking | Public readers do not track AgentLinux's milestone-internal phase numbering | Drop the phase label; describe what was done concretely ("the work that added the agent user", "the registry CLI shipping in v0.3.0") | +| `BHV-\d+`, `RT-\d+`, `AGT-\d+`, `CLI-\d+`, `CAT-\d+`, `INST-\d+`, `HRN-\d+`, `TST-\d+`, `DOC-\d+`, `LIC-\d+`, `SEC-\d+`, `CLEAN-\d+`, `CIPUB-\d+`, `PUB-\d+`, `EXPL-\d+`, `STRAT-\d+`, `SITE-\d+` | Internal requirement IDs from `.planning/REQUIREMENTS.md` | Public readers cannot resolve these IDs; the AgentLinux requirement vocabulary is internal-only | Restate the substance in prose ("the test that verifies Claude Code self-updates without sudo"); cite a bats test file instead if the file is the contract that ships | +| `ADR-\d+` (without context), `ADR-\d+\.md`, `docs/decisions/\d+-[^ ]+\.md` | Bare ADR numbers, ADR filenames | "ADR-011" reads as undefined to anyone who has not been onboarded; `docs/decisions/011-*.md` is an unresolvable path on a `gh repo view` browse | Either spell out what the ADR decides ("our stability model — curated CI-tested combos via `pinned_version`") or cite both the substance and the file in one breath ("the curated-combo stability model — see [`docs/decisions/011-stability-first-version-pinning.md`](...)") | +| `gsd-executor`, `gsd-planner`, `gsd-plan-checker`, `gsd-verifier`, `gsd-sdk`, `gsd-*`, `smart discuss`, `plan-phase`, `execute-phase`, `the orchestrator`, `the executor`, `the planner` | GSD agent / harness vocabulary | Off-topic for any external reader; AgentLinux ships installer + CLI, not the GSD harness | Delete; if context is needed, describe the action neutrally ("during planning") | +| `Claude Code` (when used as a self-reference rather than as a catalog agent), `the agent`, `Claude`, `Anthropic` (in self-reference contexts), `as the plan requires`, `per CONTEXT.md`, `per the discuss step` | Tool-chain self-references | The artifact must stand on its own technical merits | Delete | +| `Co-Authored-By: Claude` trailer (in user-visible artifacts like blog posts or website copy — *not* in commit messages, which are internal) | Author trailer | Off-topic for marketing / blog copy | Delete from blog/email/site copy; keep in commit messages | +| `feat/al-\d+-[^ ]+`, `fix/al-\d+-[^ ]+`, `chore/al-\d+-[^ ]+` (in user-facing prose, not in PR/git history) | Internal branch naming | Branch names are workflow infrastructure | Delete; describe the change instead | +| `c8a2787`, raw 7-char commit hashes | Internal commit references | Most external readers will not click; even if they do, the context is not on the linked page | Either drop the SHA, or include a one-line summary of what the commit changed | +| `the milestone`, `this milestone`, `v0.4.0` (when used as a process label, not a release tag), `the v0.4.0 cut` | Internal milestone framing | "v0.4.0" as a release tag is fine; "the v0.4.0 milestone scope" reads as workflow shorthand | Rephrase to concrete prose ("the open-source release") or use the public release tag without process framing | +| `IMPORTANT`, `CRITICAL`, `MUST` patterns copied verbatim from CLAUDE.md / plan files when they carry internal phase lexicon | Internal phase / rule lexicon | Tone mismatch with public docs | Rewrite as neutral prose; prefer "we" voice or "AgentLinux" voice consistent with the doc's audience | +| Stop-hook references (`review-reminder.sh`, `session-tracker-reminder.sh`, ADR-010 refinement) when they appear outside CLAUDE.md / contributor docs | Maintainer harness internals | Public readers don't run those hooks | Delete; they belong in CLAUDE.md and contributor-facing harness docs | + +The table is canonical but not exhaustive. If you spot another phrase that an external reader would not be able to look up, flag it under "Other leaks" and explain what you saw. + +## Good vs Bad: Worked Examples + +The examples below calibrate your judgment. Flag phrasings like the "Bad" column; accept phrasings like the "Good" column. + +### Example 1: A line in `docs/internals/installer.md` (public developer docs) + +- **Bad:** `The installer's verify-sha256 step (INST-03, AGT-02 release gate) was added in Phase 6 — see .planning/phases/06-distribution-release-pipeline/06-SUMMARY.md.` +- **Good:** `The installer verifies the tarball's SHA-256 checksum before executing it. This is what makes the curl-pipe-bash flow safe against partial-download or man-in-the-middle tampering.` +- Reasoning: `INST-03`, `AGT-02 release gate`, `Phase 6`, and the `.planning/` path are all workspace-local. A public reader needs to understand *what the step does and why*, not the maintainer's cross-reference graph. + +### Example 2: A README line introducing the catalog + +- **Bad:** `AgentLinux ships a JSON-Schema-validated catalog (CAT-01, CAT-02, CAT-03 invariants — see ADR-011 for the curated-combo stability model).` +- **Good:** `AgentLinux ships a curated catalog of agent tools — Claude Code, GSD, Playwright. Installs are opt-in (no agent is installed by default), and each version is tested as part of a CI-pinned combo so the trio always works together.` +- Reasoning: The `CAT-NN` IDs and bare `ADR-011` reference are internal vocabulary. Restate the *behavior* — opt-in defaults, CI-tested pinned combo — in prose. + +### Example 3: A blog post draft excerpt + +- **Bad:** `Plan 12-03 added a new reviewer agent (dev-docs-auditor) that fires inside the existing review loop per ADR-010's reminder-hook refinement, satisfying the DOC-06 no-new-stop-hook invariant.` +- **Good:** `We added a new reviewer agent that keeps the developer docs in sync whenever the installer or CLI source changes. It rides on the existing review-loop pipeline — no new hooks, no extra startup cost, and one less thing for maintainers to think about.` +- Reasoning: `Plan 12-03`, `ADR-010`, `DOC-06`, and "no-new-stop-hook invariant" are all maintainer vocabulary. Tell the reader *what was built and why it's nice*; not the workflow IDs that prove the work was done. + +### Example 4: An `agentlinux.org` hero subhead + +- **Bad:** `An installable extension that satisfies the AGT-02 acceptance test on Ubuntu 22.04 + 24.04 + 26.04.` +- **Good:** `An installable extension that lets coding agents — Claude Code, GSD, Playwright — self-update on Ubuntu without sudo prompts or permission errors.` +- Reasoning: `AGT-02 acceptance test` reads as undefined; the *concrete promise* (agents self-update without sudo / EACCES) is what the visitor cares about. + +### Example 5: A line in `docs/internals/README.md` index + +- **Bad:** `These docs are written for the project owner reviewing AL-22's deliverable; the sub-files mirror the per-component split agreed in 12-CONTEXT.md.` +- **Good:** `These docs explain what each AgentLinux component does and why. They're written so that anyone — the project owner, a contributor, a reader of the project blog — can answer a "what value does AgentLinux add for X?" question in under a minute.` +- Reasoning: `AL-22` and `12-CONTEXT.md` are internal cross-refs. Replace with a description of the docs' actual purpose and audience. + +### Example 6: A CONTRIBUTING.md paragraph + +- **Bad:** `Run the review loop per CLAUDE.md §"Review Loop" — invoke the appropriate reviewers from .claude/agents/ (bash-engineer, security-engineer, qa-engineer, ai-deslop, dev-docs-auditor) before opening an MR.` +- **Good:** `Before opening a PR, run the review feedback loop on your changed files — see [Review Loop](../CLAUDE.md#review-loop) for the reviewer-by-file-type table and how to invoke it.` +- Reasoning: `CLAUDE.md §"Review Loop"` is fine — it's a relative link any contributor can follow. Listing every reviewer agent inline is implementation detail and bloats the document; let the contributor click through to the table. + +### Example 7: Accepted use of internal vocabulary + +- A file at `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md` that contains `AL-22`, `DOC-06`, `Plan 12-03`, `Phase 12`, and `dev-docs-auditor` is **fine** — the file is internal-only and never read by an external audience. Do not flag it. Only flag external drafts and public-repo entry-point docs. + +## Critical Rules + +**Rule 1: Audit only externally-facing artifacts.** +The four categories in "What Counts as Externally-Facing" are the whole scope. Do not flag internal-only files; they are allowed to use the full internal vocabulary freely. Internal cross-refs between ADRs, plans, requirements, and audits are load-bearing for the maintainer; stripping them would break the workflow. + +**Rule 2: Every flagged leak must have a suggested substitute or an explicit deletion recommendation.** +A finding that says "this is internal" without proposing what to say instead is not actionable. The main agent needs a concrete next step; vague flags produce no fixes. + +**Rule 3: When in doubt about whether a file is external, ask rather than assume.** +If the file's location does not clearly match one of the four external-artifact categories, say so in your output and let the main agent confirm. False positives on internal docs are expensive — they produce churn in the workflow documentation and erode trust in the reviewer. + +**Rule 4: This reviewer is read-only.** +It reports findings; the main agent applies fixes to the draft. Matches the review-loop convention in `CLAUDE.md` § "Review Loop"; the main agent owns triage. + +**Rule 5: Distinguish "internal-vocabulary leak" from "factual error" or "bloat".** +Other reviewers cover those (`fact-checker` and `technical-writer`). Your concern is *vocabulary that the external audience cannot resolve*. If a sentence is factually wrong but uses public vocabulary, that's a fact-checker finding, not yours. If a sentence is bloated but the vocabulary is fine, that's a technical-writer finding, not yours. + +## Output Format + +Produce a free-form summary. Open with one paragraph of overall assessment — can this artifact be published as-is, or must the main agent fix something first? — then list findings. + +Organize findings in two groups: + +1. **Leak Findings (Must-Fix)** — every hit against the leak taxonomy table. For each, cite the exact line or phrase, name the leak category, and propose a substitute or deletion. +2. **Other Leaks (Flagged)** — phrasings that are not in the taxonomy table but that an external reader could not resolve or would find confusing. For each, explain what you saw and why it reads as internal, and propose a substitute. + +Do not emit a rigid PASS/FAIL verdict — the main agent decides what to act on. Do not duplicate findings already covered by `fact-checker` (factual accuracy) or `technical-writer` (bloat / clarity); focus on the leakage dimension. If the artifact is short and clean, a two-line "no leaks found" summary is the correct output. + +## Process + +1. Identify the artifact's category (top-level repo file, public release artefact, developer/contributor doc, marketing draft). This governs audience and therefore what counts as a leak. If the artifact does not match one of the four external-artifact categories, stop and say so in your output. +2. For each row in the leak taxonomy table, grep the artifact for that pattern. Report every hit with line context. +3. Read the artifact end to end with audience eyes. Flag any additional phrasing that an external reader could not resolve, even if it is not in the table. +4. For each finding, propose either (a) a substitute that the external audience CAN resolve (a feature name in prose, a public release tag, a relative repo link, a public ADR contextualized with its substance), or (b) deletion. +5. Write findings per the Output Format. + +## Scope Management + +If the artifact is large (>500 lines for a docs page or >200 lines for a README / blog draft), prioritize in this order: + +1. **Title, hero / lede paragraph, first H2** — the most-read parts; first impression dominates. +2. **Section openers** — the first sentence of each H2/H3 sets the audience expectation for that section. +3. **Cross-links and tracker keys** — correctness of references; broken links and unresolvable IDs are the most jarring leaks. +4. **The rest of the body text.** + +State which parts were fully audited versus sampled. diff --git a/.claude/agents/fact-checker.md b/.claude/agents/fact-checker.md new file mode 100644 index 0000000..df2ca7f --- /dev/null +++ b/.claude/agents/fact-checker.md @@ -0,0 +1,184 @@ +--- +name: fact-checker +description: Finds factual claims in technical documents and verifies each one against source code, tests, ADRs, research files, or reference documents. Use after any agent produces a document containing data claims, system behavior descriptions, or architectural assertions. Use proactively on any document that will be shared with stakeholders. +model: inherit +--- + +# Fact Checker + +You are a meticulous fact-checker for technical documents in the AgentLinux +project. Your job is to find every factual claim in a document, trace it to a +primary source, and report whether it's accurate, inaccurate, or unverifiable. + +AgentLinux is an installable Ubuntu plugin that provisions an `agent` user +with a correctly-owned Node.js runtime + a registry CLI for installing agent +tools. The most common claim categories are: requirement IDs (BHV/RT/AGT/CLI/ +CAT/INST/HRN/TST/DOC/EXPL/STRAT/SITE), ADR statements (`docs/decisions/0XX-*.md`), +catalog recipes (`plugin/catalog/agents/*/install.sh`), bats tests +(`tests/bats/*.bats`), research synthesis (`.planning/research/*.md`), and +release-gate artefacts (`.github/workflows/release.yml`). + +## What Counts as a Factual Claim + +Anything that can be true or false. Specifically: + +- **Numeric claims** — "4 catalog agents", "Ubuntu 22.04 + 24.04", "TST-08 + 4-gate release pipeline", "5 success criteria", "6 invocation modes" +- **System behavior** — "AGT-02 self-updates against the live Anthropic CDN + with zero EACCES", "the curated combo runs in QEMU before every release", + "`agentlinux upgrade` reconciles divergence" +- **Code / file existence** — "`tests/bats/51-agt02-release-gate.bats` exists + and is the AGT-02 release gate", "`plugin/catalog/agents/claude-code/install.sh` + uses the native installer" +- **ADR statements** — "ADR-003 mandates no agents are installed by default", + "ADR-011 names the curated-combo stability model", "ADR-012 grants + NOPASSWD ALL" +- **Process descriptions** — "the curl-installer verifies SHA256 before + executing", "phase-close audit emits GREEN before the gate closes" +- **Negations** — "we do not ship Helicone or Langfuse by default", "no + wrapper shims at /usr/local/bin/" — these are claims too +- **Comparative claims** — "most `npm install -g` paths give the user the + latest immediately", "this is the only path that avoids the recursive-shim + trap" + +Do NOT fact-check: +- Opinions and recommendations ("we recommend approach D") +- Future plans clearly marked as roadmap ("our roadmap will commit to...") +- Definitions introduced by the document itself ("we define 'preset' as...") + +## Verification Hierarchy + +Check claims against sources in this priority order: + +1. **Source code & tests** — If a claim is about system behavior, find the + actual code. Grep for function names, file paths, bats `@test` blocks, + or recipe steps. Read the implementation, not just comments. The + `plugin/`, `tests/bats/`, `tests/qemu/`, `.github/workflows/`, and + `packaging/` trees are authoritative. +2. **ADRs and Decision artefacts** — `docs/decisions/0XX-*.md` are the + authoritative ADR set. Each one is dated and Accepted/Superseded. + Reference by ADR number. If a claim cites "ADR-NNN says X", read + ADR-NNN and confirm. +3. **Research files** — `.planning/research/SUMMARY.md`, `FEATURES.md`, + `PITFALLS.md`, `ARCHITECTURE.md`, `STACK.md` are the milestone-locked + research synthesis. Cite specific sections (`§4`, `§5`, etc.) or line + numbers. +4. **Live Jira (optional)** — When a claim references a Jira issue key + (e.g. `AL-7`), verify against the live record using the Atlassian MCP + tools (`mcp__claude_ai_Atlassian__getJiraIssue`, + `mcp__claude_ai_Atlassian__searchJiraIssuesUsingJql`). The AgentLinux + board is `copiedwonder.atlassian.net` project `AL` (board 2). Read-only + access only — never mutate tickets. +5. **Roadmap / Requirements / State** — `.planning/ROADMAP.md`, + `.planning/REQUIREMENTS.md`, `.planning/STATE.md`, `.planning/PROJECT.md` + are the project's authoritative scope and history records. +6. **Logical deduction** — Only when no primary source exists. Mark these + as "Plausible (no contradicting evidence)" not "Accurate". + +## Critical Rule: Never Trust "Always" or "Never" + +When a document claims something "always" happens, "never" occurs, or there +are "no exceptions": +- This is the highest-priority claim to verify +- Run a grep / read the test / check the recipe specifically looking for + counterexamples +- A single counterexample downgrades the claim from "Accurate" to + "Inaccurate" + +This rule exists because the project routinely makes claims like "the AGT-02 +test passes against the live CDN" — these need direct verification of the +test file and the recipe, not just trust in prior docs. + +## Critical Rule: Check the Right Scope + +When a claim says "feature X is not used" or "tool Y is not installed by +default": +- Check ALL relevant contexts, not just the obvious one. The catalog has + multiple recipes; an invariant true for `claude-code` may not hold for + `playwright`. +- Verify across the six invocation modes when relevant (interactive bash + login, non-interactive SSH, cron, systemd `User=agent`, `sudo -u agent`, + `sudo -u agent -i`). A path that resolves correctly under one mode may + fail under another. + +## Critical Rule: Verify Cross-Document Consistency + +When a document proposes something that relates to a decision made in a +prior document: +- Check whether the proposal matches, refines, or contradicts the prior + decision (CONTEXT.md decisions, prior phase SUMMARY.md, ADRs) +- Flag any departure that isn't explicitly acknowledged +- Example: a phase plan that proposes installing an agent by default would + silently contradict ADR-003 (no default agents) — that must be flagged. +- Phase exploration docs (e.g. `docs/exploration/PILLAR-2-NOTES.md`) are + authoritative for downstream phases (`docs/STRATEGY.md`); their + `## Decision summary` is lifted verbatim. A summary that drifts from the + body is a defect. + +## Output Format + +Produce a structured verification report. Group by topic/section: + +``` +# Fact Check: [document name] + +*Sources checked: [list all source files, ADRs, tests, research files consulted]* + +## [Section/Topic Name] + +| Claim | Source Checked | Verdict | +|-------|---------------|---------| +| [exact quote or paraphrase] | [file:line, ADR-NNN, test name, or research §] | **Accurate** / **Inaccurate** / **Partially verified** / **Plausible** / **Unverifiable** | + +[For any non-Accurate verdict, add an explanation paragraph below the table] +``` + +### Verdict Definitions + +- **Accurate** — Confirmed by primary source. Cite the source. +- **Inaccurate** — Contradicted by primary source. Cite the source and state what's actually true. +- **Partially verified** — Some aspects confirmed, others not checkable. State which parts are verified. +- **Plausible (no contradicting evidence)** — Logical deduction, no primary source available. Cannot confirm or deny. +- **Unverifiable** — No accessible source to check against. State what source would be needed. + +### Issues Section + +After the per-section tables, add a consolidated issues section: + +``` +## Issues Found + +### Inaccurate Claims +1. **[Short title]** — [document line ref]: Claims "[X]". Actually: [Y]. Source: [Z]. + +### Misleading or Imprecise Claims +1. **[Short title]** — [document line ref]: Says "[X]" which implies [Y], but actually [Z]. + +### Silent Departures from Prior Decisions +1. **[Short title]** — [document line ref] proposes [X], but [prior doc / ADR / CONTEXT.md] decided [Y]. No rationale given for the change. + +### Unverified Data Points +1. **[Short title]** — [document line ref]: Claims "[X]" but no source cited and I could not verify. +``` + +## Process + +1. Read the target document end to end. Build a list of every factual claim. +2. For each claim, identify the best verification source (code, ADR, test, research, ROADMAP). +3. Check claims in order. Don't skip claims because they "look right." +4. For numeric claims: count the actual artefacts (`ls plugin/catalog/agents/ | wc -l`, `grep -c '^@test' tests/bats/foo.bats`). Don't estimate from document descriptions. +5. For code claims: read the actual file. Don't rely on documentation about the code. +6. For ADR claims: open the ADR and confirm the claim word-for-word. +7. Write the report. Every claim gets a row in a table. No exceptions. +8. Highlight the issues section — this is what the reader cares about most. + +## Scope Management + +If the document has more than 50 factual claims, focus verification effort on: +1. **All numeric claims and counts** (highest error rate historically) +2. **All "always/never/no exceptions" claims** (second highest error rate) +3. **All claims about system behavior that influence design decisions** (especially the load-bearing pillar / strategy claims) +4. **All claims that will be lifted verbatim into another document** (e.g. Decision-summary sections lifted into STRATEGY.md, README.md, or the website) +5. Sample-check remaining claims (at least 1 per section) + +State clearly which claims were fully verified vs. sample-checked. diff --git a/.claude/agents/technical-writer.md b/.claude/agents/technical-writer.md new file mode 100644 index 0000000..9844e19 --- /dev/null +++ b/.claude/agents/technical-writer.md @@ -0,0 +1,121 @@ +--- +name: technical-writer +description: Reviews and rewrites technical documents for clarity, conciseness, and actionability. Use when a document is bloated, hard to follow, not self-sufficient, or needs polish before sharing with stakeholders. Also use proactively after any agent produces a document longer than 200 lines. +model: inherit +--- + +# Technical Writer + +You are a senior technical editor specializing in engineering planning +documents, strategy / exploration docs, ADRs, README and contribution copy, +and public-facing landing-page copy. Your job is to make documents clear, +concise, and actionable for the AgentLinux project. + +AgentLinux is an installable Ubuntu plugin (v0.3.x) that provisions an +`agent` user, a correctly-owned Node.js runtime, and a registry CLI for +installing agent tools (Claude Code, GSD, Playwright). Its primary readers +are: (a) experienced Linux/Node developers who run coding agents, (b) +maintainers of the project, (c) potential contributors, and (d) the +maintainer themselves reviewing exploration / strategy outputs before +commit. Match prose density and depth to the audience. + +## Your Operating Principles + +1. **Cut, don't add.** Your default action is removing words, not adding them. Every sentence you keep must earn its place. +2. **The reader is busy and senior.** They know Linux, Node, npm, systemd, and bash. Don't explain things they already understand. Don't re-explain things the document already said. +3. **One idea, one place.** If the same concept appears in multiple sections, consolidate it into the strongest location and cut the rest. +4. **Self-sufficient or it fails.** A reader who has never seen any other AgentLinux document must understand this document on its own. Expand AgentLinux-specific acronyms on first use. Don't reference other AgentLinux docs without saying what they contain. +5. **Actionable or it fails.** A maintainer reading this document must be able to turn it into work — a phase plan, a README edit, a follow-up issue. Every commitment should have an evidence pointer (test file, ADR, recipe path) or an explicit "future milestone" tag. + +## Anti-Bloat Rules + +These are the patterns that cause bloat in this project's documents. Flag and fix every instance: + +### Pattern: Triple-layer justification +Phase exploration / strategy docs tend to explain "why" three times: in the framing section, in a "What we commit to" section, and again in the Decision summary. These often say the same thing with different words. Merge into the strongest single statement. + +### Pattern: Defensive reassurance +Phrases like "AgentLinux does not ship X by default" repeated 4+ times across a doc, or "we are infrastructure, not an agent product" stated five times. Say it once, prominently, then trust the reader to remember. + +### Pattern: Implementation detail in framing documents +If the audience is the maintainer deciding whether to lock a strategic position, they don't need to know the exact CLI flag syntax (`agentlinux install --preset optimum --profile web-development`) more than once. That belongs in the implementation milestone's plan, not in the exploration doc that decides whether the framework exists at all. + +### Pattern: Exhaustive examples where one suffices +A list of all 8 considered-and-rejected agent benchmarks where one or two would carry the rejection rationale. Reduce to a representative example plus an enumerated tail ("and Aider polyglot, SWE-bench Live, …"). + +### Pattern: Over-explaining alternatives +"We considered X but rejected it because Y" is fine. A full paragraph on each rejected alternative is not, unless the audience is likely to propose that alternative. + +### Pattern: Bare option menus instead of recommendations +Never present 3 options without a recommendation. The reader hired you to have an opinion. State your recommendation, then briefly note alternatives if they're genuinely viable. + +### Pattern: Voice-rule drift +For unshipped behaviour, the grammatical subject must be "we" / "our roadmap" / an explicit milestone tag (e.g. `next-milestone`, `v0.6+`) — never "AgentLinux + present-tense verb" (provides|offers|ensures|protects|defends|benchmarks|measures|hardens|isolates|detects|prevents). The strategy doc and website carry hard grep gates for this; flag any drift. + +## Self-Sufficiency Checklist + +When reviewing a document, verify each of these. Flag violations with the specific line number: + +- [ ] Every AgentLinux-specific acronym is expanded on first use (BHV, RT, AGT, CLI, CAT, INST, HRN, TST, DOC, EXPL, STRAT, SITE, ADR, EACCES) +- [ ] Every requirement-ID reference (e.g. `AGT-02`, `EXPL-01`, `STRAT-11`) is anchored to its definition somewhere in the doc, or to a path the reader can resolve (`.planning/REQUIREMENTS.md`) +- [ ] Every external file reference (e.g. `tests/bats/51-agt02-release-gate.bats`, `docs/STABILITY-MODEL.md`, `plugin/catalog/agents/claude-code/install.sh`) includes a one-line summary of what the file contains, on first reference +- [ ] Every numeric claim (test count, file count, KB sizes, version numbers) is sourced or independently verifiable via grep / `wc` +- [ ] A reader can understand any section without reading prior sections +- [ ] Domain terms specific to this project are defined (preset vs profile, curated combo vs default version set, AGT-02 vs the `claude-code` recipe, pillar vs guiding principle) +- [ ] No dangling references to removed or renamed content (e.g. references to `v0.5.0/` research dirs that were renamed, or to removed phases) + +## Actionability Checklist + +- [ ] Every commitment has either an evidence pointer (test file, ADR, recipe path) or an explicit forward-looking tag (`next-milestone`, `v0.6+`, `our roadmap`) +- [ ] Every "Decision summary" / authoritative-section is lift-ready: matches body claims word-for-word, complete on its own +- [ ] Sequencing is clear: what's shipped today vs what lands in a future milestone +- [ ] Exit criteria exist: how does a reader know whether the doc's claims are still true (e.g. "AGT-02 self-update green" — pointer to the bats test that proves it) +- [ ] Cross-doc consistency: if the doc will be lifted into another doc (STRATEGY.md, README.md, the website), the lift is unambiguous + +## Cross-Reference Consistency + +After making any edit: +- Verify that all references to edited content elsewhere in the document still make sense +- Check summary tables match the detail sections (especially `## Decision summary` matching the body's commitments) +- Check that numbering of T-N / D-N / NG-N items is sequential and unique +- Verify that "as described in Section X" references still point to the right place +- Verify that the doc still satisfies any phase-close grep gates declared in REQUIREMENTS.md (e.g. EXPL-01 distinct-token count, voice-rule clean) — flag if an edit might break a gate + +## Output Format + +When reviewing, produce a structured report: + +``` +## Review: [document name] + +### Overall Assessment +[2-3 sentences: is this document ready to share? What's the biggest problem?] + +### Bloat Issues (cut these) +1. [Line X-Y]: [what's redundant and what to do about it] +... + +### Self-Sufficiency Issues (reader would be lost) +1. [Line X]: [what's undefined/unexplained] +... + +### Actionability Issues (can't lift / can't act on this) +1. [Line X]: [what's vague/missing] +... + +### Cross-Reference / Voice-Rule Issues (inconsistencies / drift) +1. [Line X vs Line Y]: [what contradicts] +... +``` + +When rewriting, produce the cleaned document directly. Don't append changes alongside the original — edit the document in place. The diff shows what changed. + +## Word Budgets + +These are guidelines, not hard limits. But if you're over budget, something needs cutting: +- Framing / opening section: 5-12 lines +- Per-topic problem statement: 2-3 sentences +- Per-topic recommendation / commitment: 3-5 sentences (or a labeled bullet) +- Alternatives considered: 1 sentence each, or a compact table +- Decision summary: focused on the lift-target — only what downstream docs need to consume verbatim +- Public-facing copy (README excerpts, website hero/cards): far tighter; defer to the project's existing voice (dark JetBrains-Mono, terse, terminal-flavored) diff --git a/.claude/skills/dev-docs/SKILL.md b/.claude/skills/dev-docs/SKILL.md new file mode 100644 index 0000000..112f823 --- /dev/null +++ b/.claude/skills/dev-docs/SKILL.md @@ -0,0 +1,113 @@ +--- +name: dev-docs +description: Use when the task touches plugin/bin/, plugin/lib/, plugin/provisioner/, plugin/cli/src/, plugin/catalog/, or packaging/curl-installer/ — verify the matching docs/internals/.md is still accurate. Documents the four-section contract (problem -> answer -> value vs naive -> related), the source-path -> doc-path dispatch table, the product-perspective lens (the AL-22 litmus question), and the explicit decision to NOT add a stop-hook for docs sync. Grows when new top-level surfaces land under plugin/ in future milestones. +--- + +# dev-docs — docs/internals/ contract for AgentLinux developer docs + +**Status:** Active. Established in Phase 12 (DOC-01..DOC-07). The `docs/internals/` tree shipped 9 component docs alongside this skill and the `dev-docs-auditor` reviewer. + +Authoritative spec: `docs/HARNESS.md` §4 (review loop) + this skill body. Decisions: ADR-010 (review loop via CLAUDE.md, refined 2026-05-02 to allow reminder hooks with `stop_hook_active` guard) — and the deliberate Phase 12 decision to NOT add a third reminder hook (recorded in `docs/decisions/015-developer-internals-docs.md`, lands in Phase 12 Plan 05). +Requirements this skill helps enforce: DOC-01 (index doc), DOC-02 (component docs), DOC-03 (reviewer agent registered), DOC-04 (skill exists), DOC-05 (top-level discoverability), DOC-06 (no new hook), DOC-07 (ADR captures the design). + +## When to use this skill + +Use when the task touches any file under: + +- `plugin/bin/agentlinux-install` — installer entrypoint -> `docs/internals/installer.md`. +- `plugin/lib/*.sh` — shared bash helpers -> `docs/internals/nodejs-runtime.md` (PATH/as_user) or `installer.md` (logging/idempotency). +- `plugin/provisioner/*.sh` — ordered installer steps -> dispatch by step (see table below). +- `plugin/cli/src/**` — the registry CLI source -> `docs/internals/registry-cli.md`. +- `plugin/catalog/{schema,catalog}.json` — the catalog data model -> `docs/internals/catalog.md`. +- `plugin/catalog/agents//*` — per-agent recipes -> `docs/internals/.md`. +- `packaging/curl-installer/install.sh` — the curl-pipe-bash entrypoint -> `docs/internals/installer.md`. + +Or when authoring or reviewing any file under `docs/internals/`. + +## Why this exists (DOC-02, AL-22) + +The `docs/internals/` tree is the project owner's 60-second answer to "what value does AgentLinux provide for surface X" (the AL-22 litmus question). It's the source of insight for blog posts, marketing emails, and the agentlinux.org landing page (CONTEXT §"Reuse signal"). For the docs to stay useful, they must stay in sync with the source — which means a contract for what each doc contains, a dispatch table mapping source paths to docs, and a reviewer (`dev-docs-auditor`) that checks the contract on relevant PRs. This skill owns all three. + +## Per-component file structure (the four-part contract) + +Every `docs/internals/.md` has four mandatory H2 sections: + +1. `## The problem` — what a developer hits without AgentLinux when reaching for this surface. +2. `## What AgentLinux does` — the mechanics in product terms (not line-by-line code). +3. `## Value vs the naive approach` — the trade-off, written as a numbered list with **bold lead clause** items, excerpt-friendly for blog/marketing copy. +4. `## Related` — bulleted cross-links to sibling internals docs, top-level README, and (optionally) ADRs. + +Optional fifth section: `## Worked example` — a fenced shell session with realistic prompts and truncated output. Include only when prose alone leaves the mechanics ambiguous; drop when prose suffices. + +Tone: product-perspective, project-owner audience first, future contributor second. The opening lede (3-5 lines under the H1) sets the value proposition in plain prose before any H2. + +## Source-path -> doc-path dispatch table + +The `dev-docs-auditor` reviewer reads this table to decide which component doc a source change implicates. + +| Source path glob | Component doc | +|---|---| +| `packaging/curl-installer/install.sh`, `plugin/bin/agentlinux-install` | `docs/internals/installer.md` | +| `plugin/provisioner/10-agent-user.sh` | `docs/internals/agent-user.md` | +| `plugin/provisioner/20-sudoers.sh` | `docs/internals/sudo-drop-in.md` | +| `plugin/provisioner/30-nodejs.sh`, `plugin/provisioner/40-path-wiring.sh`, `plugin/lib/as_user.sh` | `docs/internals/nodejs-runtime.md` | +| `plugin/catalog/agents/claude-code/*` | `docs/internals/claude-code.md` | +| `plugin/catalog/agents/gsd/*` | `docs/internals/gsd.md` | +| `plugin/catalog/agents/playwright-cli/*`, `plugin/catalog/agents/playwright/*` | `docs/internals/playwright.md` | +| `plugin/cli/src/**`, `plugin/provisioner/50-registry-cli.sh` | `docs/internals/registry-cli.md` | +| `plugin/catalog/schema.json`, `plugin/catalog/catalog.json` | `docs/internals/catalog.md` | +| `plugin/lib/log.sh`, `plugin/lib/idempotency.sh`, `plugin/lib/distro_detect.sh` | `docs/internals/installer.md` (shared installer infrastructure) | + +When a new top-level surface lands under `plugin/` (a new provisioner step, a new CLI command class, a new catalog backend), this table grows AND a new `docs/internals/.md` ships in the same PR. + +## When to update + +**Update the matching component doc when:** + +- The source change alters observable behavior described in `## What AgentLinux does` (e.g. install path moves, default version changes, a flag is added or removed). +- The source change invalidates a claim in `## The problem` or `## Value vs the naive approach` (e.g. a new naive alternative appears, or an old one is no longer the dominant path). +- A new top-level surface lands — a new component doc ships in the same PR and the index TOC grows. + +**Skip docs update for:** + +- Pure refactors that don't change observable behavior (rename, extract function, reformat). +- Comment-only or typo-only changes. +- Whitespace / formatting-only diffs. +- Test-only changes that don't touch `plugin/` source paths. +- `.planning/`-only changes. +- `docs/`-only changes (covered by `technical-writer` and `fact-checker`). + +The `dev-docs-auditor` reviewer enforces both columns at review time. + +## Product-perspective lens (the AL-22 litmus test) + +The litmus question for every component doc is: *"What value does AgentLinux provide in installing GSD instead of using the GSD installation from npm directly?"* — generalised to the component at hand. The doc must answer it in <60 seconds for a project owner reading on first arrival. + +Concretely: + +- Lead with the value, not the implementation. "AgentLinux gives the agent its own user with its own npm prefix, so self-update Just Works" beats "AgentLinux runs `useradd agent --shell /bin/bash` and writes `~/.npmrc` with `prefix=$HOME/.npm-global`." +- Implementation detail belongs in `## What AgentLinux does` (still product-framed); never in the lede. +- Tool names (`Commander.js`, `ajv`, `bats`) are implementation; the value frame is the verb the user gets (`agentlinux install `, "schema-validated catalog," "behavior-test contract"). Tool names may appear as supporting detail; they must not lead. +- The `## Value vs the naive approach` section is the most excerpt-heavy part of every doc — it lifts directly into blog posts and marketing copy. Keep it numbered, **bold lead clause** style. + +## Why no new stop-hook (DOC-06) + +AgentLinux already has two reminder hooks (`.claude/hooks/review-reminder.sh` and `.claude/hooks/session-tracker-reminder.sh`), both wired per the ADR-010 2026-05-02 refinement (reminder hooks with a `stop_hook_active` one-shot guard are allowed; reviewer-invoking hooks remain rejected). + +Adding a third hook for docs/internals/ sync would multiply reminder noise without adding value: the existing `review-reminder.sh` already nudges Claude to run the review loop, and the review loop already routes plugin/ changes to the `dev-docs-auditor` per the CLAUDE.md "Review Loop" routing table. The dev-docs check rides inside the existing review loop; no new hook is needed. ADR-015 (lands in Phase 12 Plan 05) records this decision in full. + +## Growth plan + +- **Phase 12 (this phase):** Skill ships alongside the 9 initial component docs and the `dev-docs-auditor` reviewer. This skill carries the dispatch table and the four-section contract. +- **Future milestones — new components added under `plugin/`:** Each new top-level surface (a new provisioner step, a new CLI command class, a new catalog backend, a new agent in the catalog) ships its own `docs/internals/.md` in the same PR and adds a row to the dispatch table here. +- **Future milestones — if drift becomes a real problem:** The skill may absorb a stronger link discipline (e.g. mandated ADR cross-references in the Related footer). Currently out of scope per CONTEXT §"Deferred Ideas." +- **Future milestones — if the docs grow:** Consider a documentation site (mdBook, Docusaurus). Currently out of scope per CONTEXT §"Deferred Ideas" — markdown in the repo is sufficient for the project owner's stated goal. + +## Related + +- `docs/internals/README.md` — the docs/internals/ index (DOC-01). +- `docs/internals/.md` — the 9 component docs (DOC-02). +- ADRs: 010 (review loop via CLAUDE.md, refined 2026-05-02), 015 (developer internals docs — no new hook decision; lands in Plan 05). +- Subagents: `dev-docs-auditor` (the reviewer this skill backs). +- Sibling skills: `agentlinux-installer`, `behavior-test-contract`, `catalog-schema`, `qemu-harness`, `review`, `workspace-cleanup`. +- Top-level pointers: `CLAUDE.md` "Review Loop" section (where the reviewer is wired) and "Pointers" section (where this skill is enumerated). Both are updated in Phase 12 Plan 04. diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 3bfe2fb..cdb44d1 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -54,6 +54,20 @@ Grouped by area. Each `XXX-NN` is a testable, verifiable outcome — auditable b - [ ] **PUB-03**: Post-flip smoke test: from a clean machine without a GitHub auth token, `git clone https://github.com/Roo4L/Agent-Linux.git` succeeds; `curl -fsSL https://agentlinux.org/install.sh | bash` (or the documented public install URL) succeeds against the v0.3.0 release tag; `agent` user is provisioned; `agentlinux list` works. Evidence: terminal session log committed to `docs/audits/v0.4.0/PUB-03-postflip-smoke.md`. - [ ] **PUB-04**: The first public release (`v0.3.0` GA, or a follow-on `v0.3.1`/`v0.4.0` documentation-only release) is tagged with a public-friendly release notes blurb (link to LICENSE, contributing guide, and a "what's in the box" summary). The release page is browsable anonymously. +## Post-v0.4.0 Addendum Requirements + +The v0.4.0 milestone closed at commit `c8a2787` on 2026-05-02 with 21 requirements (LIC/SEC/CLEAN/CIPUB/PUB). The following requirement set is a *post-v0.4.0 addendum* added under issue AL-22 ("Create documentation on what AgentLinux does") — captured in this file because REQUIREMENTS.md is still the active per-project requirements doc, but tracked separately so the v0.4.0 milestone gate count stays honest. + +### Developer Documentation (DOC) — Phase 12 + +- [x] **DOC-01**: A `docs/internals/README.md` exists at the documented location, opens with a one-paragraph "What AgentLinux is" lede in product voice, and contains a `## Components` H2 with a TOC linking to all nine component docs (installer, agent-user, sudo-drop-in, nodejs-runtime, claude-code, gsd, playwright, registry-cli, catalog). Verified by file-existence check + grep for the nine `(*.md)` link targets. +- [x] **DOC-02**: Nine component docs exist under `docs/internals/` — one per surface listed in the index. Each follows the four-section structural contract: `## The problem` → `## What AgentLinux does` → `## Value vs the naive approach` → `## Related`. Each `## Value vs the naive approach` is a numbered list with **bold lead clause** items (excerpt-friendly per the AL-22 reuse-as-blog-source signal). No source-line deep links anywhere in `docs/internals/` (per the dev-docs depth contract). Verified by grep across the nine files. +- [x] **DOC-03**: A new project-scoped reviewer agent `.claude/agents/dev-docs-auditor.md` exists with read-only tools (`tools: Read, Grep, Glob, Bash`) and a frontmatter description triggering it on changes under `plugin/bin/`, `plugin/lib/`, `plugin/provisioner/`, `plugin/cli/src/`, `plugin/catalog/`, and `packaging/curl-installer/`. The reviewer is registered in CLAUDE.md "Review Loop" by extending the Bash, TS/JS, and Catalog recipes rows of the reviewer-by-file-type table. Verified by file existence + `grep -E '^- Bash → .*dev-docs-auditor' CLAUDE.md` and equivalents for the other two extended rows. +- [x] **DOC-04**: A new project-scoped skill `.claude/skills/dev-docs/SKILL.md` exists, documenting the docs/internals/ contract (per-component four-section structure, source-path → doc-path dispatch table, when to update, product-perspective lens, and the explicit decision to not add a stop-hook). The skill is enumerated in CLAUDE.md "Pointers" alongside the other project-scoped skills. Verified by file existence + grep for the dispatch-table entries covering all 9 component docs. +- [x] **DOC-05**: Top-level discoverability — top-level `README.md` gains a "Why AgentLinux — concepts" H2 section linking `docs/internals/README.md`, AND a `## Links` row labelled `**Internals (developer docs):**` linking `docs/internals/`. Verified by grep across `README.md`. +- [x] **DOC-06**: No new stop-hook was added — `.claude/hooks/dev-docs-reminder.sh` does not exist; `.claude/settings.json` is unchanged across the Phase 12 commit range. The dev-docs sync check rides inside the existing `review-reminder.sh`-triggered review loop per the ADR-010 2026-05-02 refinement and per ADR-015 (DOC-07). Verified by `! test -f .claude/hooks/dev-docs-reminder.sh` and `git diff ..HEAD -- .claude/settings.json | wc -l` returning 0. +- [x] **DOC-07**: A new ADR `docs/decisions/015-developer-internals-docs.md` records the design decision behind Phase 12 — what `docs/internals/` is for, why a reviewer + skill instead of a hook, why a flat embed inside the existing Review Loop instead of a new top-level CLAUDE.md section. Status `Accepted`. Verified by file existence + `grep -q '^## Decision' docs/decisions/015-developer-internals-docs.md`. + ## Future Requirements (not in this milestone) - Public package distribution beyond GitHub Releases (PPA, Homebrew tap, AUR) — deferred until adoption signals justify the maintenance cost. @@ -91,6 +105,15 @@ Grouped by area. Each `XXX-NN` is a testable, verifiable outcome — auditable b **Coverage check:** 21 requirements mapped to 5 phases. Zero orphans. +### Post-v0.4.0 Addendum Traceability + +| Phase | Requirements | Count | +|-------|--------------|-------| +| 12 Developer Documentation (AL-22) | DOC-01, DOC-02, DOC-03, DOC-04, DOC-05, DOC-06, DOC-07 | 7 | +| **Total addendum** | | **7** | + +**Coverage check:** 7 addendum requirements mapped to 1 phase. Zero orphans. (v0.4.0 milestone total remains 21 requirements across 5 phases — see the table above.) + ## Verification Convention Each requirement must close with at least one verifiable artifact before its phase closes (TST-07 phase-close pattern from v0.3.0): diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 18b5071..f6dac16 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -28,7 +28,7 @@ Key locked decisions honored by this roadmap: - [x] **Phase 8: Secret Scanning & History Audit** — gitleaks (1 finding, triaged false positive — OpenNebula API hostname matched `generic-api-key` regex) + trufflehog (0 verified, 0 unverified) + targeted manual audit (8 patterns × 255 commits = 0 matches). SEC-04 closes as no-op (ADR-014). gitleaks gate wired in pre-commit + CI; smoke-test confirms gate fires on contrived secrets. ✓ 2026-04-26 (commit `c94920a`; 5/5 SEC-XX evidenced; phase-close gate: GREEN; `.planning/phases/08-secret-scanning/08-AUDIT.md`). - [x] **Phase 9: Repository Hygiene & Artifact Cleanup** — 2 branches (no stale, no merged-but-unpurged); zero blobs >500 KB anywhere in history; .gitignore hardened (env/npmrc/credentials/SSH keys/editor cruft/coverage/caches with deliberate allow-lists); `.planning/` retention is deliberate per CLAUDE.md convention. ✓ 2026-04-26 (commit `158e465`; 4/4 CLEAN-XX evidenced; phase-close gate: GREEN; `.planning/phases/09-repo-hygiene/09-AUDIT.md`). - [x] **Phase 10: Public CI/CD Verification & Branch Protection** — workflow `permissions:` blocks at least-privilege (test.yml gained explicit top-level); `pull_request_target` = 0; fork-PR exfiltration surface = empty. Branch protection on `master` designed and **staged for maintainer apply** via single `gh api -X PUT` command (CIPUB-03; Option A/B documented). CIPUB-04 de facto GREEN from PR #2 + recent nightly runs (<24h). ✓ 2026-04-26 (commit `446c89b`; 4/4 CIPUB-XX evidenced or staged; phase-close gate: GREEN-pending-2-maintainer-tasks; `.planning/phases/10-public-cicd/10-AUDIT.md`). -- [ ] **Phase 11: Public Visibility Flip & Smoke Test** — PUB-01 pre-flight checklist fully prepared (`docs/audits/v0.4.0/PUB-01-preflight-checklist.md`) referencing every Phase 7-10 artifact; 13/17 items already evidenced; 2 close on staged Phase 10 maintainer commands. **PUB-02 (the flip itself) is the maintainer's hand on the trigger** — autonomous mode stops here per `/gsd-autonomous` invocation note. PUB-03 (anonymous clone + curl-pipe-bash smoke) and PUB-04 (release notes) execute post-flip. Status: ⏳ STOPPED FOR MAINTAINER SIGN-OFF (`.planning/phases/11-public-flip/11-AUDIT.md`). +- [x] **Phase 11: Public Visibility Flip & Smoke Test** — Repository visibility flipped to PUBLIC at 2026-04-26T15:30Z; squash-merged as `c8a2787` on master; branch protection re-applied as Option A (enforce_admins, linear, no force-push, gitleaks status check). Public release published as **`v0.3.1 — Open-Source Flip`** (2026-05-02; the originally-tagged `v0.4.0` was renamed to `v0.3.1` for version-constant lockstep — see release notes). Post-flip smoke (anonymous clone + raw curl-installer fetch + SHA + syntax) green. End-to-end `curl … | sudo bash` install deferred to v0.3.x final-release event. ✓ shipped 2026-05-02 (commit `c8a2787`, tag `v0.3.1`; 4/4 PUB-XX evidenced; phase-close gate: GREEN; `.planning/phases/11-public-flip/11-AUDIT.md`). ## Phase Details @@ -117,8 +117,8 @@ Phases execute in numeric order: 7 → 8 → 9 → 10 → 11 | 8. Secret Scanning & History Audit | 3 | ✓ Complete (commit `c94920a`) | SEC-01..05 evidenced; gitleaks gate live | | 9. Repository Hygiene & Artifact Cleanup | 2 | ✓ Complete (commit `158e465`) | CLEAN-01..04 evidenced | | 10. Public CI/CD Verification & Branch Protection | 2 | ✓ Complete-pending-maintainer (commit `446c89b`) | CIPUB-01..02 evidenced; CIPUB-03..04 staged for maintainer apply | -| 11. Public Visibility Flip & Smoke Test | 2 | ⏳ STOPPED for maintainer sign-off | PUB-01 checklist ready; PUB-02 is the flip; PUB-03/04 post-flip | -| **Total** | **~11 plans** | 4/5 phases done; 5th awaits maintainer | — | +| 11. Public Visibility Flip & Smoke Test | 2 | ✓ Shipped 2026-05-02 (commit `c8a2787`, tag `v0.3.1`) | PUB-01..04 evidenced; v0.4.0 originally tagged then renamed to `v0.3.1` for version-constant lockstep | +| **Total** | **~11 plans** | 5/5 phases shipped — milestone complete | Per-phase work landed via direct commits + `*-AUDIT.md`; no per-plan PLAN/SUMMARY files (autonomous-deterministic path; documented in each AUDIT §"Deviations from PLAN") | ## Coverage Summary @@ -151,3 +151,17 @@ These are open questions to resolve in `/gsd-discuss-phase 7` (and subsequent ph - **History rewrite vs. accept-and-rotate** for any leaked secrets: depends on what is found. Default-stance: rotate without rewrite unless the secret grants ongoing access — resolved in Phase 8 ADR-014. - **Default branch rename** (`master` → `main`): explicitly out of scope for v0.4.0; raise as a separate milestone if desired. (Cosmetic; would invalidate existing URL references.) - **Public install URL** for PUB-03 smoke: is it `agentlinux.org/install.sh` or `https://github.com/Roo4L/Agent-Linux/releases/download/v0.3.0/install.sh`? Resolve before Phase 11. + +### Phase 12: Developer documentation for installer, runtime, and CLI (AL-22) + +**Goal:** A reader landing on the AgentLinux repo can find a 60-second answer to "what value does AgentLinux provide for surface X" for every component (installer, agent user, sudo drop-in, Node.js runtime, the agent catalog, the registry CLI, and the curated agent set: Claude Code, GSD, Playwright). The docs stay in sync with the source via a project-scoped reviewer (`dev-docs-auditor`) embedded in the existing review loop — no new stop-hook is added (ADR-015 lands in Plan 12-05). +**Requirements**: DOC-01, DOC-02, DOC-03, DOC-04, DOC-05, DOC-06, DOC-07 +**Depends on:** Phase 11 +**Plans:** 5/5 plans complete + +Plans: +- [x] 12-01-PLAN.md — docs/internals/ index + 4 install/runtime layer component docs (DOC-01, DOC-02) +- [x] 12-02-PLAN.md — 5 agent + CLI/catalog component docs (DOC-02) +- [x] 12-03-PLAN.md — dev-docs-auditor reviewer agent + dev-docs skill (DOC-03, DOC-04, DOC-06) +- [x] 12-04-PLAN.md — CLAUDE.md Review Loop + Pointers wiring + top-level README.md discoverability (DOC-03, DOC-05) +- [x] 12-05-PLAN.md — REQUIREMENTS.md DOC-XX entries + ADR-015 + Phase 12 AUDIT (DOC-01..DOC-07, phase-close) (completed 2026-05-10) diff --git a/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/.gitkeep b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-01-PLAN.md b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-01-PLAN.md new file mode 100644 index 0000000..45f4a84 --- /dev/null +++ b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-01-PLAN.md @@ -0,0 +1,297 @@ +--- +phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 +plan: 01 +type: execute +wave: 1 +depends_on: [] +files_modified: + - docs/internals/README.md + - docs/internals/installer.md + - docs/internals/agent-user.md + - docs/internals/sudo-drop-in.md + - docs/internals/nodejs-runtime.md +autonomous: true +requirements: [DOC-01, DOC-02] + +must_haves: + truths: + - "A reader landing on docs/internals/README.md sees a one-paragraph What-AgentLinux-is lede plus a TOC linking to all 9 component docs" + - "Each install/runtime-layer component doc (installer, agent-user, sudo-drop-in, nodejs-runtime) answers what value AgentLinux provides for that surface vs the naive approach" + - "Each component doc follows the problem -> AgentLinux's answer -> value vs naive structural contract" + - "Each component doc ends with a Related cross-links footer (no source-line deep links)" + artifacts: + - path: "docs/internals/README.md" + provides: "Internals index with What-AgentLinux-is lede + TOC linking to all 9 component docs" + contains: "## " + min_lines: 25 + - path: "docs/internals/installer.md" + provides: "Component doc: curl-pipe-bash installer (problem -> answer -> value)" + contains: "## Value vs the naive approach" + min_lines: 40 + - path: "docs/internals/agent-user.md" + provides: "Component doc: dedicated agent user (problem -> answer -> value)" + contains: "## Value vs the naive approach" + min_lines: 40 + - path: "docs/internals/sudo-drop-in.md" + provides: "Component doc: NOPASSWD sudo drop-in (problem -> answer -> value)" + contains: "## Value vs the naive approach" + min_lines: 40 + - path: "docs/internals/nodejs-runtime.md" + provides: "Component doc: per-user npm prefix Node.js runtime (problem -> answer -> value)" + contains: "## Value vs the naive approach" + min_lines: 40 + key_links: + - from: "docs/internals/README.md" + to: "docs/internals/installer.md" + via: "TOC bullet markdown link" + pattern: "\\(installer\\.md\\)" + - from: "docs/internals/README.md" + to: "docs/internals/agent-user.md" + via: "TOC bullet markdown link" + pattern: "\\(agent-user\\.md\\)" + - from: "docs/internals/README.md" + to: "docs/internals/sudo-drop-in.md" + via: "TOC bullet markdown link" + pattern: "\\(sudo-drop-in\\.md\\)" + - from: "docs/internals/README.md" + to: "docs/internals/nodejs-runtime.md" + via: "TOC bullet markdown link" + pattern: "\\(nodejs-runtime\\.md\\)" +--- + + +Create the `docs/internals/` index plus the four install/runtime-layer component docs (installer, agent-user, sudo-drop-in, nodejs-runtime). Each doc answers the AL-22 litmus question — "what value does AgentLinux provide here vs the naive approach" — in product-perspective prose excerptable into blog/marketing copy. + +Purpose: Give the project owner a 60-second answer to "what does AgentLinux do for surface X" for the four foundational layers (everything below the agent catalog). +Output: 5 new markdown files under `docs/internals/`. + + + +@$HOME/.claude/get-shit-done/workflows/execute-plan.md +@$HOME/.claude/get-shit-done/templates/summary.md + + + +@.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md +@.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-PATTERNS.md +@docs/STABILITY-MODEL.md +@docs/README.md +@README.md + + + + + +H2 spine pattern (per PATTERNS.md, mapped from STABILITY-MODEL.md): + +```markdown +# + +<3-5 line plain-prose lede in product voice — what is this thing for> + +## The problem + +<2-4 paragraphs framing the situation a developer hits without AgentLinux> + +## What AgentLinux does + +<2-4 paragraphs describing the mechanics in product terms — not line-by-line code> + +## Worked example + + + +## Value vs the naive approach + +Without , the naive path is . Two problems: + +1. **.** . +2. **.** . + + + +## Related + +- []() — +- []() — +- []() — +``` + +Hard constraints from CONTEXT.md §"Depth": +- NO source-line deep links (no `path/to/file.sh:42` style references). +- ADR mentions in prose are OK; ADR links are optional, not required. +- Mermaid diagrams allowed but used sparingly — only when a diagram genuinely illustrates a concept that prose does not. + +Source-to-doc mapping for this plan's four component docs (the executor uses these to ground prose; do NOT cite specific files/lines in the doc body): + +| Component doc | Underlying source surfaces (for the executor's understanding only) | +|---|---| +| installer.md | `packaging/curl-installer/install.sh`, `plugin/bin/agentlinux-install`, ADR-006 (curl-pipe-bash + .deb) | +| agent-user.md | `plugin/provisioner/10-agent-user.sh`, ADR-004 (per-user npm prefix), the AGT-02 self-update invariant | +| sudo-drop-in.md | `plugin/provisioner/20-sudoers.sh`, ADR-012 (agent user full sudo) | +| nodejs-runtime.md | `plugin/provisioner/30-nodejs.sh`, `plugin/provisioner/40-path-wiring.sh`, ADR-005 (system Node.js over version managers), ADR-004 | + + + + + + + Task 1: Write docs/internals/README.md (index) + installer.md + agent-user.md + + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md (the authoritative spec for tone, depth, and structure) + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-PATTERNS.md (per-file analog assignments and the H2 spine mapping) + - docs/STABILITY-MODEL.md (the strongest single-topic concept-doc analog — copy its lede shape, H2 spine, "Why pin at all (the trade-off)" pattern, and Related footer pattern) + - docs/README.md (the analog for `docs/internals/README.md` — borrow the linkable-bullet TOC shape) + - README.md (top-level — for product voice and value-proposition tone) + - packaging/curl-installer/install.sh (so the executor's installer.md prose accurately describes what the installer does — SHA256 verify, partial-download protection, exec the plugin) + - plugin/bin/agentlinux-install (the installer entrypoint the curl-installer execs — what `--purge` does, what gets staged where) + - plugin/provisioner/10-agent-user.sh (so the executor's agent-user.md describes what the agent user actually is — UID, home, shell, groups) + - docs/decisions/004-per-user-npm-prefix.md (the keystone "why agent user owns npm" decision — for agent-user.md prose) + - docs/decisions/006-curl-pipe-bash-plus-deb.md (for installer.md prose — the trust story) + + docs/internals/README.md, docs/internals/installer.md, docs/internals/agent-user.md + +Create three files under `docs/internals/` (the directory does not exist yet — `mkdir -p docs/internals` first). + +**1. `docs/internals/README.md`** (target ~30-50 lines): +- H1: `# AgentLinux Internals` +- One-paragraph "What AgentLinux is" lede in product voice (~3-5 lines). Anchor on the project's value proposition: "AgentLinux provisions a dedicated agent user with a correctly-owned Node.js runtime so agent tools self-update without EACCES or sudo fights." Add one sentence on what this directory is: "Each doc here explains what one AgentLinux surface does and why — the value vs the naive approach you'd otherwise reach for." +- H2: `## Components` +- A flat bullet TOC linking to all 9 component docs in the order: installer, agent-user, sudo-drop-in, nodejs-runtime, claude-code, gsd, playwright, registry-cli, catalog. Use the shape `- [](<slug>.md) — <one-sentence what this surface is>`. Example bullet: `- [Installer](installer.md) — the curl-pipe-bash entrypoint that downloads, verifies, and executes the AgentLinux release tarball.` +- H2: `## Audience` +- One paragraph stating the audience (the project owner first, future contributors second) and the reuse signal (these docs are excerpt-friendly source material for blog posts, marketing emails, and the agentlinux.org landing page). Per CONTEXT.md §"Reuse signal". +- Trailing horizontal rule and a one-line cross-link back to `[../README.md](../README.md)` and `[HARNESS.md](../HARNESS.md)`. + +**2. `docs/internals/installer.md`** (target ~50-80 lines): +- H1: `# Installer` +- Lede (3-5 lines): "AgentLinux ships as a curl-pipe-bash installer that downloads a versioned release tarball, verifies it against a sibling SHA256 sidecar, and executes the plugin. One command on a clean Ubuntu host turns it into an agent-ready environment." +- `## The problem`: Frame what a developer hits without AgentLinux when bootstrapping an agent environment on Ubuntu. Cover: bespoke shell scripts that drift between machines, no SHA verification on `curl | bash`, partial-download execution risk, manual `apt install` + `npm install -g` that ends up root-owned and breaks self-update. +- `## What AgentLinux does`: Describe (in product terms) the install path: HTTPS fetch -> SHA256 verify against sibling `.sha256` asset -> extract to `/opt/agentlinux/` -> exec `plugin/bin/agentlinux-install` -> ordered provisioner steps (agent user, sudo drop-in, Node.js, PATH wiring, registry CLI). Mention the partial-download safety pattern (the installer wraps its body in `main() { ... }; main "$@"` so a truncated download yields a syntax error before any commands run). +- `## Worked example`: A fenced shell session showing `curl -fsSL https://agentlinux.org/install.sh | sudo bash` followed by truncated realistic output (downloaded tarball, SHA verified, provisioning steps, `agentlinux list` showing zero agents installed). Three to seven lines of session output. +- `## Value vs the naive approach`: Use the STABILITY-MODEL.md "Why pin at all (the trade-off)" pattern verbatim in shape. Lede: "Without a versioned, SHA-verified installer, the naive path is `curl https://example/script | bash`. Two problems:". Numbered list with **bold lead clause** style: (1) **Tampered or partial downloads execute by default.** Mid-stream connection resets execute partial scripts; a malicious mirror can substitute a payload silently. (2) **No reproducible install.** Re-running the same command later may pull a newer remote script with different behavior. Closing bold sentence: "AgentLinux's installer makes the trust story explicit: HTTPS + SHA256 sidecar + maintainer 2FA + branch protection." +- `## Related`: 3-5 bullets — link to `[Agent user](agent-user.md)`, `[Node.js runtime](nodejs-runtime.md)`, `[../README.md](../README.md)`. Optionally name ADR-006 in prose ("the curl-pipe-bash + .deb decision is recorded as ADR-006") without a link, per CONTEXT.md §"Depth". + +**3. `docs/internals/agent-user.md`** (target ~50-80 lines): +- H1: `# Agent user` +- Lede (3-5 lines): "AgentLinux provisions a dedicated `agent` user with a per-user npm prefix. Every agent tool (Claude Code, GSD, Playwright) installs into and updates from the agent's own home directory — no EACCES, no `sudo` fights, no recursive shims at `/usr/local/bin/`." +- `## The problem`: Describe the EACCES + recursive-shim bug class. Cover: `sudo npm install -g` writes a root-owned tree under `/usr/lib/node_modules`, the tool then writes a wrapper at `/usr/local/bin/<tool>`, the tool's own self-updater can't rewrite root-owned files as the invoking user, the user reaches for `sudo` again, the cycle repeats. Cite Claude Code's `claude update` as the canonical case (AGT-02 is the regression test that catches this). +- `## What AgentLinux does`: Describe the agent user's shape (UID, home at `/home/agent/`, shell `/bin/bash`, per-user npm prefix at `~/.npm-global/`, PATH wired across every invocation mode — interactive shell, non-interactive SSH, cron, systemd user units, `sudo -u agent`, `sudo -u agent -i`). Mention that every install runs via `as_user agent <cmd>` so the agent owns everything it needs to update. +- `## Worked example`: A fenced shell session showing a fresh install followed by `claude update` running cleanly with no `sudo` and no `EACCES`. Output excerpt should make the "agent owns its own tools" claim concrete. +- `## Value vs the naive approach`: STABILITY-MODEL trade-off pattern. Lede: "Without a dedicated agent user, the naive path is `sudo npm install -g <tool>`. Two problems:". Numbered list: (1) **EACCES on every subsequent non-root operation under `~/.npm/`.** Once root has written there, the user can no longer install or update without `sudo` again. (2) **Self-updaters break.** Tools like Claude Code that ship their own updater write into a root-owned prefix, leave a wrapper at `/usr/local/bin/`, and cannot rewrite themselves on the next update. Closing sentence: "AgentLinux gives agents their own user with their own prefix, so self-update Just Works." +- `## Related`: 3-5 bullets — link to `[Installer](installer.md)`, `[Node.js runtime](nodejs-runtime.md)`, `[Sudo drop-in](sudo-drop-in.md)`, `[Claude Code](claude-code.md)`. ADR-004 may be named in prose without link. + +Do NOT include source-line deep links anywhere. Do NOT include Mermaid diagrams in this task (none of the three docs need one). + </action> + <verify> + <automated>test -f docs/internals/README.md && test -f docs/internals/installer.md && test -f docs/internals/agent-user.md && grep -q '^# AgentLinux Internals' docs/internals/README.md && grep -qF '## Components' docs/internals/README.md && grep -qF '(installer.md)' docs/internals/README.md && grep -qF '(agent-user.md)' docs/internals/README.md && grep -qF '(sudo-drop-in.md)' docs/internals/README.md && grep -qF '(nodejs-runtime.md)' docs/internals/README.md && grep -qF '(claude-code.md)' docs/internals/README.md && grep -qF '(gsd.md)' docs/internals/README.md && grep -qF '(playwright.md)' docs/internals/README.md && grep -qF '(registry-cli.md)' docs/internals/README.md && grep -qF '(catalog.md)' docs/internals/README.md && grep -q '^## The problem' docs/internals/installer.md && grep -q '^## What AgentLinux does' docs/internals/installer.md && grep -q '^## Value vs the naive approach' docs/internals/installer.md && grep -q '^## Related' docs/internals/installer.md && grep -q '^## The problem' docs/internals/agent-user.md && grep -q '^## What AgentLinux does' docs/internals/agent-user.md && grep -q '^## Value vs the naive approach' docs/internals/agent-user.md && grep -q '^## Related' docs/internals/agent-user.md && ! grep -nE '\.sh:[0-9]+|\.ts:[0-9]+|\.json:[0-9]+' docs/internals/installer.md docs/internals/agent-user.md docs/internals/README.md</automated> + </verify> + <acceptance_criteria> + - `docs/internals/README.md` exists, opens with H1 `# AgentLinux Internals`, contains an `## Components` H2, and links to all 9 component docs (installer, agent-user, sudo-drop-in, nodejs-runtime, claude-code, gsd, playwright, registry-cli, catalog). + - `docs/internals/README.md` includes an `## Audience` H2 stating the reuse signal (excerpt-friendly for blog/marketing). + - `docs/internals/installer.md` exists, has H1 `# Installer`, and contains H2s `## The problem`, `## What AgentLinux does`, `## Value vs the naive approach`, `## Related` (Worked example optional but expected). + - `docs/internals/installer.md` `## Value vs the naive approach` section contains a numbered list with at least 2 items written in `**bold lead clause.** explanation` style. + - `docs/internals/agent-user.md` exists, has H1 `# Agent user`, and contains H2s `## The problem`, `## What AgentLinux does`, `## Value vs the naive approach`, `## Related`. + - `docs/internals/agent-user.md` mentions "EACCES" and "self-update" or "claude update" in `## The problem` (the bug class AgentLinux exists to eliminate per CLAUDE.md "Critical Rules"). + - No source-line deep links (`*.sh:NN`, `*.ts:NN`, `*.json:NN`) anywhere in the three new files — verified by `grep -nE '\.sh:[0-9]+|\.ts:[0-9]+|\.json:[0-9]+'` returning nothing. + - No Mermaid fence (` ```mermaid `) appears in any of the three new files. + </acceptance_criteria> + <done>Three files committed; all H2 spine sections present; TOC complete; no deep links; no Mermaid.</done> +</task> + +<task type="auto"> + <name>Task 2: Write sudo-drop-in.md + nodejs-runtime.md</name> + <read_first> + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-PATTERNS.md + - docs/STABILITY-MODEL.md (the H2 spine analog; copy the "Why pin at all (the trade-off)" shape) + - docs/internals/installer.md (the just-written installer doc — match its tone and section depth) + - docs/internals/agent-user.md (just-written — match tone) + - plugin/provisioner/20-sudoers.sh (so sudo-drop-in.md describes what gets dropped where, who it covers, and what's NOT in it) + - plugin/provisioner/30-nodejs.sh (Node.js install — apt? NodeSource? specific version policy?) + - plugin/provisioner/40-path-wiring.sh (so nodejs-runtime.md describes how PATH gets wired across every invocation mode — this is half the value of the runtime layer) + - docs/decisions/012-agent-user-full-sudo.md (ADR-012 — the rationale for NOPASSWD ALL=ALL) + - docs/decisions/005-system-nodejs-over-version-managers.md (ADR-005 — why apt Node.js, not nvm/asdf/fnm) + - docs/decisions/004-per-user-npm-prefix.md (the per-user npm prefix decision that nodejs-runtime.md hinges on) + </read_first> + <files>docs/internals/sudo-drop-in.md, docs/internals/nodejs-runtime.md</files> + <action> +Create two more files under `docs/internals/`. Both follow the same H2 spine as installer.md and agent-user.md from Task 1. + +**1. `docs/internals/sudo-drop-in.md`** (target ~50-80 lines): +- H1: `# Sudo drop-in` +- Lede (3-5 lines): "AgentLinux installs a `/etc/sudoers.d/agentlinux` drop-in granting the `agent` user passwordless sudo for everything. This is the `agent ALL=(ALL) NOPASSWD: ALL` line that makes coding agents able to `apt install`, `systemctl restart`, and reach into the host without a stuck password prompt." +- `## The problem`: Frame the situation an autonomous coding agent hits without this. Cover: agents need to install OS packages mid-task (`apt install <build-dep>`), restart services (`systemctl restart nginx`), edit files outside their home, and tail privileged logs. A long-running agent that hits a `[sudo] password for agent:` prompt is a stalled agent. The earlier zero-sudo posture (v0.3.0 Phases 1-4) was elegant but blocked too much real agent work, which is why Phase 5.1 added this drop-in. Cite ADR-012 in prose. +- `## What AgentLinux does`: Describe the drop-in: filename, mode (`0440`), single line content, what it grants, what it deliberately does NOT alter (the agent user still owns its own npm prefix — sudo is a tool the agent uses, not the path agents install through; `sudo npm install -g` remains forbidden because it breaks self-update, regardless of whether the password prompt appears). +- `## Worked example`: Brief fenced session — `sudo -u agent sudo apt-get install -y jq` running with no prompt, followed by a counter-example: `sudo -u agent sudo npm install -g @anthropic-ai/claude-code` shown as something the agent COULD do password-free but shouldn't (it would break `claude update`). The point: AgentLinux trusts the agent user with sudo, but the codebase's invariants (`as_user`, per-user prefix) still hold the line on what's a good idea. +- `## Value vs the naive approach`: Trade-off pattern. Lede: "Without a sudoers drop-in, the naive paths are 'no sudo' (zero-sudo lock) or 'shared root password' (the agent prompts for it). Two problems:". Numbered list: (1) **Zero-sudo blocks legitimate work.** Long-running agents that need `apt install <dep>` or `systemctl restart <svc>` mid-task simply stall. (2) **Password prompts stall autonomous loops.** A `[sudo] password for agent:` prompt in a non-interactive session never resolves; the agent retries indefinitely or fails. Closing sentence: "AgentLinux drops the sudoers entry so agents work; the codebase's `as_user` discipline still keeps the per-user prefix invariant intact (ADR-012 records this trade-off)." +- `## Related`: 3-5 bullets — link to `[Agent user](agent-user.md)`, `[Installer](installer.md)`, `[../decisions/012-agent-user-full-sudo.md](../decisions/012-agent-user-full-sudo.md)` (the ONE allowed link to an ADR — sudo-drop-in.md is the closest doc to ADR-012's content, so an explicit cross-link is justified per CONTEXT §"Depth" "may reference an ADR by name in prose"; the Related footer is the canonical place to surface it). + +**2. `docs/internals/nodejs-runtime.md`** (target ~60-100 lines): +- H1: `# Node.js runtime` +- Lede (3-5 lines): "AgentLinux installs the system Node.js LTS via apt (NodeSource), then wires the agent user with a per-user npm prefix at `~/.npm-global/` and a PATH that resolves the agent's binaries across every invocation mode — interactive shell, non-interactive SSH, cron, systemd user units, `sudo -u agent`, `sudo -u agent -i`." +- `## The problem`: Two intertwined problems. (a) Version-manager Node.js (nvm, asdf, fnm) ships per-shell-init activation that doesn't survive non-interactive contexts (cron, systemd, ssh -i without a login shell). The agent's `node` is missing in half the contexts it actually runs in. (b) System Node.js installed via apt is owned by root; `sudo npm install -g` writes into `/usr/lib/node_modules` owned by root, and the agent can no longer update its own tools. Both paths fail the AGT-02 self-update invariant. +- `## What AgentLinux does`: Describe both halves of the runtime layer: (i) Node.js install — apt + NodeSource for system Node, currently pinned to LTS major (mention the version policy without committing to a specific number — "AgentLinux tracks the Node.js LTS line"); (ii) per-user npm prefix — `~/.npm-global/` configured via `~/.npmrc`, with PATH wired in `/etc/profile.d/agentlinux.sh` (interactive + login shells), in the agent user's `~/.bashrc` (non-interactive bash), and via systemd `Environment=` directives where applicable. The "wired across every invocation mode" guarantee is the value (RT-XX behavior contract enforces it). +- `## Worked example`: Fenced session showing `which node` (system), `npm config get prefix` (agent prefix `/home/agent/.npm-global`), and `claude --version` working from cron / systemd / ssh -i / sudo -u agent. +- `## Value vs the naive approach`: Trade-off pattern. Lede: "Without this runtime layer, the two naive paths are 'install nvm/asdf' or 'use system Node.js with sudo npm'. Two problems:". Numbered list: (1) **Version managers don't survive non-interactive contexts.** nvm/asdf rely on shell-init hooks (`. ~/.nvm/nvm.sh`); cron, systemd, ssh -i, and `sudo -u agent` skip those hooks, leaving `node` missing exactly where automation runs. (2) **`sudo npm install -g` corrupts ownership.** Once root has written the global tree, the agent can no longer self-update. (Cross-link to `[Agent user](agent-user.md)` for the full bug class.) Closing sentence: "AgentLinux uses system Node.js for predictability and a per-user npm prefix for ownership — and wires PATH so both choices hold across every shell context the agent ever runs in." +- `## Related`: 3-5 bullets — link to `[Agent user](agent-user.md)`, `[Installer](installer.md)`, `[Claude Code](claude-code.md)`, `[GSD](gsd.md)`. ADRs may be named in prose without link. + +No source-line deep links. No Mermaid (these two are well-served by prose; the install-time sequence diagram, if it appears anywhere, belongs to installer.md and was already deemed unnecessary in Task 1). + </action> + <verify> + <automated>test -f docs/internals/sudo-drop-in.md && test -f docs/internals/nodejs-runtime.md && grep -q '^# Sudo drop-in' docs/internals/sudo-drop-in.md && grep -q '^# Node.js runtime' docs/internals/nodejs-runtime.md && grep -q '^## The problem' docs/internals/sudo-drop-in.md && grep -q '^## What AgentLinux does' docs/internals/sudo-drop-in.md && grep -q '^## Value vs the naive approach' docs/internals/sudo-drop-in.md && grep -q '^## Related' docs/internals/sudo-drop-in.md && grep -q '^## The problem' docs/internals/nodejs-runtime.md && grep -q '^## What AgentLinux does' docs/internals/nodejs-runtime.md && grep -q '^## Value vs the naive approach' docs/internals/nodejs-runtime.md && grep -q '^## Related' docs/internals/nodejs-runtime.md && grep -qF 'NOPASSWD' docs/internals/sudo-drop-in.md && grep -qF '~/.npm-global' docs/internals/nodejs-runtime.md && ! grep -nE '\.sh:[0-9]+|\.ts:[0-9]+|\.json:[0-9]+' docs/internals/sudo-drop-in.md docs/internals/nodejs-runtime.md && ! grep -q '^```mermaid' docs/internals/sudo-drop-in.md docs/internals/nodejs-runtime.md</automated> + </verify> + <acceptance_criteria> + - `docs/internals/sudo-drop-in.md` exists, has H1 `# Sudo drop-in`, contains all four required H2s (`## The problem`, `## What AgentLinux does`, `## Value vs the naive approach`, `## Related`). + - `docs/internals/sudo-drop-in.md` mentions `NOPASSWD` (the actual sudoers grant content) and names ADR-012 in prose or as a link. + - `docs/internals/sudo-drop-in.md` `## Value vs the naive approach` numbered list has at least 2 `**bold lead clause.**` items. + - `docs/internals/nodejs-runtime.md` exists, has H1 `# Node.js runtime`, contains all four required H2s. + - `docs/internals/nodejs-runtime.md` mentions `~/.npm-global` (the actual per-user prefix path) and references both halves of the runtime layer (system Node.js via apt + per-user npm prefix + PATH wiring across invocation modes). + - `docs/internals/nodejs-runtime.md` `## Value vs the naive approach` numbered list has at least 2 `**bold lead clause.**` items contrasting against version-manager and `sudo npm install -g` naive paths. + - No source-line deep links in either file (verified by `grep -nE '\.sh:[0-9]+|\.ts:[0-9]+|\.json:[0-9]+'` returning nothing). + - No Mermaid fence in either file. + </acceptance_criteria> + <done>Two files committed; all H2 spine sections present; trade-off lists are excerpt-friendly bold-lead-clause format; no deep links; no Mermaid.</done> +</task> + +</tasks> + +<verification> +After all tasks complete: + +```bash +# All five files exist +test -f docs/internals/README.md +test -f docs/internals/installer.md +test -f docs/internals/agent-user.md +test -f docs/internals/sudo-drop-in.md +test -f docs/internals/nodejs-runtime.md + +# Each component doc has the four mandated H2 sections +for f in docs/internals/{installer,agent-user,sudo-drop-in,nodejs-runtime}.md; do + for h in '## The problem' '## What AgentLinux does' '## Value vs the naive approach' '## Related'; do + grep -qF "$h" "$f" || { echo "MISSING $h in $f"; exit 1; } + done +done + +# Index README links every component doc (including the ones from plans 02 + 03) +for slug in installer agent-user sudo-drop-in nodejs-runtime claude-code gsd playwright registry-cli catalog; do + grep -qF "(${slug}.md)" docs/internals/README.md || { echo "MISSING TOC link to ${slug}.md"; exit 1; } +done + +# No source-line deep links anywhere in this plan's outputs +! grep -nE '\.sh:[0-9]+|\.ts:[0-9]+|\.json:[0-9]+' docs/internals/{README,installer,agent-user,sudo-drop-in,nodejs-runtime}.md +``` +</verification> + +<success_criteria> +- All 5 markdown files committed under `docs/internals/`. +- Each component doc follows the problem -> answer -> value vs naive contract from CONTEXT.md. +- The index README's TOC links to all 9 eventual component docs (4 from this plan + 5 from Plan 02). +- No source-line deep links (CONTEXT.md §"Depth"). +- Mermaid used sparingly (zero diagrams in this plan; if Plan 02 needs one, it adds it there). +- The "Value vs the naive approach" section is excerpt-friendly per CONTEXT.md §"Reuse signal" (numbered list, bold lead clauses). +</success_criteria> + +<output> +After completion, create `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-01-SUMMARY.md` per the GSD summary template. +</output> diff --git a/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-01-SUMMARY.md b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-01-SUMMARY.md new file mode 100644 index 0000000..02ddfe5 --- /dev/null +++ b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-01-SUMMARY.md @@ -0,0 +1,155 @@ +--- +phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 +plan: 01 +subsystem: docs +tags: [internals, installer, agent-user, sudoers, nodejs, npm-prefix, path-wiring, AL-22, DOC-01, DOC-02] + +# Dependency graph +requires: + - phase: 02-installer-foundation-agent-user + provides: agent user provisioner + PATH wiring artifacts (the agent-user.md + nodejs-runtime.md grounding) + - phase: 03-nodejs-runtime + provides: 30-nodejs.sh + per-user npm prefix at ~/.npm-global (the nodejs-runtime.md grounding) + - phase: 05-1-agent-user-sudo-drop-in + provides: 20-sudoers.sh + ADR-012 (the sudo-drop-in.md grounding) + - phase: 06-distribution-release-pipeline + provides: packaging/curl-installer/install.sh + INST-03 SHA256-verified release pipeline (the installer.md grounding) +provides: + - docs/internals/ tree with index README + 4 install/runtime-layer component docs (installer, agent-user, sudo-drop-in, nodejs-runtime) + - The four-part component-doc structural contract: lede -> ## The problem -> ## What AgentLinux does -> ## Worked example (optional) -> ## Value vs the naive approach -> ## Related + - The trade-off / "value vs naive" doc pattern with bold-lead-clause numbered list (excerpt-friendly per CONTEXT §"Reuse signal") + - TOC scaffold in docs/internals/README.md linking to all 9 eventual component docs (4 from this plan + 5 from Plan 02) +affects: + - 12-02-PLAN (writes the remaining 5 component docs: claude-code, gsd, playwright, registry-cli, catalog — must follow the same structural contract + tone established here) + - 12-03-PLAN (dev-docs reviewer agent + dev-docs skill — both reference the docs contract this plan instantiates) + - 12-04-PLAN (CLAUDE.md wiring of dev-docs-auditor into the Review Loop table) + - 12-05-PLAN (top-level README.md "Why AgentLinux — concepts" link into docs/internals/) + +# Tech tracking +tech-stack: + added: [] # docs only — no new libraries / runtime tech + patterns: + - Component-doc H2 spine "problem -> answer -> value vs naive -> Related" (mapped from STABILITY-MODEL.md "Why pin at all (the trade-off)") + - Bold-lead-clause numbered-list trade-off pattern (excerpt-friendly for blog/marketing reuse) + - Cross-link Related footer with no source-line deep links (CONTEXT §"Depth") + +key-files: + created: + - docs/internals/README.md + - docs/internals/installer.md + - docs/internals/agent-user.md + - docs/internals/sudo-drop-in.md + - docs/internals/nodejs-runtime.md + modified: [] + +key-decisions: + - One concrete ADR link allowed in sudo-drop-in.md Related footer (link to ADR-012) — closest doc-to-ADR mapping in the set; CONTEXT §"Depth" allows ADR mentions in prose, and linking from the doc most-tightly-bound to that ADR is justified surface area without breaking the no-deep-links rule + - Mermaid omitted from all four component docs — prose was clearer for installer (sequence) and runtime (topology); no diagram added gratuitously per CONTEXT §"Diagrams" "used sparingly" + - Worked-example shell sessions used `$ ` prompt prefix throughout for STABILITY-MODEL.md-tone consistency + - PATH ordering rationale called out explicitly in nodejs-runtime.md ("/home/agent/.npm-global/bin lands first … so a stray wrapper shim at /usr/local/bin/<tool> cannot win") — the security-engineer-rubric Pitfall 4 mitigation made visible at the doc level + - Counter-example in sudo-drop-in.md Worked example deliberately shows `sudo npm install -g` as something that WOULD succeed but remains a forbidden anti-pattern — the doc enforces the discipline that ADR-012 + ADR-004 together draw + +patterns-established: + - "H2 spine for component docs: # <Title> -> 3-5 line lede -> ## The problem -> ## What AgentLinux does -> ## Worked example (optional) -> ## Value vs the naive approach -> ## Related" + - "Trade-off list pattern: 'Without X, the naive path is Y. Two problems:' lede + numbered list with **bold lead clause.** explanation + bold one-line resolution sentence" + - "Related footer: 3-5 bullets, [readable name](path) -- one-sentence what's there; no source-line deep links anywhere" + +requirements-completed: [DOC-01, DOC-02] + +# Metrics +duration: 5min +completed: 2026-05-10 +--- + +# Phase 12 Plan 01: Internals docs index + installer + agent-user + sudo-drop-in + nodejs-runtime Summary + +**5 product-perspective component docs that answer "what value does AgentLinux provide for surface X" for the four foundational install/runtime layers, scaffolding a docs/internals/ tree the next four plans extend.** + +## Performance + +- **Duration:** ~5 min +- **Started:** 2026-05-10T05:45:32Z +- **Completed:** 2026-05-10T05:50:39Z +- **Tasks:** 2 +- **Files created:** 5 +- **Files modified:** 0 + +## Accomplishments + +- `docs/internals/` directory created (sibling to `docs/decisions/`, `docs/research/`, `docs/audits/`). +- Index README with What-AgentLinux-is lede + TOC linking all 9 eventual component docs + Audience section stating the reuse signal (excerpt-friendly for blog/marketing copy). +- Four foundational-layer component docs (installer, agent-user, sudo-drop-in, nodejs-runtime), each following the problem -> answer -> value-vs-naive contract from CONTEXT §"Documentation Scope & Format". +- Worked-example shell sessions in installer.md, agent-user.md, sudo-drop-in.md, and nodejs-runtime.md showing concrete observable behavior (curl-pipe-bash output, `claude update` without sudo/EACCES, `sudo -l` output, `which claude` resolving identically across invocation modes). +- Trade-off "Value vs the naive approach" lists in all four component docs written in the bold-lead-clause numbered format that lifts cleanly into blog posts and marketing emails. +- Hard contract upheld: no source-line deep links (`*.sh:NN`, `*.ts:NN`, `*.json:NN`) anywhere; no Mermaid fences; ADR mentions in prose only (sudo-drop-in.md Related footer is the single exception, linking ADR-012 directly per its tight binding to the doc topic). + +## Task Commits + +Each task was committed atomically (no fix commits, no deviations): + +1. **Task 1: Write README.md (index) + installer.md + agent-user.md** — `9c00061` (docs) +2. **Task 2: Write sudo-drop-in.md + nodejs-runtime.md** — `4598b4a` (docs) + +**Plan metadata commit (this SUMMARY + STATE/ROADMAP/REQUIREMENTS updates):** committed after this file lands. + +## Files Created/Modified + +- `docs/internals/README.md` (49 lines) — Index with What-AgentLinux-is lede, `## Components` TOC linking all 9 component docs (4 from this plan + 5 placeholders for Plan 02), `## Audience` section stating the project-owner-first / contributors-second / reuse-signal-for-blog-marketing audience model, trailing cross-links to `../README.md` and `../HARNESS.md`. +- `docs/internals/installer.md` (114 lines) — Component doc on the curl-pipe-bash installer. Lede frames it as "one command turns a clean Ubuntu host into agent-ready environment." Problem covers bespoke shell scripts + unverified curl-pipe-bash + sudo-npm-install poisoning. Answer describes the five-step sequence (HTTPS fetch + SHA256 verify + extract + exec + ordered provisioners) plus the `main(){}; main "$@"` partial-download-safety wrapper. Worked example shows real curl-pipe-bash transcript ending in `agentlinux list` with no agents installed (ADR-003). Trade-off list contrasts tampered/partial downloads vs non-reproducible installs. Related footer links agent-user, sudo-drop-in, nodejs-runtime, top-level README. +- `docs/internals/agent-user.md` (118 lines) — Component doc on the dedicated `agent` user with per-user npm prefix. Lede anchors on "the agent owns its tools so it can update them." Problem section walks through the EACCES + recursive-shim sequence: `sudo npm install -g` -> root-owned tree -> wrapper at `/usr/local/bin/` -> `claude update` fails EACCES -> user reaches for sudo -> permission tax compounds; calls AGT-02 the canonical regression. Answer describes the agent user's shape (UID, home, shell, locale, CLAUDE.md anti-pattern doc) + the per-user prefix at `~/.npm-global/` + PATH wired across six modes via four artifacts + the `as_user agent` discipline. Worked example shows fresh install -> `claude update` succeeding without sudo or EACCES. Trade-off list contrasts EACCES-on-every-non-root-op vs broken self-updaters. Related links installer, nodejs-runtime, sudo-drop-in, claude-code (the canonical case). +- `docs/internals/sudo-drop-in.md` (123 lines) — Component doc on `/etc/sudoers.d/agentlinux`. Lede explains the single-line `agent ALL=(ALL) NOPASSWD: ALL` grant. Problem section frames how autonomous coding agents need root-class operations (apt install, systemctl restart, etc.) and how zero-sudo / shared-root-password / narrow-allowlist all fail in practice; cites ADR-012 explicitly in prose. Answer describes the drop-in mechanics (mode 0440, root:root, visudo -cf gate before atomic install, post-install rehash, byte-stable on re-run) and the deliberate non-effect on the per-user prefix invariant. Worked example shows password-free `sudo apt-get install` PLUS a counter-example showing `sudo npm install -g` would succeed-but-is-still-forbidden — the discipline ADR-004 enforces beyond what ADR-012 grants. Trade-off list contrasts zero-sudo (blocks legitimate work) vs password prompts (stall autonomous loops). Related footer is the **only** doc with a direct ADR link in this plan: `../decisions/012-agent-user-full-sudo.md` — sudo-drop-in.md is the closest doc to ADR-012's content, justifying the explicit cross-link per CONTEXT §"Depth" "may reference an ADR by name in prose." +- `docs/internals/nodejs-runtime.md` (141 lines) — Component doc on the system Node.js + per-user npm prefix + PATH wiring layer. Lede establishes "two pieces, one runtime contract." Problem section covers both naive paths: version-manager-non-interactive (nvm/asdf/fnm shell-init hooks skipped under cron/systemd/ssh -i/sudo) AND sudo-npm-corrupts-ownership (root-owned `/usr/lib/node_modules` -> EACCES -> broken `claude update`). Answer describes both halves: (i) NodeSource apt + LTS line + ADR-005 trade-off; (ii) per-user prefix at `~/.npm-global/{bin,lib}` + `~/.npmrc` + NPM_CONFIG_PREFIX belt-and-braces + PATH wiring across six modes via four artifacts (profile.d, .bashrc-at-top, agentlinux.env, cron.d) + path-ordering rationale (npm-global FIRST, defeats `/usr/local/bin/` shim). Worked example shows `which node` (system) + `npm config get prefix` (agent) + `which claude` resolving the same way under cron, systemd, ssh, and `sudo -u agent bash -c`. Trade-off list contrasts version-manager non-interactive failure vs sudo-npm ownership corruption (with explicit cross-link to agent-user.md for the full bug class). Related links agent-user, installer, claude-code, gsd. + +## Decisions Made + +- **One concrete ADR link allowed (sudo-drop-in.md → ADR-012).** CONTEXT §"Depth" disallows source-line deep links and says ADR links are optional, not required. Sudo-drop-in.md's content maps almost 1:1 to ADR-012's decision record, so a single Related-footer link to ADR-012 was the most useful surface. installer.md, agent-user.md, and nodejs-runtime.md mention their ADRs (006, 004, 005, 004 respectively) only in prose, no link — preserving the bulk-no-link discipline. +- **No Mermaid diagrams.** All four component docs were prose-clear without diagrams. The plan flagged Mermaid as optional per CONTEXT §"Diagrams" "used sparingly" — I judged each component and concluded prose served. (If Plan 02's catalog or registry-cli docs need a sequence diagram or topology, the plan adds it there.) +- **Worked-example use across all four component docs.** PATTERNS.md lists worked-example as optional; I included one in each because the AL-22 litmus test ("60-second answer for what value AgentLinux adds") is dramatically reinforced by a 5-7-line shell session showing the actual observable behavior. Without the session, "claude update without sudo or EACCES" is abstract; with it, the value lands. +- **Counter-example in sudo-drop-in.md is deliberate.** The plan calls for a counter-example showing `sudo npm install -g` running password-free under ADR-012 but remaining forbidden because ADR-004 + the codebase's `as_user` rule still draw the line. This is the single most subtle teaching moment in the four docs — the docs are excerpt-friendly source material, and "ADR-012 grants sudo, ADR-004 disciplines what to use it for" is exactly the kind of pull-quote the AL-22 ticket is asking for. +- **Counter to PATTERNS.md mapping for STABILITY-MODEL "Worked example: I ran claude update":** STABILITY-MODEL.md uses that worked example to introduce three-state divergence (synced / override-ahead / override-behind). I deliberately did NOT replicate that example in agent-user.md or nodejs-runtime.md — those docs are about the foundational ownership invariant (AGT-02 succeeds without sudo/EACCES), not about the divergence reconciliation surface (which lives in the registry-cli + catalog docs in Plan 02). Splitting the topic this way keeps each doc's argument tight. + +## Deviations from Plan + +None - plan executed exactly as written. + +Both verify-block automated checks pass first try; both `<acceptance_criteria>` lists pass; both `<done>` criteria met. Zero auto-fix commits, zero Rule N deviations to document. + +## Issues Encountered + +None. The plan's `<read_first>` lists pre-loaded the right context (CONTEXT, PATTERNS, STABILITY-MODEL, source files for each component, ADRs); the H2 spine and bold-lead-clause patterns were copy-pastable from STABILITY-MODEL.md modulo content swap; the no-deep-links + no-mermaid contract was easy to honor because both component docs were short and prose-natural. + +The pre-existing `git status` snapshot showed unrelated modifications to `.planning/STATE.md`, `.planning/config.json`, three Plan 12-0[2..5] PLAN.md files, and `docs/audits/v0.4.0/PUB-04-release-notes.md` — these were left strictly untouched. Per the protocol, only `docs/internals/*.md` files were `git add`-ed and committed; no `git add .` / `-A` was used. + +## User Setup Required + +None — no external service configuration required. + +## Next Phase Readiness + +- `docs/internals/` tree scaffolded; the index README's TOC already enumerates all 9 component docs with `[name](slug.md)` links. +- Plan 02 picks up the remaining 5 component docs (claude-code, gsd, playwright, registry-cli, catalog) — files are referenced as broken links from this plan's `## Related` footers and from the README TOC, which the verifier should expect as known-broken until Plan 02 lands. +- Plan 03 (dev-docs reviewer + dev-docs skill) and Plan 04 (CLAUDE.md wiring) can begin in parallel with Plan 02 — both are about *enforcing* the contract this plan instantiated, not about authoring new docs against it. +- Plan 05 (top-level README pointer into docs/internals/) is trivially unblocked; it just needs the `docs/internals/README.md` target to exist, which this plan delivers. +- The structural contract (problem -> answer -> value -> Related; bold-lead-clause trade-off list; no source-line deep links; ADR mentions in prose without links by default) is now reified in 4 working examples that Plan 02 should pattern-match against — the dev-docs-auditor reviewer (Plan 03) will enforce the same. + +## Self-Check: PASSED + +- `docs/internals/README.md` — FOUND (49 lines) +- `docs/internals/installer.md` — FOUND (114 lines) +- `docs/internals/agent-user.md` — FOUND (118 lines) +- `docs/internals/sudo-drop-in.md` — FOUND (123 lines) +- `docs/internals/nodejs-runtime.md` — FOUND (141 lines) +- Task 1 commit `9c00061` — FOUND in `git log` +- Task 2 commit `4598b4a` — FOUND in `git log` +- Each component doc has the four mandated H2 sections — VERIFIED via grep +- README has H1 `# AgentLinux Internals` + `## Components` H2 + all 9 TOC links — VERIFIED via grep +- No source-line deep links (`*.sh:NN`, `*.ts:NN`, `*.json:NN`) anywhere in 5 new files — VERIFIED via `grep -nE` +- No Mermaid fences in 5 new files — VERIFIED via `grep '^```mermaid'` +- Both `## Value vs the naive approach` numbered lists across 4 component docs use `**bold lead clause.**` form (count: 2 each) — VERIFIED via `grep -cE '^[0-9]+\. \*\*'` +- `agent-user.md` mentions EACCES + self-update / claude update in `## The problem` — VERIFIED via grep +- `sudo-drop-in.md` mentions NOPASSWD + names ADR-012 — VERIFIED via grep +- `nodejs-runtime.md` mentions `~/.npm-global` + both halves (system Node.js via apt + per-user prefix + PATH wiring across modes) — VERIFIED via grep + +--- +*Phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22* +*Completed: 2026-05-10* diff --git a/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-02-PLAN.md b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-02-PLAN.md new file mode 100644 index 0000000..e915766 --- /dev/null +++ b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-02-PLAN.md @@ -0,0 +1,277 @@ +--- +phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 +plan: 02 +type: execute +wave: 1 +depends_on: [] +files_modified: + - docs/internals/claude-code.md + - docs/internals/gsd.md + - docs/internals/playwright.md + - docs/internals/registry-cli.md + - docs/internals/catalog.md +autonomous: true +requirements: [DOC-02] + +must_haves: + truths: + - "Each agent doc (claude-code, gsd, playwright) explains why the agent is in the AgentLinux catalog and what value AgentLinux adds over installing the agent directly from npm/upstream" + - "registry-cli.md explains what the agentlinux CLI does and why a CLI exists at all (vs raw shell + npm)" + - "catalog.md explains the catalog data model (opt-in, schema-validated, no defaults) and the value of a curated catalog vs ad-hoc npm install" + - "Each doc follows the problem -> AgentLinux's answer -> value vs naive structural contract" + artifacts: + - path: "docs/internals/claude-code.md" + provides: "Component doc: Claude Code in the AgentLinux catalog" + contains: "## Value vs the naive approach" + min_lines: 40 + - path: "docs/internals/gsd.md" + provides: "Component doc: GSD (Get Shit Done) in the AgentLinux catalog" + contains: "## Value vs the naive approach" + min_lines: 40 + - path: "docs/internals/playwright.md" + provides: "Component doc: Playwright (browser-access tool) in the AgentLinux catalog" + contains: "## Value vs the naive approach" + min_lines: 40 + - path: "docs/internals/registry-cli.md" + provides: "Component doc: the agentlinux registry CLI" + contains: "## Value vs the naive approach" + min_lines: 40 + - path: "docs/internals/catalog.md" + provides: "Component doc: the agent catalog (schema, opt-in, curated combos)" + contains: "## Value vs the naive approach" + min_lines: 40 + key_links: + - from: "docs/internals/claude-code.md" + to: "docs/internals/agent-user.md" + via: "Related footer markdown link" + pattern: "\\(agent-user\\.md\\)" + - from: "docs/internals/registry-cli.md" + to: "docs/internals/catalog.md" + via: "Related footer markdown link" + pattern: "\\(catalog\\.md\\)" + - from: "docs/internals/catalog.md" + to: "docs/internals/registry-cli.md" + via: "Related footer markdown link" + pattern: "\\(registry-cli\\.md\\)" +--- + +<objective> +Create the five remaining component docs under `docs/internals/`: three agent docs (claude-code, gsd, playwright) and the two CLI/catalog-layer docs (registry-cli, catalog). Each answers "what value does AgentLinux provide for this surface vs the naive approach" — the AL-22 litmus question — in product-perspective prose excerptable into blog/marketing copy. + +Purpose: Complete the 9-component dev-docs set so docs/internals/ is self-contained. +Output: 5 new markdown files under `docs/internals/`. +</objective> + +<execution_context> +@$HOME/.claude/get-shit-done/workflows/execute-plan.md +@$HOME/.claude/get-shit-done/templates/summary.md +</execution_context> + +<context> +@.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md +@.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-PATTERNS.md +@docs/STABILITY-MODEL.md +@README.md + +<interfaces> +<!-- Same H2 spine as Plan 01 (the four mandated sections from CONTEXT.md §"Documentation Scope & Format"): --> + +```markdown +# <Component Title> + +<3-5 line plain-prose lede in product voice> + +## The problem + +## What AgentLinux does + +## Worked example <!-- optional --> + +## Value vs the naive approach + +Without <component>, the naive path is <X>. Two problems: + +1. **<Lead clause as bold headline>.** <Explanation>. +2. **<Lead clause as bold headline>.** <Explanation>. + +<Bold one-line resolution sentence stating the AgentLinux contract.> + +## Related + +- [<readable name>](<path>) — <one-sentence what's there> +``` + +Hard constraints (CONTEXT.md §"Depth"): +- NO source-line deep links. +- ADR mentions in prose are OK; ADR links are optional. +- Mermaid sparingly — only when a diagram genuinely illustrates a concept. + +Source surfaces grounding each doc (for the executor's understanding only — do NOT cite specific files/lines in the doc body): + +| Component doc | Underlying source surfaces | +|---|---| +| claude-code.md | `plugin/catalog/agents/claude-code/install.sh`, AGT-02 self-update invariant, the canonical "claude update" worked example from STABILITY-MODEL.md | +| gsd.md | `plugin/catalog/agents/gsd/install.sh`, the GSD upstream regression story (STABILITY-MODEL §"Why pin at all" mentions it) | +| playwright.md | `plugin/catalog/agents/playwright-cli/install.sh`, ADR-012 (sudo drop-in is what lets `playwright install --with-deps` work) | +| registry-cli.md | `plugin/cli/src/index.ts`, `plugin/cli/src/commands/`, ADR-008 (Commander.js for CLI) — note: the doc is product-perspective; "Commander.js" is an implementation detail and should NOT lead the prose | +| catalog.md | `plugin/catalog/schema.json`, `plugin/catalog/catalog.json`, the CAT-01/CAT-02/CAT-03 invariants ("available not installed", "schema-validated", "add an agent without touching CLI source") | + +Cross-link suggestions (for the Related footer of each doc): +- claude-code.md -> agent-user.md (the bug class it depends on solving), catalog.md, registry-cli.md +- gsd.md -> catalog.md, registry-cli.md, ../STABILITY-MODEL.md +- playwright.md -> sudo-drop-in.md (browser deps need apt), catalog.md +- registry-cli.md -> catalog.md (the catalog the CLI consumes), agent-user.md (every install runs as the agent user) +- catalog.md -> registry-cli.md, ../STABILITY-MODEL.md (curated combos), claude-code.md / gsd.md / playwright.md (the three current entries) +</interfaces> +</context> + +<tasks> + +<task type="auto"> + <name>Task 1: Write three agent docs — claude-code.md, gsd.md, playwright.md</name> + <read_first> + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-PATTERNS.md + - docs/STABILITY-MODEL.md (the H2 spine analog and the canonical "I ran `claude update`" worked-example pattern) + - README.md (for the AGT-02 / "claude update" framing in product voice) + - plugin/catalog/agents/claude-code/install.sh (so claude-code.md describes what AgentLinux's claude-code install actually does — pinned version, install path, why) + - plugin/catalog/agents/gsd/install.sh (so gsd.md describes the gsd install path — npm package name, global install via as_user) + - plugin/catalog/agents/playwright-cli/install.sh (so playwright.md describes the playwright install — npm package + `playwright install --with-deps chromium` apt-layer that needs the sudo drop-in) + - docs/decisions/011-stability-first-version-pinning.md (for the curated-combo framing all three agent docs hinge on) + </read_first> + <files>docs/internals/claude-code.md, docs/internals/gsd.md, docs/internals/playwright.md</files> + <action> +Create three agent docs under `docs/internals/`. Each follows the same H2 spine established in Plan 01 (problem -> answer -> value vs naive). + +**1. `docs/internals/claude-code.md`** (target ~50-80 lines): +- H1: `# Claude Code` +- Lede (3-5 lines): "Claude Code is an Anthropic-published agent CLI. AgentLinux ships it as an opt-in catalog entry — `agentlinux install claude-code` puts the pinned version into the agent user's home directory, where Claude Code's own self-updater (`claude update`) can rewrite it without `sudo` or EACCES. That self-update invariant is the canonical AgentLinux acceptance test (AGT-02)." +- `## The problem`: Frame what a developer hits installing Claude Code on a fresh Ubuntu host with the naive path. Cover: `sudo npm install -g @anthropic-ai/claude-code` writes a root-owned tree; Claude Code's installer then drops a wrapper at `/usr/local/bin/claude`; the next `claude update` tries to rewrite the root-owned files and fails with `EACCES` or silently writes to a wrong path; the user reaches for `sudo claude update` and the cycle deepens. AGT-02 is the regression test that catches this exact failure mode. +- `## What AgentLinux does`: Describe AgentLinux's claude-code install: `agentlinux install claude-code` runs the catalog recipe via `as_user agent npm install -g @anthropic-ai/claude-code`, installing into `/home/agent/.npm-global/`. The agent user owns everything, so `claude update` (Claude Code's own updater) Just Works. Mention the `pinned_version` from the curated combo (no specific number — just say "the version AgentLinux's CI tested in the latest release"). +- `## Worked example`: Use the STABILITY-MODEL.md "I ran `claude update`" session VERBATIM IN SHAPE (not in literal text) — `$ claude update` followed by truncated output showing the version bump, then `$ agentlinux upgrade` showing the divergence between curated and installed. The point is: AgentLinux surfaces the divergence; it doesn't fight the self-updater. (You may copy the spirit of the example from STABILITY-MODEL.md lines 50-77 — but reword for the claude-code doc's framing rather than the stability-model framing.) +- `## Value vs the naive approach`: Trade-off pattern. Lede: "Without AgentLinux, the naive path is `sudo npm install -g @anthropic-ai/claude-code`. Two problems:". Numbered list: (1) **`claude update` breaks on root-owned trees.** Claude Code's self-updater is the recommended way to stay current; if the install tree is root-owned, the updater hits EACCES and the user has to keep using `sudo`, which deepens the breakage. (2) **Curated combos disappear.** The naive path always pulls upstream `latest` — every Anthropic release ships immediately to the user, including the rare broken ones. AgentLinux pins to a CI-tested combo and lets the user opt past the pin via `agentlinux pin claude-code=latest`. Closing sentence: "AgentLinux makes Claude Code installable, updatable, and reconcilable — without root, without surprises." +- `## Related`: `[Agent user](agent-user.md)`, `[Catalog](catalog.md)`, `[Registry CLI](registry-cli.md)`, `[../STABILITY-MODEL.md](../STABILITY-MODEL.md)`. AGT-02 may be named in prose without link. + +**2. `docs/internals/gsd.md`** (target ~40-70 lines): +- H1: `# GSD (Get Shit Done)` +- Lede (3-5 lines): "GSD is a Claude Code workflow framework — slash commands and skills for planning, executing, and verifying multi-step engineering work. AgentLinux ships it as an opt-in catalog entry pinned to a tested version, so a regression in upstream GSD doesn't immediately reach users." +- `## The problem`: Two intertwined problems. (a) Like Claude Code, GSD installed via `sudo npm install -g get-shit-done-cc` lands root-owned and breaks future updates from the agent user. (b) GSD ships fast (multiple releases per week) and has hit upstream regressions in production — a thin-wrapper distribution that always pulls latest exposes users to every wobble in the upstream release cadence. (You may name the GSD upstream regression that STABILITY-MODEL.md mentions — keep it general; don't pin a date.) +- `## What AgentLinux does`: Describe AgentLinux's gsd install: `agentlinux install gsd` runs the recipe via `as_user agent npm install -g get-shit-done-cc`, into the agent's per-user prefix. The catalog `pinned_version` is the version AgentLinux's release-gate matrix exercised end-to-end before the tag shipped. `agentlinux upgrade` shows the divergence between installed, curated, and (optionally) upstream latest. +- `## Worked example`: Brief fenced session — `agentlinux install gsd`, `gsd --version`, then `agentlinux upgrade gsd` showing the agent is on the curated pin (or not, with the three divergence states from STABILITY-MODEL.md). +- `## Value vs the naive approach`: Trade-off pattern. Lede: "Without AgentLinux, the naive path is `sudo npm install -g get-shit-done-cc`. Two problems:". Numbered list: (1) **The agent's own tools end up root-owned.** Same EACCES + recursive-shim story as Claude Code; cross-link to [Agent user](agent-user.md). (2) **Upstream regressions hit immediately.** GSD ships fast; the day a broken release publishes, every thin-wrapper user is on it. AgentLinux's curated pin gives the project the freedom to test upstream movement before it reaches users. Closing sentence: "Pinning is the explicit contract — we test what we ship; you opt past the pin when you're ready." +- `## Related`: `[Agent user](agent-user.md)`, `[Catalog](catalog.md)`, `[Registry CLI](registry-cli.md)`, `[../STABILITY-MODEL.md](../STABILITY-MODEL.md)`. + +**3. `docs/internals/playwright.md`** (target ~50-80 lines): +- H1: `# Playwright` +- Lede (3-5 lines): "Playwright is the browser-automation library agents use to read web pages, fill forms, and inspect network traffic. AgentLinux ships it as an opt-in catalog entry that handles both the npm install AND the chromium-with-OS-deps install — including the apt-level packages that `playwright install --with-deps chromium` requires under the hood. The agent user's NOPASSWD sudo drop-in is what lets that apt step run mid-install without a password prompt." +- `## The problem`: Frame the situation. Cover: `npm install -g playwright` only gets the JavaScript package — to actually drive a browser, the user must also `playwright install --with-deps chromium`, which apt-installs ~200MB of Chromium dependencies (libnss3, libatk-bridge2.0-0, etc). This requires sudo; without a sudoers drop-in, the install stalls on a password prompt in any non-interactive session. Plus the same root-ownership problem hits if the user takes the naive `sudo npm install -g` path. +- `## What AgentLinux does`: Describe the install path: `agentlinux install playwright` runs the recipe via `as_user agent npm install -g playwright`, then runs `playwright install --with-deps chromium` which apt-installs the OS-level browser deps. The sudo drop-in (`/etc/sudoers.d/agentlinux`, see [Sudo drop-in](sudo-drop-in.md)) is what makes the apt step pass silently. The pinned `playwright` version is the one AgentLinux's release-gate matrix tested chromium against. +- `## Worked example`: Brief fenced session showing the install completing without a password prompt, followed by a one-liner that proves the browser launches (e.g. `playwright open https://example.com`). +- `## Value vs the naive approach`: Trade-off pattern. Lede: "Without AgentLinux, the naive path is `sudo npm install -g playwright && sudo playwright install --with-deps chromium`. Two problems:". Numbered list: (1) **The npm install ends up root-owned.** Same self-update breakage as the other agents. (2) **The browser-deps step needs sudo, which stalls non-interactive sessions.** A long-running agent that hits a `[sudo] password:` prompt mid-install is a stalled agent. AgentLinux's NOPASSWD sudo drop-in (ADR-012) is what makes the deps step run cleanly under automation. Closing sentence: "AgentLinux ships the full Playwright install — npm package, browser binaries, and OS deps — as one opt-in catalog entry that works the first time, every time." +- `## Related`: `[Agent user](agent-user.md)`, `[Sudo drop-in](sudo-drop-in.md)`, `[Catalog](catalog.md)`, `[Registry CLI](registry-cli.md)`. + +No source-line deep links. No Mermaid diagrams in any of these three files. + </action> + <verify> + <automated>test -f docs/internals/claude-code.md && test -f docs/internals/gsd.md && test -f docs/internals/playwright.md && grep -q '^# Claude Code' docs/internals/claude-code.md && grep -q '^# GSD' docs/internals/gsd.md && grep -q '^# Playwright' docs/internals/playwright.md && for f in docs/internals/claude-code.md docs/internals/gsd.md docs/internals/playwright.md; do for h in '## The problem' '## What AgentLinux does' '## Value vs the naive approach' '## Related'; do grep -qF "$h" "$f" || { echo "MISSING $h in $f"; exit 1; }; done; done && grep -qE 'AGT-02|claude update' docs/internals/claude-code.md && grep -qE 'agent-user\.md|EACCES' docs/internals/claude-code.md && grep -qF '(sudo-drop-in.md)' docs/internals/playwright.md && ! grep -nE '\.sh:[0-9]+|\.ts:[0-9]+|\.json:[0-9]+' docs/internals/claude-code.md docs/internals/gsd.md docs/internals/playwright.md && ! grep -q '^```mermaid' docs/internals/claude-code.md docs/internals/gsd.md docs/internals/playwright.md</automated> + </verify> + <acceptance_criteria> + - All three files exist with the correct H1s (`# Claude Code`, `# GSD (Get Shit Done)`, `# Playwright`). + - Each file contains all four required H2s: `## The problem`, `## What AgentLinux does`, `## Value vs the naive approach`, `## Related`. + - `claude-code.md` mentions "AGT-02" or "claude update" (the canonical AgentLinux acceptance test) and links to `agent-user.md` from Related. + - `gsd.md` mentions the curated/pinned-version trade-off (links to `STABILITY-MODEL.md` or names the curated-combo concept in prose). + - `playwright.md` mentions the OS-level browser deps + apt + sudo trade-off and links to `sudo-drop-in.md` from Related. + - Each `## Value vs the naive approach` section is a numbered list with at least 2 items in `**bold lead clause.** explanation` style. + - No source-line deep links in any of the three files. + - No Mermaid fence in any of the three files. + </acceptance_criteria> + <done>Three agent docs committed; all H2 spine sections present; cross-links into agent-user.md / sudo-drop-in.md / catalog.md / registry-cli.md as appropriate; no deep links; no Mermaid.</done> +</task> + +<task type="auto"> + <name>Task 2: Write registry-cli.md + catalog.md</name> + <read_first> + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-PATTERNS.md + - docs/STABILITY-MODEL.md (the curated-combo framing catalog.md hinges on) + - docs/internals/claude-code.md (just-written — the agent doc that registry-cli.md and catalog.md cross-link to) + - plugin/cli/src/index.ts (the CLI entrypoint — what commands ship: list/install/remove/info/doctor/upgrade/pin) + - plugin/cli/src/commands/ (ls this directory to see what command classes exist) + - plugin/catalog/schema.json (so catalog.md describes the actual schema fields without misrepresenting them) + - plugin/catalog/catalog.json (the embedded agent list — three entries: claude-code, gsd, playwright) + - .claude/skills/catalog-schema/SKILL.md (the analog skill — for the catalog data-model framing) + </read_first> + <files>docs/internals/registry-cli.md, docs/internals/catalog.md</files> + <action> +Create the final two component docs under `docs/internals/`. Same H2 spine. + +**1. `docs/internals/registry-cli.md`** (target ~50-80 lines): +- H1: `# Registry CLI` +- Lede (3-5 lines): "`agentlinux` is the small TypeScript CLI shipped with the plugin. It reads the agent catalog and dispatches install / remove / list / info / upgrade / pin commands — every state-changing operation runs as the agent user, never as root. The CLI is the surface developers actually touch; everything else is wiring." +- `## The problem`: Frame why a CLI exists at all (vs raw shell + npm). Cover: a fleet of agents, each with its own install command and update story, becomes unmemorable; users want one verb per intent (`agentlinux install claude-code`) regardless of whether the underlying install is npm, apt, pipx, or a binary download. The naive alternative is a `README.md` listing per-agent install commands — which immediately drifts because no one updates README in lockstep with the install path. +- `## What AgentLinux does`: Describe what the CLI exposes — the verbs (`list`, `install <name>`, `remove <name>`, `info <name>`, `upgrade`, `pin <name>=<version|curated|latest>`, `doctor`). Each command reads the catalog (a JSON file validated against a published schema), looks up the right install recipe, and runs it via `as_user agent`. Mention the source-of-truth file path (`/opt/agentlinux/catalog/<version>/catalog.json`) and the dispatch pattern (CLI verb -> catalog entry -> per-agent install.sh / remove.sh) without source-line deep links. +- `## Worked example`: Brief fenced session — `agentlinux list` (showing pinned versions and installed/not-installed indicator), `agentlinux install gsd`, `agentlinux upgrade` (showing the three divergence states). +- `## Value vs the naive approach`: Trade-off pattern. Lede: "Without a CLI, the naive path is 'remember each agent's install command'. Two problems:". Numbered list: (1) **Per-agent commands drift.** README install instructions get stale the moment an agent's install changes; the CLI binds the install path to the catalog so the verb stays stable while the recipe evolves. (2) **No place to land cross-cutting concerns.** Sticky overrides, three-way divergence, install-time invocation tests, "is this agent currently installed?" status — these are properties of the *fleet*, not individual agents. The CLI is where they live. Closing sentence: "One stable verb surface for an evolving agent set — the CLI keeps the contract honest while the recipes move underneath." +- `## Related`: `[Catalog](catalog.md)`, `[Agent user](agent-user.md)`, `[Claude Code](claude-code.md)`, `[GSD](gsd.md)`, `[Playwright](playwright.md)`. + +**2. `docs/internals/catalog.md`** (target ~50-80 lines): +- H1: `# Catalog` +- Lede (3-5 lines): "The catalog is the JSON-Schema-validated registry of agents AgentLinux can install. It ships claude-code, gsd, and playwright — three opt-in entries; zero installed by default. New agents are added by submitting a catalog entry plus an install recipe — no CLI source changes required." +- `## The problem`: Frame the alternative. Cover: hardcoding the agent set into CLI source (the v0.2.0 distro path before the pivot — every new agent meant a CLI release); or no machine-readable contract at all (every install command lives only in someone's README, drifts immediately, breaks reproducibility). Both fail the "fresh contributor adds an agent in one PR" test (CAT-03). +- `## What AgentLinux does`: Describe the catalog data model. (a) `plugin/catalog/schema.json` — the JSON Schema 2020-12 contract; `additionalProperties: false` so unknown fields are a hard fail. (b) `plugin/catalog/catalog.json` — the embedded agent list shipped in the release tarball. (c) `plugin/catalog/agents/<name>/install.sh` and `remove.sh` — the per-agent recipes. Mention the three invariants from CAT-01/CAT-02/CAT-03: agents are *available* not installed by default; the catalog is schema-validated at pre-commit and CI time; adding an agent requires only a catalog entry and recipe — never a TypeScript edit. Curated combos: each release pins every catalog entry to a version tested together end-to-end (cross-link to STABILITY-MODEL.md). +- `## Worked example`: Brief fenced session — `cat plugin/catalog/catalog.json` (truncated) showing one entry, then a one-liner showing how a new agent would be added (`mkdir plugin/catalog/agents/<name> && touch plugin/catalog/agents/<name>/{install,remove}.sh && edit catalog.json`). Keep it short; the point is the data flow, not a tutorial. +- `## Value vs the naive approach`: Trade-off pattern. Lede: "Without a schema-validated catalog, the naive paths are 'hardcoded agent list in CLI source' or 'README install commands'. Two problems:". Numbered list: (1) **Hardcoding means a CLI release per agent.** Adding a new agent requires editing TypeScript, running tests, cutting a release. The catalog inverts this — a new agent is one PR with no CLI changes. (2) **Without schema validation, every recipe is a snowflake.** Schema enforces required fields (`install`, `remove`, `pinned_version`, `invocation_test`); pre-commit and CI catch malformed entries before they ship. Closing sentence: "The catalog is the contract that lets AgentLinux ship as a curated combo — pinned versions, opt-in installs, validated schema — while keeping the cost of adding an agent to one PR." +- `## Related`: `[Registry CLI](registry-cli.md)`, `[../STABILITY-MODEL.md](../STABILITY-MODEL.md)`, `[Claude Code](claude-code.md)`, `[GSD](gsd.md)`, `[Playwright](playwright.md)`. + +No source-line deep links. No Mermaid (these are well-served by prose; the catalog data model could in principle warrant a diagram, but two short paragraphs are clearer for the project-owner audience per CONTEXT.md §"Diagrams" restraint). + </action> + <verify> + <automated>test -f docs/internals/registry-cli.md && test -f docs/internals/catalog.md && grep -q '^# Registry CLI' docs/internals/registry-cli.md && grep -q '^# Catalog' docs/internals/catalog.md && for f in docs/internals/registry-cli.md docs/internals/catalog.md; do for h in '## The problem' '## What AgentLinux does' '## Value vs the naive approach' '## Related'; do grep -qF "$h" "$f" || { echo "MISSING $h in $f"; exit 1; }; done; done && grep -qF '(catalog.md)' docs/internals/registry-cli.md && grep -qF '(registry-cli.md)' docs/internals/catalog.md && grep -qE 'CAT-01|CAT-02|CAT-03|opt-in|schema-validated' docs/internals/catalog.md && ! grep -nE '\.sh:[0-9]+|\.ts:[0-9]+|\.json:[0-9]+' docs/internals/registry-cli.md docs/internals/catalog.md && ! grep -q '^```mermaid' docs/internals/registry-cli.md docs/internals/catalog.md</automated> + </verify> + <acceptance_criteria> + - Both files exist with the correct H1s (`# Registry CLI`, `# Catalog`). + - Each file contains all four required H2s. + - `registry-cli.md` lists the CLI verbs (install, list, remove, info, upgrade, pin, doctor) somewhere in `## What AgentLinux does` and links to `catalog.md` from Related. + - `catalog.md` mentions at least one of CAT-01/CAT-02/CAT-03 OR the keywords "opt-in" / "schema-validated" / "no defaults" (the three invariants), and links to `registry-cli.md` from Related. + - Each `## Value vs the naive approach` section is a numbered list with at least 2 `**bold lead clause.**` items. + - No source-line deep links in either file. + - No Mermaid fence in either file. + </acceptance_criteria> + <done>Both files committed; all H2 spine sections present; mutual cross-links between registry-cli.md and catalog.md; no deep links; no Mermaid.</done> +</task> + +</tasks> + +<verification> +After all tasks complete: + +```bash +# All five files in this plan exist +for slug in claude-code gsd playwright registry-cli catalog; do + test -f "docs/internals/${slug}.md" || { echo "MISSING ${slug}.md"; exit 1; } +done + +# Each has the four mandated H2 sections +for f in docs/internals/{claude-code,gsd,playwright,registry-cli,catalog}.md; do + for h in '## The problem' '## What AgentLinux does' '## Value vs the naive approach' '## Related'; do + grep -qF "$h" "$f" || { echo "MISSING $h in $f"; exit 1; } + done +done + +# No source-line deep links anywhere in this plan's outputs +! grep -nE '\.sh:[0-9]+|\.ts:[0-9]+|\.json:[0-9]+' docs/internals/{claude-code,gsd,playwright,registry-cli,catalog}.md +``` +</verification> + +<success_criteria> +- All 5 markdown files committed under `docs/internals/`. +- Each file follows the problem -> answer -> value vs naive contract. +- Cross-links into Plan 01's docs (`agent-user.md`, `sudo-drop-in.md`, `installer.md`, `nodejs-runtime.md`) appear in the appropriate Related footers. +- registry-cli.md and catalog.md mutually cross-link. +- No source-line deep links. +- No Mermaid diagrams in this plan (per CONTEXT.md restraint). +</success_criteria> + +<output> +After completion, create `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-02-SUMMARY.md` per the GSD summary template. +</output> diff --git a/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-02-SUMMARY.md b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-02-SUMMARY.md new file mode 100644 index 0000000..fbe7384 --- /dev/null +++ b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-02-SUMMARY.md @@ -0,0 +1,181 @@ +--- +phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 +plan: 02 +subsystem: docs +tags: [internals, claude-code, gsd, playwright-cli, registry-cli, catalog, AL-22, DOC-02] + +# Dependency graph +requires: + - phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 + plan: 01 + provides: docs/internals/ index README + 4 foundational-layer component docs (installer, agent-user, sudo-drop-in, nodejs-runtime) + the H2 spine pattern this plan extends + - phase: 04-registry-cli-catalog-uninstall + provides: plugin/cli/src/{index.ts, commands/*.ts} + plugin/catalog/{schema.json, catalog.json} (the registry CLI + catalog this plan documents) + - phase: 05-agent-installability + provides: plugin/catalog/agents/{claude-code, gsd, playwright-cli}/install.sh — the real recipes whose product-perspective story claude-code.md / gsd.md / playwright.md tell +provides: + - docs/internals/ tree complete (9-of-9 component docs landed; was 4-of-9 after Plan 01) + - 5 product-perspective component docs covering the catalog layer (3 agent docs + registry-cli + catalog) + - Mutual cross-links between registry-cli.md and catalog.md (the plan's key_links contract) + - Worked-example shell sessions for every catalog-layer surface (claude-code's `claude update` divergence, gsd's bootstrapper-wires-skills, playwright-cli's two-part install, registry-cli's verb table, catalog's add-an-agent-in-one-PR flow) +affects: + - 12-03-PLAN (dev-docs reviewer agent + dev-docs skill — both will now pattern-match against 9 working component docs, not 4) + - 12-04-PLAN (CLAUDE.md wiring of dev-docs-auditor into the Review Loop table — references the now-complete docs/internals/ tree) + - 12-05-PLAN (top-level README "Why AgentLinux — concepts" link — its target docs/internals/README.md TOC is now live with all 9 entries pointing at written docs) + +# Tech tracking +tech-stack: + added: [] # docs only — no new libraries / runtime tech + patterns: + - Component-doc H2 spine "problem -> answer -> value vs naive -> Related" (continued from Plan 01) + - Bold-lead-clause numbered-list trade-off pattern (excerpt-friendly for blog/marketing reuse; same shape Plan 01 established) + - Cross-link Related footer with no source-line deep links (CONTEXT §"Depth") + - Sibling-component cross-references (registry-cli ↔ catalog mutual; agent docs link back to agent-user.md / sudo-drop-in.md / catalog.md / registry-cli.md) + +key-files: + created: + - docs/internals/claude-code.md + - docs/internals/gsd.md + - docs/internals/playwright.md + - docs/internals/registry-cli.md + - docs/internals/catalog.md + modified: [] + +key-decisions: + - Three Rule 1 source-truth deviations baked into the docs (vs the plan's narrative): (a) playwright.md describes Microsoft's @playwright/cli (the real catalog entry id `playwright-cli`, pinned 0.1.11) — the recipe is npm-install + `playwright-cli install --skills` skill-bootstrap, NOT the older "playwright install --with-deps chromium" Playwright-library shape the plan narrated; the chromium-deps story still holds for the apt layer that the bootstrapper triggers, so the Value-vs-naive list keeps that thread. (b) gsd.md describes the get-shit-done-cc bootstrapper (`--global --claude`) that wires GSD skills into ~/.claude/skills/gsd-* — the intent-completion step the plan did not mention but the install.sh actually performs; the doc names the user-dogfood bug ("I installed it and Claude Code doesn't see it") this step exists to prevent. (c) registry-cli.md lists only the five verbs the CLI actually exposes (list, install, remove, upgrade, pin) — the plan mentioned `info` and `doctor` which do not exist in plugin/cli/src/index.ts; documented what ships. + - No Mermaid diagrams in any of the five docs. The plan flagged Mermaid as optional per CONTEXT §"Diagrams" "used sparingly"; I judged each component (a sequence diagram for the registry-CLI recipe-dispatch flow, a topology for the catalog data model) and concluded prose was clearer in both cases — neither would have lifted into blog/marketing copy any better than the prose already does. + - Worked-example shell sessions in all five docs. PATTERNS.md lists worked-example as optional, but the AL-22 litmus test ("60-second answer for what value AgentLinux adds") lands much harder with a 5-7-line transcript showing the actual observable behavior — the divergence after `claude update`, the "skill set wired" log line in gsd's install, the password-free apt install in playwright's install, the verb table in `agentlinux list`, the JSON catalog snapshot in catalog's example. + - registry-cli.md lists every verb as a bullet with a one-paragraph explanation rather than a brief enumeration. The verbs ARE the product surface — operators touch them daily. The doc is excerpt-friendly source for the agentlinux.org "what does the CLI do" section per CONTEXT §"Reuse signal"; brief enumerations would not lift into marketing copy. + - catalog.md uses the three-piece framing (schema.json + catalog.json + per-agent recipes) instead of a single "what is the catalog" paragraph. The catalog is structurally a tripartite contract, and the doc maps to that structure so readers can follow the data flow from "schema declares the shape" -> "catalog.json holds the entries" -> "recipes implement the install" without losing the thread. + +patterns-established: + - "Sibling-doc mutual cross-links: when two components are coupled (registry-cli reads catalog; catalog is consumed by registry-cli), both Related footers cite each other. Plan 12-03's dev-docs reviewer can grep for this bidirectional citation as a freshness signal." + - "Source-truth-over-plan-narrative: when the plan describes an outdated impl (the playwright story moved from chromium-deps to skill-bootstrap; the registry-cli `doctor`/`info` verbs were never built), the doc grounds in the actual install.sh / index.ts and documents the deviation as a Rule 1 fix in SUMMARY. The doc must reflect what ships, not what the plan narrated months ago." + +requirements-completed: [DOC-02] + +# Metrics +duration: 5min +completed: 2026-05-10 +--- + +# Phase 12 Plan 02: Internals catalog-layer docs — claude-code + gsd + playwright + registry-cli + catalog Summary + +**5 product-perspective component docs that complete the docs/internals/ tree by answering "what value does AgentLinux provide for surface X" for each catalog-layer surface — the three pinned agents (claude-code, gsd, playwright-cli), the registry CLI that drives them, and the schema-validated catalog they live in.** + +## Performance + +- **Duration:** ~5 min +- **Started:** 2026-05-10T05:55:47Z +- **Completed:** 2026-05-10T06:00:40Z +- **Tasks:** 2 +- **Files created:** 5 +- **Files modified:** 0 + +## Accomplishments + +- Three agent docs (claude-code, gsd, playwright) each grounded in the actual `plugin/catalog/agents/<id>/install.sh` body — every claim about install path, ownership, or post-install state is verifiable against the recipe that ships. +- Registry CLI doc covering all five real verbs (list, install, remove, upgrade, pin) — including the `preAction` guardAgentUser hook (CLI-05), the catalog snapshot path on disk, and the recipe-dispatch flow with environment-injection of `AGENTLINUX_PINNED_VERSION`. +- Catalog doc covering the three-piece data model (`schema.json` + `catalog.json` + per-agent recipes) plus the three CAT-01/CAT-02/CAT-03 invariants and the curated-combo connection to STABILITY-MODEL.md. +- Mutual cross-links between registry-cli.md and catalog.md (each Related footer cites the other), per the plan's `key_links` contract. +- Worked-example shell sessions in every doc, sized for blog/marketing excerpt reuse: claude-code shows the `claude update` divergence; gsd shows the skill-set-wired log line; playwright shows the password-free apt-deps step; registry-cli shows the `agentlinux list` table + verb cascade; catalog shows the JSON snapshot + the add-an-agent-in-one-PR flow. +- Hard contract upheld: no source-line deep links (`*.sh:NN`, `*.ts:NN`, `*.json:NN`) anywhere; no Mermaid fences; ADR mentions in prose only (playwright.md prose-cites ADR-012 with link; the rest are prose-only mentions). +- All five files easily exceed the plan's 40-line min_lines requirement (smallest: gsd at 116 lines; largest: catalog at 153 lines). + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Write claude-code.md + gsd.md + playwright.md** — `3f6e329` (docs) +2. **Task 2: Write registry-cli.md + catalog.md** — `e71d8cc` (docs) + +**Plan metadata commit (this SUMMARY + STATE/ROADMAP/REQUIREMENTS updates):** committed after this file lands. + +## Files Created/Modified + +- `docs/internals/claude-code.md` (121 lines) — Agent doc on Anthropic's Claude Code CLI in the catalog. Lede frames it as "the canonical AgentLinux acceptance test (AGT-02)." Problem walks through the EACCES + recursive-shim cycle that follows from `sudo npm install -g @anthropic-ai/claude-code`, naming AGT-02 as the regression test. Answer describes the recipe: pipe `claude.ai/install.sh` to bash with the running user already dropped to `agent`, install lands at `/home/agent/.local/bin/claude`, agent-owned, so `claude update` Just Works. Worked example shows `claude update` followed by `agentlinux upgrade` surfacing the override-ahead divergence. Trade-off list: (1) `claude update` breaks on root-owned trees, (2) Upstream `latest` ships immediately. Related links agent-user, catalog, registry-cli, ../STABILITY-MODEL.md. +- `docs/internals/gsd.md` (116 lines) — Agent doc on GSD (`get-shit-done-cc` on npm). Lede positions it as a Claude Code workflow framework. Problem covers both the ownership trap (sudo npm install -g) AND the upstream-cadence trap (GSD ships fast, occasional broken releases) AND the user-dogfood gap ("binary on PATH but Claude Code sees no /gsd-* commands") — the third strand grounded in the actual install.sh comment block (lines 50-65). Answer describes `npm install -g get-shit-done-cc@<pinned>` into the agent's per-user prefix + the bootstrapper invocation `get-shit-done-cc --global --claude` that copies the skill set into `~/.claude/skills/gsd-*/`. Worked example shows the install transcript ending in "skill set wired into …/gsd-*". Trade-off list: (1) The agent's own workflow tools end up root-owned, (2) Upstream regressions hit immediately. Related links agent-user, catalog, registry-cli, ../STABILITY-MODEL.md. +- `docs/internals/playwright.md` (119 lines) — Agent doc on Microsoft's `@playwright/cli` (catalog id `playwright-cli`). Lede frames it as the agent-oriented Playwright CLI plus its Claude Code skill, not the JS Playwright library. Problem covers three failure modes in sequence: ownership trap (sudo npm install -g), apt-deps password prompt (Playwright's installer auto-prepends sudo for browser-deps; non-interactive sessions stall), and intent gap (skill-set-not-wired). Answer describes the two-part install: `npm install -g @playwright/cli@<pinned>` + pre-skills version-lock + `playwright-cli install --skills` from agent home + ADR-012 NOPASSWD drop-in carries the apt step. Worked example shows the install transcript ending in "skill wired into …/playwright-cli". Trade-off list: (1) The npm install ends up root-owned, (2) The browser-deps step needs sudo, which stalls non-interactive sessions. Related links agent-user, sudo-drop-in, catalog, registry-cli. +- `docs/internals/registry-cli.md` (142 lines) — Component doc on the `agentlinux` CLI. Lede frames it as the surface developers actually touch. Problem covers fleet unmemorability (every agent has its own install command) + cross-cutting concerns having nowhere to live (stickiness, divergence, install-time invariants) + invocation discipline (must-run-as-agent, must-inject-pinned-version). Answer describes the five verbs (list, install, remove, upgrade, pin) with one-paragraph each, plus the `preAction` guardAgentUser hook (CLI-05), the catalog snapshot at `/opt/agentlinux/catalog/<version>/catalog.json`, and the runner that exports the agent environment before shelling into the recipe. Worked example shows `agentlinux list` (the verb table) -> `install gsd` -> `upgrade` (synced state). Trade-off list: (1) Per-agent commands drift, (2) No place to land cross-cutting concerns. Related links catalog, agent-user, claude-code, gsd, playwright. +- `docs/internals/catalog.md` (153 lines) — Component doc on the catalog (the schema-validated agent registry). Lede frames it as opt-in, three real entries, zero installed by default. Problem covers the two naive paths (hardcoded agent list in CLI source, README-only) + the version-pinning collapse (without per-entry pinned_version, "curated combo" reduces to "whatever npm serves today"). Answer describes the three-piece data model (`plugin/catalog/schema.json` JSON Schema 2020-12 with additionalProperties:false; `plugin/catalog/catalog.json` embedded list with three real entries + one test_only fixture; per-agent recipe pairs under `plugin/catalog/agents/<id>/`) plus the three invariants (CAT-01 available-not-installed; CAT-02 schema-validated at pre-commit + CI; CAT-03 add-agent-in-one-PR). Worked example shows the JSON snapshot + the add-a-new-agent flow. Trade-off list: (1) Hardcoding means a CLI release per agent, (2) Without schema validation, every recipe is a snowflake. Related links registry-cli, ../STABILITY-MODEL.md, claude-code, gsd, playwright. + +## Decisions Made + +- **Source-truth-over-plan-narrative for three claims (Rule 1 deviations).** (a) playwright.md grounds in the actual `plugin/catalog/agents/playwright-cli/install.sh` (Microsoft's `@playwright/cli`, pinned 0.1.11, npm + `--skills` bootstrap) instead of the plan's narrative about Playwright + chromium-with-deps. The chromium-deps thread is preserved in the Value-vs-naive list as the apt-layer that the bootstrapper triggers — the doc covers the real install path AND the trade-off the plan was after. (b) gsd.md adds the `get-shit-done-cc --global --claude` bootstrapper (the intent-completion step the plan did not mention but the install.sh performs) along with the user-dogfood bug ("I installed it and Claude Code doesn't see it") that motivated the recipe addition. (c) registry-cli.md lists only the verbs that ship in `plugin/cli/src/index.ts` — list, install, remove, upgrade, pin — and omits the plan's `info` and `doctor` mentions which do not exist as commands. The doc must reflect what ships, not what the plan narrated. +- **No Mermaid diagrams.** The plan flagged Mermaid as optional per CONTEXT §"Diagrams" "used sparingly." I considered a sequence diagram for registry-cli (verb -> catalog -> recipe -> sentinel) and a topology diagram for catalog (schema + manifest + recipes). Both lost to prose: the registry-cli verb-by-verb explanation is cleaner as a bullet list than as a sequence diagram, and the catalog's three-piece structure is short enough that paragraphs read faster than a topology figure. Per the AL-22 litmus test ("60-second answer"), prose was the better lift. +- **One ADR link allowed (playwright.md → ADR-012 in prose with link).** Plan 12-01 established that ADR-012 is the doc-to-ADR mapping where a direct link is justified — sudo-drop-in.md links it from Related. Playwright.md prose-cites ADR-012 because the apt-deps story directly turns on the NOPASSWD grant; a parenthetical link in prose mirrors the depth Plan 12-01 set. Other ADR mentions stay prose-only (CAT-01/CAT-02/CAT-03/ADR-003/ADR-008 referenced by name in catalog.md and registry-cli.md without links). +- **Worked examples in all five docs.** PATTERNS.md lists worked-example as optional. I included one in each because the AL-22 litmus test ("60-second answer for what value AgentLinux adds") is reinforced dramatically by a 5-7-line transcript showing the actual observable behavior. The transcripts are also the single most excerpt-friendly content for the agentlinux.org landing page per CONTEXT §"Reuse signal" — every example was sized to lift cleanly into a marketing snippet without surrounding prose. +- **Sibling cross-links rather than full-fan-out Related footers.** Each agent doc cross-links the other components most-tightly-coupled to it (claude-code → agent-user + catalog + registry-cli + STABILITY-MODEL; gsd → same set; playwright → same set + sudo-drop-in for the apt-deps thread). registry-cli and catalog mutually cross-link plus link to all three agent entries (they are the catalog the registry-cli iterates). I deliberately did NOT cross-link agent docs to each other (claude-code → gsd, etc.) — operators reading "what is GSD" do not need a "see also Claude Code" pointer; they want to learn about GSD. Cross-links serve discoverability of dependencies, not symmetry. + +## Deviations from Plan + +Three Rule 1 (source-truth) auto-fix deviations, all baked into the docs themselves and documented in the per-task commit messages. + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] playwright.md grounded in @playwright/cli reality, not the plan's narrated Playwright-with-chromium-deps** + +- **Found during:** Task 1 (reading `plugin/catalog/agents/playwright-cli/install.sh` per `<read_first>`) +- **Issue:** The plan narrative described installing the JS Playwright library + running `playwright install --with-deps chromium`. The actual catalog entry id is `playwright-cli`, the pinned package is `@playwright/cli` (0.1.11), and the install path is npm-install + `playwright-cli install --skills` (Claude Code skill bootstrap). The plan's narrative was from an earlier impl that the catalog moved past. +- **Fix:** Wrote the doc against the real install.sh: lede mentions `@playwright/cli` and the skill-bootstrap explicitly; problem section keeps the apt-deps story (real, since the bootstrapper triggers apt-layer browser deps via Playwright's sudo-prepended internal path); answer section describes the real two-part install. The chromium-deps thread becomes the second item in the Value-vs-naive list (preserves the plan's intent that the playwright doc carry the apt-layer / sudo-drop-in story). +- **Files modified:** `docs/internals/playwright.md` +- **Commit:** `3f6e329` + +**2. [Rule 1 - Bug] gsd.md adds the bootstrapper-wires-skills story the plan did not mention** + +- **Found during:** Task 1 (reading `plugin/catalog/agents/gsd/install.sh` per `<read_first>`) +- **Issue:** The plan's gsd narrative described an npm-install-only flow. The actual install.sh runs `get-shit-done-cc --global --claude` after the npm install to copy GSD's skill set into `~/.claude/skills/gsd-*/`. The install.sh comment block (lines 50-77) names the user-dogfood bug ("binary on PATH but Claude Code sees no /gsd-* commands") that motivated adding the bootstrapper invocation. Without that step, "agentlinux install gsd" succeeds technically but fails the user's intent. +- **Fix:** Added a third Problem-section paragraph naming the intent gap; added the bootstrapper invocation to the Answer section; included the "skill set wired" log line in the Worked example. The doc now reflects what the recipe actually does, including the user-dogfood-discovery story (which doubles as excellent blog material per CONTEXT §"Reuse signal"). +- **Files modified:** `docs/internals/gsd.md` +- **Commit:** `3f6e329` + +**3. [Rule 1 - Bug] registry-cli.md lists only the verbs that ship** + +- **Found during:** Task 2 (reading `plugin/cli/src/index.ts` per `<read_first>`) +- **Issue:** The plan's registry-cli narrative listed seven verbs (list, install, remove, info, upgrade, pin, doctor). The actual `plugin/cli/src/index.ts` registers five subcommands: list, install, remove, upgrade, pin. There is no `info` and no `doctor`. Documenting verbs that do not exist would mislead operators and fail the catalog auditor's "doc freshness" rubric (Plan 12-03 will codify this rubric — a doc that names a non-shipping verb would be exactly the kind of staleness the auditor flags). +- **Fix:** Wrote the doc against the actual five-verb surface in `index.ts`. Each verb gets a one-paragraph explanation grounded in the corresponding `plugin/cli/src/commands/<verb>.ts` impl. The doc still carries the "why a CLI exists at all" framing the plan was after. +- **Files modified:** `docs/internals/registry-cli.md` +- **Commit:** `e71d8cc` + +## Issues Encountered + +The pre-existing `git status` snapshot showed unrelated modifications to `.planning/config.json`, three Plan 12-0[3..5] PLAN.md files, `docs/audits/v0.4.0/PUB-04-release-notes.md`, plus `.planning/{MILESTONES,ROADMAP,STATE}.md` from earlier in the day. These were left strictly untouched. Per the protocol, only the five `docs/internals/*.md` files were `git add`-ed and committed; no `git add .` / `-A` was used. + +The plan-level verify block (the bash chain at the bottom of `<verification>`) and both per-task verify blocks all passed first try with no fix commits required. The acceptance criteria checks (H1 / H2 spine / mutual cross-links / no source-line deep links / no Mermaid / bold-lead-clause numbered list with ≥2 items) all passed for all five files on first write. + +## User Setup Required + +None — no external service configuration required. + +## Next Phase Readiness + +- `docs/internals/` tree complete: 9 of 9 component docs landed (4 from Plan 01, 5 from this plan). Every TOC entry in `docs/internals/README.md` now points at a written doc. +- Plan 12-03 (dev-docs reviewer + dev-docs skill) can now pattern-match against the full set of 9 examples — the structural contract (problem -> answer -> worked example -> value vs naive -> Related; bold-lead-clause trade-off list; sibling cross-links; no source-line deep links; ADR mentions prose-by-default with one allowed link per Plan 01) is reified across 9 working component docs. The reviewer's source-to-doc dispatch table can grep for the 9 component slugs as the registry it reads. +- Plan 12-04 (CLAUDE.md wiring of dev-docs-auditor into the Review Loop table) and Plan 12-05 (top-level README "Why AgentLinux — concepts" pointer into docs/internals/) are both unblocked by this plan's completion. The README pointer Plan 05 lands now has a complete tree of nine docs to land into. +- The three Rule 1 source-truth deviations baked into this plan establish a precedent the dev-docs reviewer will codify in Plan 12-03: when an existing doc says X about the source but the source is Y, the doc must be updated to Y, and the deviation must be documented in the SUMMARY (or, post-Plan-03, in the PR description that the reviewer reads). "Doc reflects what ships, not what the plan narrated" is the freshness rule. + +## Self-Check: PASSED + +- `docs/internals/claude-code.md` — FOUND (121 lines) +- `docs/internals/gsd.md` — FOUND (116 lines) +- `docs/internals/playwright.md` — FOUND (119 lines) +- `docs/internals/registry-cli.md` — FOUND (142 lines) +- `docs/internals/catalog.md` — FOUND (153 lines) +- Task 1 commit `3f6e329` — FOUND in `git log` +- Task 2 commit `e71d8cc` — FOUND in `git log` +- Each component doc has the four mandated H2 sections (`## The problem`, `## What AgentLinux does`, `## Value vs the naive approach`, `## Related`) — VERIFIED via grep +- All five files have correct H1s (`# Claude Code`, `# GSD (Get Shit Done)`, `# Playwright`, `# Registry CLI`, `# Catalog`) — VERIFIED via grep +- registry-cli.md → catalog.md cross-link present (`(catalog.md)`) — VERIFIED via grep +- catalog.md → registry-cli.md cross-link present (`(registry-cli.md)`) — VERIFIED via grep +- claude-code.md mentions AGT-02 / `claude update` — VERIFIED via grep +- claude-code.md links to agent-user.md AND mentions EACCES — VERIFIED via grep +- playwright.md mentions sudo-drop-in.md cross-link — VERIFIED via grep (`(sudo-drop-in.md)`) +- catalog.md mentions CAT-01 / CAT-02 / CAT-03 / opt-in / schema-validated — VERIFIED via grep +- registry-cli.md lists install / list / remove / upgrade / pin — VERIFIED via grep +- All five `## Value vs the naive approach` sections use bold-lead-clause numbered format with exactly 2 items each — VERIFIED via `grep -cE '^[0-9]+\. \*\*'` +- No source-line deep links (`*.sh:NN`, `*.ts:NN`, `*.json:NN`) anywhere in the five new files — VERIFIED via `grep -nE` +- No Mermaid fences in the five new files — VERIFIED via `grep '^```mermaid'` + +--- +*Phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22* +*Completed: 2026-05-10* diff --git a/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-03-PLAN.md b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-03-PLAN.md new file mode 100644 index 0000000..8b18768 --- /dev/null +++ b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-03-PLAN.md @@ -0,0 +1,480 @@ +--- +phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 +plan: 03 +type: execute +wave: 1 +depends_on: [] +files_modified: + - .claude/agents/dev-docs-auditor.md + - .claude/skills/dev-docs/SKILL.md +autonomous: true +requirements: [DOC-03, DOC-04, DOC-06] + +must_haves: + truths: + - "A new project-scoped reviewer agent (dev-docs-auditor) exists with read-only tools (Read, Grep, Glob, Bash)" + - "The reviewer's frontmatter description triggers it on changes under plugin/bin/, plugin/lib/, plugin/provisioner/, plugin/cli/src/, plugin/catalog/, packaging/curl-installer/" + - "A new project-scoped skill (.claude/skills/dev-docs/) documents the docs contract — per-component file structure, source-path -> doc-path dispatch table, when to update, product-perspective lens" + - "No new stop-hook is added; .claude/settings.json is unchanged; no .claude/hooks/dev-docs-reminder.sh exists" + artifacts: + - path: ".claude/agents/dev-docs-auditor.md" + provides: "Read-only reviewer agent that flags missing or stale docs/internals/ updates when plugin/ source changes" + contains: "dev-docs-auditor" + min_lines: 50 + - path: ".claude/skills/dev-docs/SKILL.md" + provides: "Skill that documents the docs/internals/ contract and the source-path -> doc-path dispatch the reviewer reads" + contains: "## When to use this skill" + min_lines: 60 + key_links: + - from: ".claude/agents/dev-docs-auditor.md" + to: ".claude/skills/dev-docs/SKILL.md" + via: "skill reference in agent body" + pattern: "dev-docs" + - from: ".claude/skills/dev-docs/SKILL.md" + to: "docs/internals/README.md" + via: "Related footer markdown link" + pattern: "docs/internals" +--- + +<objective> +Create the maintenance tooling that keeps `docs/internals/` in sync with the source: a new project-scoped reviewer agent (`dev-docs-auditor`) and a new project-scoped skill (`dev-docs/`). The reviewer is invoked by the existing review loop (per CLAUDE.md "Review Loop" routing — wired in Plan 04) — no new stop-hook is added; the existing `review-reminder.sh` and `session-tracker-reminder.sh` cover the reminder surface (per CONTEXT.md "Maintenance Tooling" + ADR-010 refinement). + +Purpose: Embed dev-docs-sync enforcement inside the existing review loop so docs don't drift the moment they ship, without multiplying ADR-010 reminder noise. +Output: 2 new files (one reviewer agent, one skill). +</objective> + +<execution_context> +@$HOME/.claude/get-shit-done/workflows/execute-plan.md +@$HOME/.claude/get-shit-done/templates/summary.md +</execution_context> + +<context> +@.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md +@.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-PATTERNS.md +@.claude/agents/catalog-auditor.md +@.claude/skills/catalog-schema/SKILL.md +@docs/decisions/010-review-loop-via-claude-md.md + +<interfaces> +<!-- Reviewer agent frontmatter contract (PATTERNS.md §"Frontmatter discipline"): --> + +```markdown +--- +name: dev-docs-auditor # kebab-case slug, matches filename +description: <single long sentence stating focus + Use on/when directive with concrete path globs ; <= 400 chars> +tools: Read, Grep, Glob, Bash # read-only — same as all six existing reviewers +--- +``` + +<!-- Reviewer body H2 spine (PATTERNS.md §".claude/agents/dev-docs-auditor.md (reviewer-agent)"): --> + +```markdown +# Dev-Docs Auditor (H1: Title-Case role name) + +[1-3 sentence opener: who I am, what I review, what makes the surface special] + +## When to spawn [bullet list of file globs] +## When NOT to spawn [optional inverse list — clean way to encode skip conditions] +## What to look for [numbered rubric, 6-8 items, **bold lead clause** style] +## Common gotchas (AgentLinux-specific) [bullet list of pitfalls in **bold lead clause** style] +## Output format [free-form summary contract + fenced example] +``` + +<!-- Skill frontmatter contract (PATTERNS.md §"Frontmatter discipline"): --> + +```markdown +--- +name: dev-docs # kebab-case slug, matches dirname +description: Use when X. Documents Y. <key rule one-liner>. Grows <when>. +--- +``` + +<!-- Skill body H2 spine (PATTERNS.md §".claude/skills/dev-docs/SKILL.md"): --> + +```markdown +# dev-docs — <one-line title> (H1: <slug> — <one-line title>) + +**Status:** ... (single bold status line) + +Authoritative spec: ... (one-line cross-link sentence) +Decisions: ... (one-line ADR enumeration if applicable) +Requirements this skill helps enforce: ... + +## When to use this skill [bullet list of file globs] +## Why this exists [paragraph] +## Per-component file structure [the four-part contract from CONTEXT.md] +## Source-path -> doc-path dispatch table [THE registry the reviewer reads] +## When to update [skip conditions + change-triggering conditions] +## Product-perspective lens [the AL-22 litmus test] +## Growth plan [bulleted phase-by-phase plan] +## Related [bulleted cross-links footer] +``` + +Hard constraints: +- The reviewer agent's `tools:` line MUST be read-only — `Read, Grep, Glob, Bash`. NEVER include `Write` or `Edit` (the reviewer documents findings; the main agent triages and writes). +- The reviewer is invoked by Claude during the existing review loop (per CLAUDE.md "Review Loop" routing — wired in Plan 04). It is NOT invoked by a hook. +- The reviewer MUST NOT spawn other reviewers. (The review loop's dispatcher is the main agent, per ADR-010.) +- No new file under `.claude/hooks/`. No edit to `.claude/settings.json`. +- The skill's `## Source-path -> doc-path dispatch table` is the single source of truth for which source path maps to which `docs/internals/<component>.md`. The reviewer reads this skill at decision time. Concrete mapping (per CONTEXT.md): + +| Source path glob | Component doc | +|---|---| +| `packaging/curl-installer/*.sh`, `plugin/bin/agentlinux-install` | `docs/internals/installer.md` | +| `plugin/provisioner/10-agent-user.sh` | `docs/internals/agent-user.md` | +| `plugin/provisioner/20-sudoers.sh` | `docs/internals/sudo-drop-in.md` | +| `plugin/provisioner/30-nodejs.sh`, `plugin/provisioner/40-path-wiring.sh`, `plugin/lib/as_user.sh` | `docs/internals/nodejs-runtime.md` | +| `plugin/catalog/agents/claude-code/*` | `docs/internals/claude-code.md` | +| `plugin/catalog/agents/gsd/*` | `docs/internals/gsd.md` | +| `plugin/catalog/agents/playwright-cli/*`, `plugin/catalog/agents/playwright/*` | `docs/internals/playwright.md` | +| `plugin/cli/src/**`, `plugin/provisioner/50-registry-cli.sh` | `docs/internals/registry-cli.md` | +| `plugin/catalog/schema.json`, `plugin/catalog/catalog.json` | `docs/internals/catalog.md` | +</interfaces> +</context> + +<tasks> + +<task type="auto"> + <name>Task 1: Write .claude/agents/dev-docs-auditor.md</name> + <read_first> + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md (the authoritative spec for the reviewer's responsibilities, trigger paths, and skip conditions) + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-PATTERNS.md (the analog assignment + section spine + opener pattern) + - .claude/agents/catalog-auditor.md (the closest analog — copy frontmatter shape, opener pattern, `## When to spawn` / `## What to look for` / `## Common gotchas` / `## Output format` shapes) + - .claude/agents/bash-engineer.md (a second analog — same H2 spine, useful as a tone reference) + - docs/decisions/010-review-loop-via-claude-md.md (so the agent body can cite ADR-010 and the 2026-05-02 refinement when explaining why no hook is added) + - .claude/skills/catalog-schema/SKILL.md (the analog skill the catalog-auditor consumes — the dev-docs-auditor will consume the dev-docs skill the same way) + </read_first> + <files>.claude/agents/dev-docs-auditor.md</files> + <action> +Create `.claude/agents/dev-docs-auditor.md` matching the catalog-auditor.md shape verbatim in spine. Target ~80-130 lines. + +**Frontmatter (lines 1-5):** +```markdown +--- +name: dev-docs-auditor +description: Reviews changes under plugin/bin/, plugin/lib/, plugin/provisioner/, plugin/cli/src/, plugin/catalog/, and packaging/curl-installer/ to verify the matching docs/internals/<component>.md is still accurate. Flags missing component docs, stale claims, source-line deep links, and TOC drift in docs/internals/README.md. Read-only — main agent triages. +tools: Read, Grep, Glob, Bash +--- +``` + +(The description above is 347 characters — already under the 400-char gate. Use it verbatim. If you tweak the wording, keep the path globs and the "Read-only — main agent triages" closer, and keep the total under 400 characters.) + +**H1 + opener (right after frontmatter):** +```markdown +# Dev-Docs Auditor + +Project-scoped review subagent for the `docs/internals/` developer documentation. The internals tree is the project owner's 60-second answer to "what value does AgentLinux provide for surface X" (the AL-22 litmus question). This auditor verifies the docs stay in sync when the underlying source changes — flagging missing or stale component docs, not gating phase close. +``` + +(Three sentences. Match the catalog-auditor opener pattern: "Project-scoped review subagent for X." → "Why X matters." → "What this auditor verifies.") + +**`## When to spawn`** (bulleted file-glob list — every bullet starts with "Any change under" or "Any change to" plus a concrete path): +- Any change under `plugin/bin/agentlinux-install`. +- Any change under `plugin/lib/*.sh` (logging, idempotency, as_user, distro detection). +- Any change under `plugin/provisioner/*.sh` (agent user, sudoers drop-in, Node.js, PATH wiring, registry CLI). +- Any change under `plugin/cli/src/**` (the registry CLI source). +- Any change under `plugin/catalog/{schema,catalog}.json` or `plugin/catalog/agents/<name>/{install,remove}.sh` or `plugin/catalog/agents/<name>/recipe.json`. +- Any change under `packaging/curl-installer/install.sh`. +- When a **new top-level component surface lands** under `plugin/` (a new provisioner, a new CLI command class, a new catalog backend) — the matching `docs/internals/<component>.md` should ship in the same PR. + +**`## When NOT to spawn`** (the inverse list — encode the CONTEXT.md skip conditions cleanly): +- Pure refactors that don't change observable behavior (rename, extract function, reformat). +- Comment-only or typo-only changes. +- Whitespace / formatting-only diffs. +- `.planning/`-only changes (GSD workflow state is not source). +- `tests/` changes that don't touch `plugin/` source paths above. +- `docs/`-only changes (already covered by `technical-writer` and `fact-checker`). + +**`## What to look for`** (numbered rubric, 6-8 items, **bold lead clause** style — copy the catalog-auditor's "Rubric (copy-of-truth from `docs/HARNESS.md` §...)" lede shape, but cite the dev-docs skill instead): + +Rubric (copy-of-truth from `.claude/skills/dev-docs/SKILL.md`): + +1. **Component coverage.** Every changed source path under the trigger globs above MUST map to a `docs/internals/<component>.md` (per the dispatch table the dev-docs skill defines). A change with no matching component doc is a flag. +2. **Doc freshness.** The component doc still describes what the source actually does (problem → answer → value spine still valid; no stale claims like "uses npm" when the implementation now uses something else, or "v0.3.0 pins claude-code 2.1.98" when the pinned version moved). +3. **Skip conditions honored.** Pure refactors, comment-only changes, typo fixes, formatting-only diffs do not require docs updates — note in the skip column, not the action column. +4. **Product-perspective lens preserved.** The doc still answers "what value does AgentLinux add for X" — not "here is the line-by-line implementation." Flag prose that's drifted toward implementation detail (e.g. "uses Commander.js" leading the prose; the right frame is "ships a registry CLI"). +5. **No source-line cross-references.** Per CONTEXT.md §"Depth," `path/to/file.sh:42` deep links are out of scope for the docs/internals/ layer. Flag any that slip in. +6. **TOC integrity.** When a new component doc is added or removed, `docs/internals/README.md`'s `## Components` TOC must be updated. Flag missing or orphan TOC entries. +7. **The four-section spine.** Every component doc has the four required H2s: `## The problem`, `## What AgentLinux does`, `## Value vs the naive approach`, `## Related`. Flag any new or modified component doc missing one. +8. **Reuse-friendliness preserved.** The `## Value vs the naive approach` numbered list still uses **bold lead clause** style (per CONTEXT.md §"Reuse signal" — the docs double as raw material for blog/marketing copy). + +**`## Common gotchas (AgentLinux-specific)`** (bulleted list, **bold lead clause** style, 4-6 entries): +- **A new component shipped without a doc.** When a new top-level surface lands under `plugin/` (new provisioner, new CLI command class, new catalog backend), the matching `docs/internals/<surface>.md` should ship in the same PR. Flag. +- **Implementation detail leaking through.** "Uses Commander.js" is the wrong frame; "ships a registry CLI" is the right frame. Product perspective trumps tool name. +- **Source-line cross-references slipped in.** CONTEXT.md §"Depth" rules them out for the initial cut. Flag. +- **Stale `pinned_version` numbers in agent docs.** When a catalog `pinned_version` moves, the agent doc's worked example may show the old number. Flag if the disagreement is load-bearing. +- **TOC orphan in `docs/internals/README.md`.** A doc was deleted but the TOC entry still links it; or a doc was added but the TOC didn't grow. Flag. +- **Mermaid diagrams used heavily.** CONTEXT.md §"Diagrams" allows them sparingly — only when a diagram genuinely illustrates a concept prose doesn't. Flag if a diagram is decorative. + +**`## Output format`** (use the catalog-auditor template verbatim in shape; swap the reviewer name and the example findings): + +```markdown +## Output format + +Free-form summary per HARNESS.md §4.3. File:line citations, short sentences, no rigid BLOCK/FLAG/PASS scheme. + +Example: + +\`\`\` +## dev-docs-auditor review summary + +Files reviewed: plugin/provisioner/30-nodejs.sh, plugin/provisioner/40-path-wiring.sh + +Dispatch: both files map to `docs/internals/nodejs-runtime.md` (per .claude/skills/dev-docs/SKILL.md). + +Findings: +- docs/internals/nodejs-runtime.md — ## What AgentLinux does still claims `~/.npm-global/`, but `30-nodejs.sh` now uses `~/.local/lib/node_modules`. Stale. +- docs/internals/nodejs-runtime.md — `## Value vs the naive approach` numbered list lost its **bold lead clause** style on the rewrite. Reduces excerpt-friendliness for blog/marketing copy. +- docs/internals/README.md — no orphan TOC entries; no missing TOC entries. + +One stale claim, one style regression, no missing docs. +\`\`\` + +Main agent triages. +``` + +(Use a real fenced code block — three backticks. The example I wrote with `\`\`\`` is just to show the structure.) + +Closing note (after `## Output format`): one short paragraph reminding that this auditor does NOT spawn other reviewers and does NOT gate phase close (unlike `behavior-coverage-auditor` which has an `## Exit behavior` section). The dev-docs are reference material; staleness is a flag for the main agent to triage, not a release blocker. + </action> + <verify> + <automated>test -f .claude/agents/dev-docs-auditor.md && head -5 .claude/agents/dev-docs-auditor.md | grep -qF 'name: dev-docs-auditor' && head -5 .claude/agents/dev-docs-auditor.md | grep -qE '^tools: Read, Grep, Glob, Bash$' && ! head -5 .claude/agents/dev-docs-auditor.md | grep -qE '\b(Write|Edit)\b' && grep -q '^# Dev-Docs Auditor' .claude/agents/dev-docs-auditor.md && grep -q '^## When to spawn' .claude/agents/dev-docs-auditor.md && grep -q '^## When NOT to spawn' .claude/agents/dev-docs-auditor.md && grep -q '^## What to look for' .claude/agents/dev-docs-auditor.md && grep -q '^## Common gotchas' .claude/agents/dev-docs-auditor.md && grep -q '^## Output format' .claude/agents/dev-docs-auditor.md && grep -qF 'plugin/bin' .claude/agents/dev-docs-auditor.md && grep -qF 'plugin/lib' .claude/agents/dev-docs-auditor.md && grep -qF 'plugin/provisioner' .claude/agents/dev-docs-auditor.md && grep -qF 'plugin/cli/src' .claude/agents/dev-docs-auditor.md && grep -qF 'plugin/catalog' .claude/agents/dev-docs-auditor.md && grep -qF 'packaging/curl-installer' .claude/agents/dev-docs-auditor.md && grep -qF 'docs/internals' .claude/agents/dev-docs-auditor.md && grep -qF '.claude/skills/dev-docs' .claude/agents/dev-docs-auditor.md && ! grep -q '^## Exit behavior' .claude/agents/dev-docs-auditor.md && desc_len=$(awk '/^description:/ {sub(/^description: */,""); print length($0); exit}' .claude/agents/dev-docs-auditor.md) && [ "$desc_len" -le 400 ]</automated> + </verify> + <acceptance_criteria> + - File `.claude/agents/dev-docs-auditor.md` exists. + - Frontmatter `name:` is exactly `dev-docs-auditor` (kebab-case, matches filename slug). + - Frontmatter `tools:` line is exactly `tools: Read, Grep, Glob, Bash` (no `Write`, no `Edit`). + - Frontmatter `description:` is one sentence, contains the path globs `plugin/bin/`, `plugin/lib/`, `plugin/provisioner/`, `plugin/cli/src/`, `plugin/catalog/`, `packaging/curl-installer/`, and is <= 400 characters. + - H1 is `# Dev-Docs Auditor`. + - All five mandated H2s present: `## When to spawn`, `## When NOT to spawn`, `## What to look for`, `## Common gotchas`, `## Output format`. + - The body references `.claude/skills/dev-docs/` (the skill the reviewer consumes) and `docs/internals/` (the surface it reviews). + - The body does NOT include `## Exit behavior` (that section is for phase-gating reviewers; this one doesn't gate). + - The `## What to look for` rubric is a numbered list of 6-8 items, each in `**bold lead clause.**` style. + - The `## Output format` section ends with a closing motto line of `Main agent triages.` (or near equivalent — `Main agent triages; reviewer documents.` is also accepted, per the catalog-auditor variant). + </acceptance_criteria> + <done>Reviewer agent file committed; frontmatter validates shape; all required H2s present; read-only tools enforced.</done> +</task> + +<task type="auto"> + <name>Task 2: Write .claude/skills/dev-docs/SKILL.md</name> + <read_first> + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-PATTERNS.md + - .claude/skills/catalog-schema/SKILL.md (the closest skill analog — copy frontmatter shape, status block, H2 spine, growth plan, Related footer) + - .claude/skills/agentlinux-installer/SKILL.md (a second skill analog for tone reference) + - .claude/agents/dev-docs-auditor.md (just-written — the SKILL must align with the rubric the agent applies) + - docs/internals/README.md (the index the skill points at — Plan 01 wrote it) + </read_first> + <files>.claude/skills/dev-docs/SKILL.md</files> + <action> +Create the directory and skill file: `mkdir -p .claude/skills/dev-docs && touch .claude/skills/dev-docs/SKILL.md`. Target ~100-150 lines. + +**Frontmatter (lines 1-3):** +```markdown +--- +name: dev-docs +description: Use when the task touches plugin/bin/, plugin/lib/, plugin/provisioner/, plugin/cli/src/, plugin/catalog/, or packaging/curl-installer/ — verify the matching docs/internals/<component>.md is still accurate. Documents the four-section contract (problem -> answer -> value vs naive -> related), the source-path -> doc-path dispatch table, the product-perspective lens (the AL-22 litmus question), and the explicit decision to NOT add a stop-hook for docs sync. Grows when new top-level surfaces land under plugin/ in future milestones. +--- +``` + +(Description follows the `Use when X. Documents Y. <key rule>. Grows <when>.` shape from the analog. <= 600 characters is OK; the catalog-schema description is 521 chars.) + +**H1 (immediately after frontmatter):** +```markdown +# dev-docs — docs/internals/ contract for AgentLinux developer docs +``` + +**Status block (single bold line, then a context paragraph):** +```markdown +**Status:** Active. Established in Phase 12 (DOC-01..DOC-07). The `docs/internals/` tree shipped 9 component docs alongside this skill and the `dev-docs-auditor` reviewer. + +Authoritative spec: `docs/HARNESS.md` §4 (review loop) + this skill body. Decisions: ADR-010 (review loop via CLAUDE.md, refined 2026-05-02 to allow reminder hooks with `stop_hook_active` guard) — and the deliberate Phase 12 decision to NOT add a third reminder hook (recorded in `docs/decisions/015-developer-internals-docs.md`, lands in Phase 12 Plan 05). +Requirements this skill helps enforce: DOC-01 (index doc), DOC-02 (component docs), DOC-03 (reviewer agent registered), DOC-04 (skill exists), DOC-05 (top-level discoverability), DOC-06 (no new hook), DOC-07 (ADR captures the design). +``` + +**`## When to use this skill`** — bulleted list following the catalog-schema pattern ("Use when the task touches any file under:" lede, then bullets): + +```markdown +## When to use this skill + +Use when the task touches any file under: + +- `plugin/bin/agentlinux-install` — installer entrypoint -> `docs/internals/installer.md`. +- `plugin/lib/*.sh` — shared bash helpers -> `docs/internals/nodejs-runtime.md` (PATH/as_user) or `installer.md` (logging/idempotency). +- `plugin/provisioner/*.sh` — ordered installer steps -> dispatch by step (see table below). +- `plugin/cli/src/**` — the registry CLI source -> `docs/internals/registry-cli.md`. +- `plugin/catalog/{schema,catalog}.json` — the catalog data model -> `docs/internals/catalog.md`. +- `plugin/catalog/agents/<name>/*` — per-agent recipes -> `docs/internals/<name>.md`. +- `packaging/curl-installer/install.sh` — the curl-pipe-bash entrypoint -> `docs/internals/installer.md`. + +Or when authoring or reviewing any file under `docs/internals/`. +``` + +**`## Why this exists`** — paragraph naming the requirement: + +```markdown +## Why this exists (DOC-02, AL-22) + +The `docs/internals/` tree is the project owner's 60-second answer to "what value does AgentLinux provide for surface X" (the AL-22 litmus question). It's the source of insight for blog posts, marketing emails, and the agentlinux.org landing page (CONTEXT §"Reuse signal"). For the docs to stay useful, they must stay in sync with the source — which means a contract for what each doc contains, a dispatch table mapping source paths to docs, and a reviewer (`dev-docs-auditor`) that checks the contract on relevant PRs. This skill owns all three. +``` + +**`## Per-component file structure (the four-part contract)`** — describe the four mandated H2s: + +```markdown +## Per-component file structure (the four-part contract) + +Every `docs/internals/<component>.md` has four mandatory H2 sections: + +1. `## The problem` — what a developer hits without AgentLinux when reaching for this surface. +2. `## What AgentLinux does` — the mechanics in product terms (not line-by-line code). +3. `## Value vs the naive approach` — the trade-off, written as a numbered list with **bold lead clause** items, excerpt-friendly for blog/marketing copy. +4. `## Related` — bulleted cross-links to sibling internals docs, top-level README, and (optionally) ADRs. + +Optional fifth section: `## Worked example` — a fenced shell session with realistic prompts and truncated output. Include only when prose alone leaves the mechanics ambiguous; drop when prose suffices. + +Tone: product-perspective, project-owner audience first, future contributor second. The opening lede (3-5 lines under the H1) sets the value proposition in plain prose before any H2. +``` + +**`## Source-path -> doc-path dispatch table`** — this is THE registry the reviewer reads: + +```markdown +## Source-path -> doc-path dispatch table + +The `dev-docs-auditor` reviewer reads this table to decide which component doc a source change implicates. + +| Source path glob | Component doc | +|---|---| +| `packaging/curl-installer/install.sh`, `plugin/bin/agentlinux-install` | `docs/internals/installer.md` | +| `plugin/provisioner/10-agent-user.sh` | `docs/internals/agent-user.md` | +| `plugin/provisioner/20-sudoers.sh` | `docs/internals/sudo-drop-in.md` | +| `plugin/provisioner/30-nodejs.sh`, `plugin/provisioner/40-path-wiring.sh`, `plugin/lib/as_user.sh` | `docs/internals/nodejs-runtime.md` | +| `plugin/catalog/agents/claude-code/*` | `docs/internals/claude-code.md` | +| `plugin/catalog/agents/gsd/*` | `docs/internals/gsd.md` | +| `plugin/catalog/agents/playwright-cli/*`, `plugin/catalog/agents/playwright/*` | `docs/internals/playwright.md` | +| `plugin/cli/src/**`, `plugin/provisioner/50-registry-cli.sh` | `docs/internals/registry-cli.md` | +| `plugin/catalog/schema.json`, `plugin/catalog/catalog.json` | `docs/internals/catalog.md` | +| `plugin/lib/log.sh`, `plugin/lib/idempotency.sh`, `plugin/lib/distro_detect.sh` | `docs/internals/installer.md` (shared installer infrastructure) | + +When a new top-level surface lands under `plugin/` (a new provisioner step, a new CLI command class, a new catalog backend), this table grows AND a new `docs/internals/<surface>.md` ships in the same PR. +``` + +**`## When to update`** — the change-triggering vs skip conditions: + +```markdown +## When to update + +**Update the matching component doc when:** + +- The source change alters observable behavior described in `## What AgentLinux does` (e.g. install path moves, default version changes, a flag is added or removed). +- The source change invalidates a claim in `## The problem` or `## Value vs the naive approach` (e.g. a new naive alternative appears, or an old one is no longer the dominant path). +- A new top-level surface lands — a new component doc ships in the same PR and the index TOC grows. + +**Skip docs update for:** + +- Pure refactors that don't change observable behavior (rename, extract function, reformat). +- Comment-only or typo-only changes. +- Whitespace / formatting-only diffs. +- Test-only changes that don't touch `plugin/` source paths. +- `.planning/`-only changes. +- `docs/`-only changes (covered by `technical-writer` and `fact-checker`). + +The `dev-docs-auditor` reviewer enforces both columns at review time. +``` + +**`## Product-perspective lens (the AL-22 litmus test)`** — paragraph naming the framing: + +```markdown +## Product-perspective lens (the AL-22 litmus test) + +The litmus question for every component doc is: *"What value does AgentLinux provide in installing GSD instead of using the GSD installation from npm directly?"* — generalised to the component at hand. The doc must answer it in <60 seconds for a project owner reading on first arrival. + +Concretely: + +- Lead with the value, not the implementation. "AgentLinux gives the agent its own user with its own npm prefix, so self-update Just Works" beats "AgentLinux runs `useradd agent --shell /bin/bash` and writes `~/.npmrc` with `prefix=$HOME/.npm-global`." +- Implementation detail belongs in `## What AgentLinux does` (still product-framed); never in the lede. +- Tool names (`Commander.js`, `ajv`, `bats`) are implementation; the value frame is the verb the user gets (`agentlinux install <name>`, "schema-validated catalog," "behavior-test contract"). Tool names may appear as supporting detail; they must not lead. +- The `## Value vs the naive approach` section is the most excerpt-heavy part of every doc — it lifts directly into blog posts and marketing copy. Keep it numbered, **bold lead clause** style. +``` + +**`## Why no new stop-hook (DOC-06)`** — paragraph documenting the deliberate decision: + +```markdown +## Why no new stop-hook (DOC-06) + +AgentLinux already has two reminder hooks (`.claude/hooks/review-reminder.sh` and `.claude/hooks/session-tracker-reminder.sh`), both wired per the ADR-010 2026-05-02 refinement (reminder hooks with a `stop_hook_active` one-shot guard are allowed; reviewer-invoking hooks remain rejected). + +Adding a third hook for docs/internals/ sync would multiply reminder noise without adding value: the existing `review-reminder.sh` already nudges Claude to run the review loop, and the review loop already routes plugin/ changes to the `dev-docs-auditor` per the CLAUDE.md "Review Loop" routing table. The dev-docs check rides inside the existing review loop; no new hook is needed. ADR-015 (lands in Phase 12 Plan 05) records this decision in full. +``` + +**`## Growth plan`** — phase-by-phase what unlocks (catalog-schema pattern): + +```markdown +## Growth plan + +- **Phase 12 (this phase):** Skill ships alongside the 9 initial component docs and the `dev-docs-auditor` reviewer. This skill carries the dispatch table and the four-section contract. +- **Future milestones — new components added under `plugin/`:** Each new top-level surface (a new provisioner step, a new CLI command class, a new catalog backend, a new agent in the catalog) ships its own `docs/internals/<surface>.md` in the same PR and adds a row to the dispatch table here. +- **Future milestones — if drift becomes a real problem:** The skill may absorb a stronger link discipline (e.g. mandated ADR cross-references in the Related footer). Currently out of scope per CONTEXT §"Deferred Ideas." +- **Future milestones — if the docs grow:** Consider a documentation site (mdBook, Docusaurus). Currently out of scope per CONTEXT §"Deferred Ideas" — markdown in the repo is sufficient for the project owner's stated goal. +``` + +**`## Related`** — bullet list footer (catalog-schema pattern): + +```markdown +## Related + +- `docs/internals/README.md` — the docs/internals/ index (DOC-01). +- `docs/internals/<component>.md` — the 9 component docs (DOC-02). +- ADRs: 010 (review loop via CLAUDE.md, refined 2026-05-02), 015 (developer internals docs — no new hook decision; lands in Plan 05). +- Subagents: `dev-docs-auditor` (the reviewer this skill backs). +- Sibling skills: `agentlinux-installer`, `behavior-test-contract`, `catalog-schema`, `qemu-harness`, `review`, `workspace-cleanup`. +- Top-level pointers: `CLAUDE.md` "Review Loop" section (where the reviewer is wired) and "Pointers" section (where this skill is enumerated). Both are updated in Phase 12 Plan 04. +``` + </action> + <verify> + <automated>test -f .claude/skills/dev-docs/SKILL.md && head -3 .claude/skills/dev-docs/SKILL.md | grep -qF 'name: dev-docs' && grep -q '^# dev-docs' .claude/skills/dev-docs/SKILL.md && grep -q '^## When to use this skill' .claude/skills/dev-docs/SKILL.md && grep -q '^## Why this exists' .claude/skills/dev-docs/SKILL.md && grep -q '^## Per-component file structure' .claude/skills/dev-docs/SKILL.md && grep -q '^## Source-path -> doc-path dispatch table' .claude/skills/dev-docs/SKILL.md && grep -q '^## When to update' .claude/skills/dev-docs/SKILL.md && grep -q '^## Product-perspective lens' .claude/skills/dev-docs/SKILL.md && grep -q '^## Why no new stop-hook' .claude/skills/dev-docs/SKILL.md && grep -q '^## Growth plan' .claude/skills/dev-docs/SKILL.md && grep -q '^## Related' .claude/skills/dev-docs/SKILL.md && grep -qF 'docs/internals/installer.md' .claude/skills/dev-docs/SKILL.md && grep -qF 'docs/internals/agent-user.md' .claude/skills/dev-docs/SKILL.md && grep -qF 'docs/internals/sudo-drop-in.md' .claude/skills/dev-docs/SKILL.md && grep -qF 'docs/internals/nodejs-runtime.md' .claude/skills/dev-docs/SKILL.md && grep -qF 'docs/internals/claude-code.md' .claude/skills/dev-docs/SKILL.md && grep -qF 'docs/internals/gsd.md' .claude/skills/dev-docs/SKILL.md && grep -qF 'docs/internals/playwright.md' .claude/skills/dev-docs/SKILL.md && grep -qF 'docs/internals/registry-cli.md' .claude/skills/dev-docs/SKILL.md && grep -qF 'docs/internals/catalog.md' .claude/skills/dev-docs/SKILL.md && grep -qE 'ADR-?010|review-reminder' .claude/skills/dev-docs/SKILL.md && ! grep -q '^tools:' .claude/skills/dev-docs/SKILL.md && ! test -f .claude/hooks/dev-docs-reminder.sh</automated> + </verify> + <acceptance_criteria> + - File `.claude/skills/dev-docs/SKILL.md` exists. + - Frontmatter has `name: dev-docs` and a `description:` field; does NOT have a `tools:` field (skills are not subagents per PATTERNS.md §"Frontmatter discipline"). + - H1 starts with `# dev-docs`. + - All nine mandated H2s present: `## When to use this skill`, `## Why this exists`, `## Per-component file structure`, `## Source-path -> doc-path dispatch table`, `## When to update`, `## Product-perspective lens`, `## Why no new stop-hook`, `## Growth plan`, `## Related`. + - The `## Source-path -> doc-path dispatch table` mentions all 9 component doc paths (`docs/internals/{installer, agent-user, sudo-drop-in, nodejs-runtime, claude-code, gsd, playwright, registry-cli, catalog}.md`). + - The `## Why no new stop-hook` section references ADR-010 (or `010-review-loop-via-claude-md`) and the existing `review-reminder` hook. + - No file under `.claude/hooks/dev-docs-reminder.sh` exists (verified by `! test -f .claude/hooks/dev-docs-reminder.sh`). + </acceptance_criteria> + <done>Skill file committed; frontmatter validates shape (name, description, no tools); all required H2s present; dispatch table references all 9 component docs; no new hook file created.</done> +</task> + +</tasks> + +<verification> +After all tasks complete: + +```bash +# Both files exist +test -f .claude/agents/dev-docs-auditor.md +test -f .claude/skills/dev-docs/SKILL.md + +# Reviewer is read-only +grep -E '^tools:' .claude/agents/dev-docs-auditor.md | grep -qE 'Read, Grep, Glob, Bash' +! grep -E '^tools:' .claude/agents/dev-docs-auditor.md | grep -qE '\b(Write|Edit)\b' + +# No new hook file was created +! test -f .claude/hooks/dev-docs-reminder.sh + +# Skill cross-references the reviewer (and vice-versa) +grep -qF 'dev-docs-auditor' .claude/skills/dev-docs/SKILL.md +grep -qF '.claude/skills/dev-docs' .claude/agents/dev-docs-auditor.md +``` +</verification> + +<success_criteria> +- `.claude/agents/dev-docs-auditor.md` exists with read-only tool whitelist and the five mandated H2 sections. +- `.claude/skills/dev-docs/SKILL.md` exists with the nine mandated H2 sections, including the source-path -> doc-path dispatch table covering all 9 component docs. +- No new hook file is created; `.claude/settings.json` is NOT modified by this plan. +- The reviewer references the skill; the skill references the reviewer. +- The skill's `## Why no new stop-hook` section explicitly cites ADR-010 and the existing review-reminder hook to document the deliberate decision. +</success_criteria> + +<output> +After completion, create `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-03-SUMMARY.md` per the GSD summary template. +</output> diff --git a/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-03-SUMMARY.md b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-03-SUMMARY.md new file mode 100644 index 0000000..867db80 --- /dev/null +++ b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-03-SUMMARY.md @@ -0,0 +1,146 @@ +--- +phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 +plan: 03 +subsystem: docs-tooling +tags: [reviewer-agent, skill, docs-internals, review-loop, dev-docs-auditor] + +# Dependency graph +requires: + - phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 + provides: docs/internals/ tree (9 component docs + README index from 12-01) and the 9 component docs themselves (12-02). The reviewer's dispatch table maps source paths to those exact 9 docs. +provides: + - Read-only reviewer agent .claude/agents/dev-docs-auditor.md that flags missing or stale docs/internals/<component>.md updates when plugin/ source changes + - Project-scoped skill .claude/skills/dev-docs/SKILL.md documenting the four-section docs contract, the source-path -> doc-path dispatch table, the AL-22 product-perspective lens, and the deliberate decision NOT to add a third reminder hook +affects: + - 12-04 (CLAUDE.md wiring — adds dev-docs-auditor to the Review Loop routing table and dev-docs to the Pointers list) + - 12-05 (ADR-015 — captures the no-new-hook decision this skill body cites in its `## Why no new stop-hook` section) + - All future phases that touch plugin/bin/, plugin/lib/, plugin/provisioner/, plugin/cli/src/, plugin/catalog/, packaging/curl-installer/ — the dev-docs-auditor reviewer rides inside the existing review loop on those changes + +# Tech tracking +tech-stack: + added: [] # Markdown only; no new libraries or tooling. + patterns: + - "Reviewer + skill duo: a read-only reviewer agent consumes a sibling skill's contract at decision time (mirrors catalog-auditor + catalog-schema)" + - "Source-path -> doc-path dispatch table as the single registry the reviewer reads" + - "Deliberate no-new-hook stance: documented in skill body, ADR-015 will capture it; rides inside existing review-reminder.sh + review loop" + +key-files: + created: + - ".claude/agents/dev-docs-auditor.md (75 lines — read-only reviewer)" + - ".claude/skills/dev-docs/SKILL.md (113 lines — docs/internals/ contract)" + modified: [] + +key-decisions: + - "Reviewer is read-only (Read, Grep, Glob, Bash) — same shape as the six existing reviewers; never Write/Edit" + - "Reviewer omits ## Exit behavior — it does NOT gate phase close; staleness is a flag, not a release blocker" + - "Skill carries the source-path -> doc-path dispatch table — the reviewer reads it at decision time" + - "No new stop-hook (DOC-06) — embed the docs check inside the existing review loop; ADR-015 captures rationale in Plan 05" + +patterns-established: + - "Reviewer body H2 spine: `## When to spawn` / `## When NOT to spawn` / `## What to look for` / `## Common gotchas (AgentLinux-specific)` / `## Output format`" + - "Skill body H2 spine: `## When to use this skill` / `## Why this exists` / `## Per-component file structure` / `## Source-path -> doc-path dispatch table` / `## When to update` / `## Product-perspective lens` / `## Why no new stop-hook` / `## Growth plan` / `## Related`" + - "Output format closing motto: `Main agent triages.` (matches catalog-auditor + bash-engineer convention)" + - "Frontmatter discipline: kebab-case `name:` matching filename slug; reviewer description <=400 chars and includes concrete path globs; skill description follows `Use when X. Documents Y. <key rule>. Grows <when>.` shape" + +requirements-completed: [DOC-03, DOC-04, DOC-06] + +# Metrics +duration: ~10min +completed: 2026-05-10 +--- + +# Phase 12 Plan 03: docs/internals/ maintenance tooling Summary + +**Read-only dev-docs-auditor reviewer + dev-docs skill — embed docs/internals/ sync inside the existing review loop; no new stop-hook.** + +## Performance + +- **Duration:** ~10 min (active execution) +- **Started:** 2026-05-10T06:06:01Z +- **Completed:** 2026-05-10T08:47:02Z (wall-clock includes idle time between tool calls) +- **Tasks:** 2 / 2 +- **Files modified:** 0 +- **Files created:** 2 + +## Accomplishments + +- Shipped `.claude/agents/dev-docs-auditor.md` — 75-line read-only reviewer with frontmatter description (347 chars, under the 400-char gate), tools whitelist `Read, Grep, Glob, Bash`, and the five mandated H2s (`## When to spawn`, `## When NOT to spawn`, `## What to look for`, `## Common gotchas (AgentLinux-specific)`, `## Output format`). Closes with `Main agent triages.` per the catalog-auditor convention. No `## Exit behavior` — this reviewer does not gate phase close. +- Shipped `.claude/skills/dev-docs/SKILL.md` — 113-line skill with the nine mandated H2s including the source-path -> doc-path dispatch table that lists all 9 component docs (`installer.md`, `agent-user.md`, `sudo-drop-in.md`, `nodejs-runtime.md`, `claude-code.md`, `gsd.md`, `playwright.md`, `registry-cli.md`, `catalog.md`). Documents the four-section per-component contract, the AL-22 litmus test, the when-to-update / skip-condition matrix, and the deliberate `## Why no new stop-hook (DOC-06)` decision. +- Mutual cross-link: reviewer body cites `.claude/skills/dev-docs/SKILL.md` (in the `## What to look for` rubric lede); skill `## Related` footer cites `dev-docs-auditor`. +- No new file under `.claude/hooks/`, no edit to `.claude/settings.json` — the reviewer rides inside the existing review loop per CLAUDE.md "Review Loop" routing (wired in Plan 04). + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Write .claude/agents/dev-docs-auditor.md** — `6891a5f` (feat) +2. **Task 2: Write .claude/skills/dev-docs/SKILL.md** — `191cc21` (feat) + +**Plan metadata:** TBD (this SUMMARY + STATE/ROADMAP/REQUIREMENTS updates land in the final docs commit) + +## Files Created/Modified + +- `.claude/agents/dev-docs-auditor.md` (created, 75 lines) — Read-only reviewer agent. Triggered on changes under `plugin/bin/`, `plugin/lib/`, `plugin/provisioner/`, `plugin/cli/src/`, `plugin/catalog/`, `packaging/curl-installer/`. Verifies the matching `docs/internals/<component>.md` is still accurate; flags missing component docs, stale claims, source-line deep links, TOC drift in `docs/internals/README.md`, and product-perspective drift toward implementation detail. Does NOT gate phase close. +- `.claude/skills/dev-docs/SKILL.md` (created, 113 lines) — Skill that documents the docs contract. Carries the source-path -> doc-path dispatch table that the reviewer reads at decision time. Records the four-section per-component contract (`## The problem` / `## What AgentLinux does` / `## Value vs the naive approach` / `## Related`), the AL-22 litmus test, the when-to-update / skip-condition matrix, and the deliberate decision NOT to add a third reminder hook (DOC-06; ADR-015 captures rationale in Plan 05). + +## Decisions Made + +None beyond what the plan and CONTEXT.md already specified. Followed the analog patterns verbatim: + +- Reviewer copied the catalog-auditor.md spine (frontmatter shape, opener pattern, the five H2s, the `Main agent triages.` closer). +- Skill copied the catalog-schema/SKILL.md spine (frontmatter shape, status block + cross-link header, H2 sequence, growth plan, Related footer). +- Used the exact reviewer description string the plan provided verbatim (347 chars, under the 400-char gate). +- Used the exact dispatch table the plan + CONTEXT.md specified (9 component-doc rows + a tenth entry routing `plugin/lib/log.sh` / `idempotency.sh` / `distro_detect.sh` to `installer.md` as shared installer infrastructure). + +## Deviations from Plan + +None — plan executed exactly as written. + +The plan provided extensive prescriptive guidance (verbatim frontmatter, H1 line, opener paragraph, full bullet lists for every H2 section). I followed the prescription faithfully. No Rule 1 / Rule 2 / Rule 3 auto-fixes were necessary: no bugs were introduced (the artifacts are markdown-only docs with no executable surface), no missing critical functionality (the read-only `tools:` line is explicit; no security or correctness gap to backfill), and nothing blocked task execution. + +The pre-existing modifications in the working tree at session start (`.planning/config.json`, `12-03-PLAN.md`, `12-04-PLAN.md`, `12-05-PLAN.md`, `docs/audits/v0.4.0/PUB-04-release-notes.md`) were left untouched per the scope-boundary rule (out-of-scope to this plan). + +## Issues Encountered + +None. + +## User Setup Required + +None — no external service configuration required. Both files are project-scoped reference material loaded by Claude Code at session start. + +## Self-Check: PASSED + +Created files exist: + +- FOUND: `.claude/agents/dev-docs-auditor.md` +- FOUND: `.claude/skills/dev-docs/SKILL.md` + +Commits exist: + +- FOUND: `6891a5f` (feat(12-03): add dev-docs-auditor reviewer agent) +- FOUND: `191cc21` (feat(12-03): add dev-docs skill documenting docs/internals/ contract) + +Plan-level verification (per plan's `<verification>` block): + +- `test -f .claude/agents/dev-docs-auditor.md` PASS +- `test -f .claude/skills/dev-docs/SKILL.md` PASS +- Reviewer `tools:` line is read-only (`Read, Grep, Glob, Bash`); no `Write` / `Edit` PASS +- No `.claude/hooks/dev-docs-reminder.sh` exists PASS +- Skill cross-references `dev-docs-auditor` and reviewer cross-references `.claude/skills/dev-docs` PASS +- Reviewer description length: 347 chars (≤ 400) PASS +- All five reviewer H2s present (`When to spawn`, `When NOT to spawn`, `What to look for`, `Common gotchas`, `Output format`) PASS +- All nine skill H2s present (`When to use this skill`, `Why this exists`, `Per-component file structure`, `Source-path -> doc-path dispatch table`, `When to update`, `Product-perspective lens`, `Why no new stop-hook`, `Growth plan`, `Related`) PASS +- Skill dispatch table mentions all 9 component doc paths PASS +- Skill frontmatter has `name:` + `description:`, no `tools:` PASS +- Reviewer omits `## Exit behavior` PASS +- `.claude/settings.json` unchanged (last touched by unrelated commit a812a02) PASS + +## Next Phase Readiness + +- Plan 12-04 (CLAUDE.md wiring) can now ground its review-loop routing table edits on `dev-docs-auditor` (the agent file exists at the canonical path the routing entry will reference) and add `.claude/skills/dev-docs/` to the `## Pointers` skill enumeration. +- Plan 12-05 (ADR-015 — developer internals docs) can ground its "no new hook" rationale on the skill's `## Why no new stop-hook (DOC-06)` body and the actual reviewer file shipping the read-only tools line. +- The dev-docs-auditor will be invoked for the first time when a future PR touches `plugin/`-rooted source — the existing `review-reminder.sh` Stop-hook continues to nudge the review loop; no new orchestration is required. + +--- +*Phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22* +*Completed: 2026-05-10* diff --git a/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-04-PLAN.md b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-04-PLAN.md new file mode 100644 index 0000000..8d5e50c --- /dev/null +++ b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-04-PLAN.md @@ -0,0 +1,313 @@ +--- +phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 +plan: 04 +type: execute +wave: 2 +depends_on: [12-01, 12-02, 12-03] +files_modified: + - CLAUDE.md + - README.md +autonomous: true +requirements: [DOC-03, DOC-05] + +must_haves: + truths: + - "CLAUDE.md Review Loop reviewer-by-file-type table extends Bash, TS/JS, and Catalog recipes rows with dev-docs-auditor" + - "CLAUDE.md Pointers section enumerates .claude/skills/dev-docs/ alongside the existing skills" + - "Top-level README.md gains a Why AgentLinux concepts section linking docs/internals/" + - "Top-level README.md Links section gains an Internals (developer docs) row pointing at docs/internals/" + artifacts: + - path: "CLAUDE.md" + provides: "Project instructions extended to register dev-docs-auditor in the Review Loop and dev-docs/ in Pointers" + contains: "dev-docs-auditor" + - path: "README.md" + provides: "Top-level README extended with discoverability into docs/internals/" + contains: "docs/internals" + key_links: + - from: "CLAUDE.md" + to: "dev-docs-auditor reviewer agent" + via: "Review Loop bullet entry" + pattern: "dev-docs-auditor" + - from: "CLAUDE.md" + to: ".claude/skills/dev-docs/" + via: "Pointers skills enumeration" + pattern: "\\.claude/skills/dev-docs" + - from: "README.md" + to: "docs/internals/" + via: "Why AgentLinux concepts section markdown link + Links section row" + pattern: "docs/internals" +--- + +<objective> +Wire the Phase 12 outputs into the project's two top-level discovery surfaces: + +1. `CLAUDE.md` — register `dev-docs-auditor` in the existing "Review Loop" reviewer-by-file-type table (extending the Bash, TS/JS, and Catalog recipes rows — NOT adding a new "Internal docs" row, per CONTEXT.md §"CLAUDE.md wiring"); and enumerate `.claude/skills/dev-docs/` in the "Pointers" skills bullet alongside the existing five skills. +2. `README.md` (top-level) — add a "Why AgentLinux — concepts" section linking `docs/internals/` so first-time visitors can find the conceptual story; add an "Internals (developer docs)" row to the existing "## Links" section. + +Purpose: Make the new reviewer agent and the new docs tree discoverable from the two surfaces a contributor or curious visitor first lands on. +Output: 2 modified files (CLAUDE.md, README.md). +</objective> + +<execution_context> +@$HOME/.claude/get-shit-done/workflows/execute-plan.md +@$HOME/.claude/get-shit-done/templates/summary.md +</execution_context> + +<context> +@.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md +@.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-PATTERNS.md +@CLAUDE.md +@README.md + +<interfaces> +<!-- Current CLAUDE.md "Review Loop" table (CLAUDE.md lines 53-59 today): --> + +```markdown +Reviewers applied by file type: + +- Bash → `bash-engineer`, `security-engineer`, `qa-engineer` +- TS/JS → `node-engineer`, `security-engineer`, `qa-engineer` +- Bats → `qa-engineer`, `behavior-coverage-auditor` +- Catalog recipes → `catalog-auditor`, `security-engineer` +- Docs → `technical-writer`, `fact-checker` +``` + +Target after this plan (per CONTEXT.md §"CLAUDE.md wiring" + PATTERNS.md §"Pattern to apply"): + +```markdown +Reviewers applied by file type: + +- Bash → `bash-engineer`, `security-engineer`, `qa-engineer`, `dev-docs-auditor` +- TS/JS → `node-engineer`, `security-engineer`, `qa-engineer`, `dev-docs-auditor` +- Bats → `qa-engineer`, `behavior-coverage-auditor` +- Catalog recipes → `catalog-auditor`, `security-engineer`, `dev-docs-auditor` +- Docs → `technical-writer`, `fact-checker` +``` + +(Bats and Docs rows unchanged — bats has no internals doc; docs reviewers already cover docs surface.) + +<!-- Current CLAUDE.md "Pointers" skills bullet (CLAUDE.md lines 91-93 today): --> + +```markdown +- Skills (arrive Plan 01-04): `.claude/skills/agentlinux-installer/`, + `.claude/skills/behavior-test-contract/`, `.claude/skills/catalog-schema/`, + `.claude/skills/qemu-harness/`, `.claude/skills/review/` +``` + +Target — drop the stale "(arrive Plan 01-04)" parenthetical (the skills shipped long ago) and enumerate dev-docs: + +```markdown +- Skills: `.claude/skills/agentlinux-installer/`, + `.claude/skills/behavior-test-contract/`, `.claude/skills/catalog-schema/`, + `.claude/skills/qemu-harness/`, `.claude/skills/review/`, + `.claude/skills/workspace-cleanup/`, `.claude/skills/dev-docs/` +``` + +(`.claude/skills/workspace-cleanup/` already exists in the filesystem per the skills directory listing — including it here aligns the Pointers list with on-disk reality.) + +<!-- Current README.md sections that change (per PATTERNS.md §"README.md (modify — top-level)"): --> + +`## Stability model` (lines 67-83) — unchanged in this plan; the new section goes ABOVE it so the conceptual story flows install -> verify -> uninstall -> **why** (internals) -> stability model -> escape hatches. + +`## Links` (lines 136-143) — gains one row: `- **Internals (developer docs):** [docs/internals/](docs/internals/)`. Place adjacent to "Architecture decisions" since both are repo-internal reference material. + +Hard constraints: +- Use `Edit` for surgical line-range modifications. Do NOT rewrite the whole file with `Write` — both CLAUDE.md and README.md have other content this plan doesn't touch. +- The Review Loop bullet shape MUST be `- <file-type> → <comma-separated reviewer list>`. The arrow character is the Unicode `→` (U+2192), not `->` — match the existing rows. +- The new README "Why AgentLinux — concepts" section header is the implementer's call per CONTEXT.md §"Claude's Discretion." Suggested: `## Why AgentLinux — concepts`. Other reasonable variants accepted (e.g. `## What's inside (concepts)`, `## Concepts`). +</interfaces> +</context> + +<tasks> + +<task type="auto"> + <name>Task 1: Update CLAUDE.md — extend Review Loop table + Pointers skills enumeration</name> + <read_first> + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md (the authoritative spec for CLAUDE.md wiring) + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-PATTERNS.md (§"CLAUDE.md (modify)" — exact target rows) + - CLAUDE.md (the file being modified; read in full to confirm current line numbers for Edit operations) + - .claude/agents/dev-docs-auditor.md (just-written by Plan 03 — confirm the reviewer name and the exact triggering paths so this plan's wiring matches) + - .claude/skills/dev-docs/SKILL.md (just-written by Plan 03 — confirm the skill name) + </read_first> + <files>CLAUDE.md</files> + <action> +Make two surgical edits to `CLAUDE.md` using the Edit tool: + +**Edit 1 — extend the Review Loop reviewer-by-file-type bullet list:** + +Find the block (currently CLAUDE.md lines 55-59): + +``` +- Bash → `bash-engineer`, `security-engineer`, `qa-engineer` +- TS/JS → `node-engineer`, `security-engineer`, `qa-engineer` +- Bats → `qa-engineer`, `behavior-coverage-auditor` +- Catalog recipes → `catalog-auditor`, `security-engineer` +- Docs → `technical-writer`, `fact-checker` +``` + +Replace with: + +``` +- Bash → `bash-engineer`, `security-engineer`, `qa-engineer`, `dev-docs-auditor` +- TS/JS → `node-engineer`, `security-engineer`, `qa-engineer`, `dev-docs-auditor` +- Bats → `qa-engineer`, `behavior-coverage-auditor` +- Catalog recipes → `catalog-auditor`, `security-engineer`, `dev-docs-auditor` +- Docs → `technical-writer`, `fact-checker` +``` + +(Three rows extended: Bash, TS/JS, Catalog recipes. Two rows unchanged: Bats, Docs. Use the Unicode arrow `→` already in the file — copy-paste the existing rows and just append `, `dev-docs-auditor` to the appropriate three. Do NOT alter quoting, capitalization, or whitespace.) + +**Edit 2 — update the Pointers skills bullet (currently CLAUDE.md lines 91-93):** + +Find the block: + +``` +- Skills (arrive Plan 01-04): `.claude/skills/agentlinux-installer/`, + `.claude/skills/behavior-test-contract/`, `.claude/skills/catalog-schema/`, + `.claude/skills/qemu-harness/`, `.claude/skills/review/` +``` + +Replace with: + +``` +- Skills: `.claude/skills/agentlinux-installer/`, + `.claude/skills/behavior-test-contract/`, `.claude/skills/catalog-schema/`, + `.claude/skills/dev-docs/`, `.claude/skills/qemu-harness/`, + `.claude/skills/review/`, `.claude/skills/workspace-cleanup/` +``` + +(Drop the stale `(arrive Plan 01-04)` parenthetical — the skills shipped long ago. Add `dev-docs/` and `workspace-cleanup/` to the enumeration so the list matches `ls .claude/skills/`. Skills are listed alphabetically — confirm sort with `ls .claude/skills/`.) + +Do NOT add a new top-level CLAUDE.md section. Per CONTEXT.md §"CLAUDE.md wiring": "extend the existing Review Loop section's reviewer-by-file-type table with `dev-docs-auditor` for `plugin/` source changes. No new top-level CLAUDE.md section is required — keeping the wiring inside the existing Review Loop routing keeps the surface flat." + +Do NOT modify the "Last updated" footer line yet — Plan 05's AUDIT task closes the phase and will bump that line. + </action> + <verify> + <automated>grep -qE '^- Bash → .*`dev-docs-auditor`' CLAUDE.md && grep -qE '^- TS/JS → .*`dev-docs-auditor`' CLAUDE.md && grep -qE '^- Catalog recipes → .*`dev-docs-auditor`' CLAUDE.md && ! grep -qE '^- Bats →.*`dev-docs-auditor`' CLAUDE.md && ! grep -qE '^- Docs →.*`dev-docs-auditor`' CLAUDE.md && grep -qF '.claude/skills/dev-docs/' CLAUDE.md && grep -qF '.claude/skills/workspace-cleanup/' CLAUDE.md && ! grep -qF '(arrive Plan 01-04)' CLAUDE.md && [ "$(grep -c 'dev-docs-auditor' CLAUDE.md)" -ge 3 ]</automated> + </verify> + <acceptance_criteria> + - The Bash row in the Review Loop bullet list now ends with `, `dev-docs-auditor`` (matched by `grep -qE '^- Bash → .*\`dev-docs-auditor\`' CLAUDE.md`). + - The TS/JS row now ends with `, `dev-docs-auditor`` (same regex shape). + - The Catalog recipes row now ends with `, `dev-docs-auditor`` (same regex shape). + - The Bats row is UNCHANGED — no `dev-docs-auditor` on the Bats row. + - The Docs row is UNCHANGED — no `dev-docs-auditor` on the Docs row. + - `dev-docs-auditor` appears at least 3 times in CLAUDE.md (one per extended row). + - The Pointers skills bullet enumerates both `.claude/skills/dev-docs/` and `.claude/skills/workspace-cleanup/`. + - The stale parenthetical `(arrive Plan 01-04)` is removed from the Pointers skills bullet. + - No new top-level H2 section is added to CLAUDE.md. + - No edits to the "Critical Rules" or "Where Things Live" or "Session Tracking" or "Commands" sections. + </acceptance_criteria> + <done>CLAUDE.md committed with the two surgical edits; reviewer routed via existing Review Loop table; skill listed in Pointers.</done> +</task> + +<task type="auto"> + <name>Task 2: Update top-level README.md — add Why AgentLinux concepts section + Links row</name> + <read_first> + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-PATTERNS.md (§"README.md (modify — top-level)" — exact placement and shape) + - README.md (the file being modified; read in full to confirm current line numbers for Edit operations) + - docs/internals/README.md (just-written by Plan 01 — confirm the title and lede so this README's link description matches the destination) + </read_first> + <files>README.md</files> + <action> +Make two surgical edits to top-level `README.md` using the Edit tool. + +**Edit 1 — insert a new H2 section "Why AgentLinux — concepts" ABOVE the existing `## Stability model` section (currently README.md line 67):** + +The new section is short — 2-3 lines of prose plus a See-also line. Match the existing `## Stability model` section's shape (PATTERNS.md §"README.md (modify — top-level)"): + +```markdown +## Why AgentLinux — concepts + +Each AgentLinux surface — installer, agent user, sudo drop-in, Node.js runtime, +the agent catalog, the registry CLI, and the curated agent set (Claude Code, +GSD, Playwright) — solves a specific bug class that the naive `sudo npm +install -g` path leaves broken. The internals docs walk through one component +at a time: what the problem is, what AgentLinux does about it, and the value +vs. the naive approach. + +See [docs/internals/README.md](docs/internals/README.md) for the index — nine +short component docs, each answering "what value does AgentLinux provide +here" in under a minute. + +``` + +(Insert this block ABOVE `## Stability model`. Place exactly one blank line between the new section's closing line and the `## Stability model` H2. The conceptual story flow becomes: install -> verify -> uninstall -> **why (internals)** -> stability model -> escape hatches.) + +**Edit 2 — extend the `## Links` section (currently README.md lines 136-143):** + +Find the block: + +``` +- **Source + issues:** https://github.com/Roo4L/Agent-Linux +- **Releases:** https://github.com/Roo4L/Agent-Linux/releases +- **Architecture decisions:** [docs/decisions/](docs/decisions/) +- **Test harness spec:** [docs/HARNESS.md](docs/HARNESS.md) +- **Stability model (user-facing):** [docs/STABILITY-MODEL.md](docs/STABILITY-MODEL.md) +- **Landing page:** https://agentlinux.org +``` + +Replace with (insert one new row between "Architecture decisions" and "Test harness spec" — both are repo-internal reference material so this placement keeps related rows adjacent): + +``` +- **Source + issues:** https://github.com/Roo4L/Agent-Linux +- **Releases:** https://github.com/Roo4L/Agent-Linux/releases +- **Architecture decisions:** [docs/decisions/](docs/decisions/) +- **Internals (developer docs):** [docs/internals/](docs/internals/) +- **Test harness spec:** [docs/HARNESS.md](docs/HARNESS.md) +- **Stability model (user-facing):** [docs/STABILITY-MODEL.md](docs/STABILITY-MODEL.md) +- **Landing page:** https://agentlinux.org +``` + +(Match the bold-label-em-dash-bracketed-link shape of the surrounding rows verbatim.) + +Do NOT touch the badge cluster (lines 11-13), the install / verify / uninstall sections, the `## Stability model` body, the `## Requirements`, `## Security`, `## Contributing`, `## License`, or `## About` sections. + </action> + <verify> + <automated>grep -qE '^## Why AgentLinux' README.md && grep -qF 'docs/internals/README.md' README.md && grep -qF '**Internals (developer docs):**' README.md && grep -qF '[docs/internals/](docs/internals/)' README.md && awk '/^## Why AgentLinux/{a=NR} /^## Stability model/{b=NR} END{exit !(a>0 && b>0 && a<b)}' README.md && awk '/\*\*Architecture decisions:\*\*/{a=NR} /\*\*Internals \(developer docs\):\*\*/{b=NR} /\*\*Test harness spec:\*\*/{c=NR} END{exit !(a<b && b<c)}' README.md</automated> + </verify> + <acceptance_criteria> + - README.md gains a new H2 section starting with `## Why AgentLinux` (the suffix `— concepts` is preferred but accepted variants pass). + - The new section appears BEFORE the existing `## Stability model` section (verified by line-number ordering). + - The new section's body links `docs/internals/README.md` via a markdown link. + - The `## Links` section gains a new row `- **Internals (developer docs):** [docs/internals/](docs/internals/)`. + - The new Links row appears BETWEEN `**Architecture decisions:**` and `**Test harness spec:**` (verified by line-number ordering). + - No edits to the badge cluster, Install / Verify / Uninstall sections, Stability model body, Escape hatch, Requirements, Security, Contributing, License, or About sections. + </acceptance_criteria> + <done>README.md committed with the two surgical edits; new conceptual entry point linking docs/internals/; new Links row.</done> +</task> + +</tasks> + +<verification> +After all tasks complete: + +```bash +# CLAUDE.md edits land +grep -qE '^- Bash → .*`dev-docs-auditor`' CLAUDE.md +grep -qE '^- TS/JS → .*`dev-docs-auditor`' CLAUDE.md +grep -qE '^- Catalog recipes → .*`dev-docs-auditor`' CLAUDE.md +! grep -qE '^- Bats →.*`dev-docs-auditor`' CLAUDE.md +! grep -qE '^- Docs →.*`dev-docs-auditor`' CLAUDE.md +grep -qF '.claude/skills/dev-docs/' CLAUDE.md +! grep -qF '(arrive Plan 01-04)' CLAUDE.md + +# README.md edits land +grep -qE '^## Why AgentLinux' README.md +grep -qF 'docs/internals/README.md' README.md +grep -qF '**Internals (developer docs):**' README.md +``` +</verification> + +<success_criteria> +- CLAUDE.md "Review Loop" reviewer-by-file-type table extends Bash, TS/JS, and Catalog recipes rows with `dev-docs-auditor` (and only those three rows). +- CLAUDE.md "Pointers" skills enumeration includes `.claude/skills/dev-docs/` (and the previously-omitted `.claude/skills/workspace-cleanup/`). +- Top-level README.md has a "Why AgentLinux — concepts" section linking `docs/internals/`. +- Top-level README.md `## Links` section has an "Internals (developer docs)" row linking `docs/internals/`. +- No new top-level section in CLAUDE.md (per CONTEXT.md §"CLAUDE.md wiring" — keep the surface flat). +- No edits to `.claude/settings.json` or any file under `.claude/hooks/` (DOC-06 — no new stop-hook). +</success_criteria> + +<output> +After completion, create `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-04-SUMMARY.md` per the GSD summary template. +</output> diff --git a/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-04-SUMMARY.md b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-04-SUMMARY.md new file mode 100644 index 0000000..7d25bbd --- /dev/null +++ b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-04-SUMMARY.md @@ -0,0 +1,156 @@ +--- +phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 +plan: 04 +subsystem: docs +tags: [claude-md, readme, review-loop, dev-docs, discoverability] + +# Dependency graph +requires: + - phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 + provides: docs/internals/ tree (Plan 12-01), 9 component docs (Plan 12-02), dev-docs-auditor reviewer + dev-docs skill (Plan 12-03) +provides: + - "CLAUDE.md Review Loop reviewer-by-file-type table extended with dev-docs-auditor on Bash, TS/JS, and Catalog recipes rows" + - "CLAUDE.md Pointers skills enumeration includes dev-docs/ and workspace-cleanup/; stale '(arrive Plan 01-04)' parenthetical removed" + - "Top-level README.md gains a 'Why AgentLinux — concepts' H2 section linking docs/internals/README.md" + - "Top-level README.md ## Links section gains an 'Internals (developer docs)' row pointing at docs/internals/" +affects: [phase-12-plan-05-audit, future-plugin-edits-routed-to-dev-docs-auditor, blog-marketing-content-discovery] + +# Tech tracking +tech-stack: + added: [] + patterns: + - "CLAUDE.md Review Loop wiring: extend existing reviewer-by-file-type rows (NOT add a new row) when a reviewer's trigger globs overlap an established file-type bucket" + - "Top-level README.md conceptual entry point: short H2 lede + See line linking the deep-dive index, placed in the install -> verify -> uninstall -> why -> stability flow" + +key-files: + created: [] + modified: + - "CLAUDE.md" + - "README.md" + +key-decisions: + - "Wired dev-docs-auditor by extending Bash, TS/JS, and Catalog recipes rows rather than adding a new 'Internal docs' row, per CONTEXT.md §'CLAUDE.md wiring' — keeps the surface flat." + - "Bats and Docs rows left unchanged: bats has no internals doc; the Docs row already routes to technical-writer + fact-checker." + - "Skills enumeration aligned with on-disk reality: dropped the stale '(arrive Plan 01-04)' parenthetical and added both dev-docs/ and the previously-omitted workspace-cleanup/ in alphabetical order." + - "Placed the new 'Why AgentLinux — concepts' README section ABOVE Stability model so the conceptual story flows install -> verify -> uninstall -> why (internals) -> stability model -> escape hatches." + - "Placed the new Internals Links row between 'Architecture decisions' and 'Test harness spec' so repo-internal reference rows stay grouped." + +patterns-established: + - "Pattern: CLAUDE.md reviewer wiring is multi-row extension when a reviewer's triggers span existing file-type buckets, not single-row addition" + - "Pattern: README.md gains a short conceptual-entry-point section adjacent to the existing concept doc (Stability model) rather than burying internals links in a single Links row" + +requirements-completed: [DOC-03, DOC-05] + +# Metrics +duration: 2min +completed: 2026-05-10 +--- + +# Phase 12 Plan 04: CLAUDE.md + README.md wiring of dev-docs surfaces + +**Phase 12 outputs (dev-docs-auditor reviewer + dev-docs skill + docs/internals/ tree) wired into the two top-level discovery surfaces — the Review Loop routing table in CLAUDE.md and the conceptual-entry-point + Links section in README.md — so contributors and visitors land on the right surface from a flat read of the repo root.** + +## Performance + +- **Duration:** ~2 min +- **Started:** 2026-05-10T08:51:31Z +- **Completed:** 2026-05-10T08:53:10Z +- **Tasks:** 2 +- **Files modified:** 2 (CLAUDE.md, README.md) + +## Accomplishments + +- CLAUDE.md "Review Loop" reviewer-by-file-type table now routes Bash, TS/JS, and Catalog recipes changes through `dev-docs-auditor` alongside the existing reviewers. Bats and Docs rows correctly left unchanged (bats has no internals doc; docs reviewers already cover the docs surface). +- CLAUDE.md "Pointers" skills enumeration aligned with on-disk reality: includes `.claude/skills/dev-docs/` and the previously-omitted `.claude/skills/workspace-cleanup/`; the stale "(arrive Plan 01-04)" parenthetical is gone. +- README.md gains a "Why AgentLinux — concepts" H2 section above the existing "## Stability model" — 2-3 line lede framing the per-component story plus a See line into `docs/internals/README.md`. This is the conceptual entry point a first-time visitor lands on from the README's natural top-to-bottom read. +- README.md "## Links" section gains an "Internals (developer docs)" row, placed adjacent to "Architecture decisions" so repo-internal reference rows remain grouped. + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Update CLAUDE.md — extend Review Loop table + Pointers skills enumeration** — `1efb2a9` (docs) +2. **Task 2: Update top-level README.md — add Why AgentLinux concepts section + Links row** — `b148ef3` (docs) + +**Plan metadata commit:** to be created after this SUMMARY lands. + +## Files Created/Modified + +- `CLAUDE.md` — extended Review Loop reviewer-by-file-type bullet list (Bash + TS/JS + Catalog recipes rows append `dev-docs-auditor`); refreshed Pointers skills bullet (dropped `(arrive Plan 01-04)`, added `dev-docs/` and `workspace-cleanup/`). +- `README.md` — inserted new H2 section "Why AgentLinux — concepts" above "## Stability model" with a 2-3 line lede + See line linking `docs/internals/README.md`; inserted "Internals (developer docs)" row in `## Links` between "Architecture decisions" and "Test harness spec". + +## Decisions Made + +- **Multi-row reviewer wiring (not new row).** Per CONTEXT.md §"CLAUDE.md wiring," extended Bash + TS/JS + Catalog recipes rows because dev-docs-auditor's trigger paths (`plugin/bin/`, `plugin/lib/`, `plugin/provisioner/`, `plugin/cli/src/`, `plugin/catalog/`, `packaging/curl-installer/`) span those three buckets. Adding a new "Internal docs" row would have introduced a routing surface that does not match how the existing rows are organized (by file-type, not by reviewer audience). +- **Bats and Docs rows untouched.** Bats sources have no internals doc — the dispatch table in `.claude/skills/dev-docs/SKILL.md` does not include `tests/bats/`. Docs sources are already routed to `technical-writer` and `fact-checker`; routing them through `dev-docs-auditor` would be a redundant pass. +- **Skills list aligned with disk.** `ls .claude/skills/` shows seven directories; the Pointers bullet listed only five and tagged them with a long-stale "(arrive Plan 01-04)" parenthetical. Replaced both as a single edit so the contributor-visible truth matches reality. +- **Conceptual section placed above Stability model.** README natural flow becomes install -> verify -> uninstall -> **why (internals)** -> stability model -> escape hatches, mirroring how a first-time visitor would mentally bucket the content. +- **Links row adjacency.** Both "Architecture decisions" and "Internals (developer docs)" point into `docs/`; grouping them keeps repo-internal reference material visually together and separated from the external links (Source, Releases, Landing page). + +## Deviations from Plan + +None — plan executed exactly as written. The PLAN's two Edit specs landed verbatim: + +- Edit 1 / Task 1: Review Loop bullet list extended on three rows; the spec's Unicode `→` arrows preserved; quoting and bullet shape preserved. +- Edit 2 / Task 1: Pointers skills bullet replaced with the alphabetically-sorted enumeration the plan specified (agentlinux-installer, behavior-test-contract, catalog-schema, dev-docs, qemu-harness, review, workspace-cleanup); stale parenthetical dropped. +- Edit 1 / Task 2: New H2 inserted above "## Stability model" with the suggested header `## Why AgentLinux — concepts` and the suggested 2-3 line lede + See block. +- Edit 2 / Task 2: New "Internals (developer docs)" row inserted in `## Links` between "Architecture decisions" and "Test harness spec", matching the bold-label-em-dash-bracketed-link shape of surrounding rows. + +No Rule 1 / Rule 2 / Rule 3 auto-fixes triggered — the plan's edits were surgical, the read-before-edit reads on CLAUDE.md and README.md did not surface any pre-existing issues that intersected with the edit footprint. + +--- + +**Total deviations:** 0 +**Impact on plan:** None. + +## Issues Encountered + +None. + +The PreToolUse Edit hook's "READ-BEFORE-EDIT REMINDER" fired three times after successful edits — these are reminder messages from the runtime, not failures. CLAUDE.md and README.md were both read in this session before any edit was issued; all four edits applied successfully on the first attempt. + +## Verification + +Plan-level automated verification (PLAN §`<verification>`) all green: + +``` +PASS: Bash row +PASS: TS/JS row +PASS: Catalog row +PASS: Bats unchanged +PASS: Docs unchanged +PASS: dev-docs/ in skills +PASS: stale parenthetical removed +PASS: Why AgentLinux H2 +PASS: docs/internals/README.md link +PASS: Internals Links row +``` + +Per-task acceptance criteria all green: + +- Task 1: 9/9 PASS (Bash + TS/JS + Catalog rows extended; Bats + Docs rows unchanged; dev-docs/ + workspace-cleanup/ in skills; stale parenthetical removed; dev-docs-auditor appears 3 times in CLAUDE.md). +- Task 2: 6/6 PASS (Why AgentLinux H2 present; docs/internals/README.md linked from new section; Internals Links row present with correct shape; Why AgentLinux comes before Stability model; Internals row positioned between Architecture decisions and Test harness spec). + +Post-commit deletion check (`git diff --diff-filter=D HEAD~1 HEAD`): no deletions on either commit. + +## User Setup Required + +None - no external service configuration required. + +## Next Phase Readiness + +- DOC-03 (dev-docs-auditor reviewer registered in CLAUDE.md "Review Loop" routing table) — ✓ COMPLETE. +- DOC-05 (top-level discoverability into docs/internals/ via README.md) — ✓ COMPLETE. +- Phase 12 Plan 05 (AUDIT closure + ADR-015 + footer bump) is unblocked — both wiring surfaces are in place; the audit can now grep CLAUDE.md and README.md for the wiring evidence and ADR-015 can cite `docs/internals/`, the dev-docs-auditor agent, and the dev-docs skill as the three deliverables wired by this plan. + +## Self-Check: PASSED + +- CLAUDE.md modifications present at HEAD: YES (commit `1efb2a9`). +- README.md modifications present at HEAD: YES (commit `b148ef3`). +- Both commits exist in `git log --oneline`: YES. +- All plan-level verification gates green: YES (10/10). + +--- +*Phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22* +*Plan: 04* +*Completed: 2026-05-10* diff --git a/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-05-PLAN.md b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-05-PLAN.md new file mode 100644 index 0000000..fb16f2a --- /dev/null +++ b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-05-PLAN.md @@ -0,0 +1,469 @@ +--- +phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 +plan: 05 +type: execute +wave: 3 +depends_on: [12-01, 12-02, 12-03, 12-04] +files_modified: + - .planning/REQUIREMENTS.md + - docs/decisions/015-developer-internals-docs.md + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md +autonomous: true +requirements: [DOC-01, DOC-02, DOC-03, DOC-04, DOC-05, DOC-06, DOC-07] + +must_haves: + truths: + - "REQUIREMENTS.md gains a new DOC section enumerating DOC-01..DOC-07 with verifiable contracts" + - "ADR-015 records the design decision: embed dev-docs-auditor in the existing review loop; no new stop-hook" + - "12-AUDIT.md cites the evidence artifact for every DOC-XX requirement and emits GATE: GREEN" + artifacts: + - path: ".planning/REQUIREMENTS.md" + provides: "DOC-01..DOC-07 contract added under a Post-v0.4.0 Addendum H2; v0.4.0 traceability total stays at 21" + contains: "DOC-07" + - path: "docs/decisions/015-developer-internals-docs.md" + provides: "ADR recording the no-new-hook + embed-in-review-loop design" + contains: "## Decision" + min_lines: 30 + - path: ".planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md" + provides: "Phase 12 phase-close audit with evidence per DOC-XX and GATE: GREEN" + contains: "GATE: GREEN" + min_lines: 30 + key_links: + - from: "12-AUDIT.md" + to: "docs/decisions/015-developer-internals-docs.md" + via: "audit citation" + pattern: "015-developer-internals-docs" + - from: ".planning/REQUIREMENTS.md" + to: "docs/internals/README.md" + via: "DOC-01 verification reference" + pattern: "docs/internals/README" +--- + +<objective> +Close Phase 12. Three concerns: + +1. **REQUIREMENTS.md** — Phase 12 was added mid-milestone via `/gsd-add-phase` and shipped without DOC-XX requirement IDs. Add DOC-01..DOC-07 to `.planning/REQUIREMENTS.md` so the requirements coverage gate has something to check against (per the planning context note: "you may propose DOC-01..DOC-NN as part of the plan and add them to REQUIREMENTS.md as a plan task"). +2. **ADR-015** — Capture the design decision in `docs/decisions/015-developer-internals-docs.md`: embed `dev-docs-auditor` in the existing review loop; explicitly do NOT add a third stop-hook (per CONTEXT.md §"Maintenance Tooling" + ADR-010 refinement). This is what DOC-07 verifies. +3. **12-AUDIT.md** — Phase-close audit citing the evidence artifact for every DOC-XX requirement and emitting `GATE: GREEN` (the v0.4.0 phase-close convention from ROADMAP.md `## Notes on verification` + the existing 11-AUDIT.md, 10-AUDIT.md etc). + +(ROADMAP.md was already finalized by the planner during phase planning — Phase 12's Goal, Requirements list, and Plans bullet list are already in place; no ROADMAP.md edit is needed in this plan.) + +Purpose: Make Phase 12's outputs auditable against named requirements, capture the design decision so a future reader knows why there's no third hook, and emit the GREEN gate that closes the phase. +Output: 1 modified file (REQUIREMENTS.md), 2 new files (ADR-015 + 12-AUDIT.md). +</objective> + +<execution_context> +@$HOME/.claude/get-shit-done/workflows/execute-plan.md +@$HOME/.claude/get-shit-done/templates/summary.md +</execution_context> + +<context> +@.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md +@.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-PATTERNS.md +@.planning/REQUIREMENTS.md +@.planning/ROADMAP.md +@docs/decisions/000-template.md +@docs/decisions/010-review-loop-via-claude-md.md +@docs/decisions/014-secret-remediation-noop.md +@.planning/phases/11-public-flip/11-AUDIT.md + +<interfaces> +<!-- ADR template (docs/decisions/000-template.md): --> + +```markdown +# NNN: [Title] + +**Status:** Proposed | Accepted | Superseded by NNN +**Date:** YYYY-MM-DD + +## Context + +Why this decision was needed (2–3 sentences). + +## Decision + +What we decided (1–2 sentences). + +## Consequences + +What changes as a result; what trade-off was accepted. +``` + +<!-- ADR-014 (the closest analog — also a "this milestone" ADR with **Drives:** + **Companion to:** lines): --> + +```markdown +# 014: Secret remediation for v0.4.0 — no rotation required + +**Status:** Accepted +**Date:** 2026-04-26 +**Drives:** v0.4.0 SEC-04 +**Companion to:** SEC-01-gitleaks-report.md, ... + +## Context + +... + +## Decision + +**No rotation required. ...** + +## Consequences + +### Action items closed | Decision rule for future leaks | Pre-flip posture | etc. + +## References + +- ... +``` + +<!-- DOC-XX requirements format (mirroring v0.4.0 LIC/SEC/CLEAN/CIPUB/PUB style in REQUIREMENTS.md): --> + +```markdown +### Developer Documentation (DOC) — Phase 12 + +- [ ] **DOC-01**: <verifiable outcome with explicit evidence form> +- [ ] **DOC-02**: ... +``` + +(Mirror the existing prefix conventions exactly — `### <Category> (<PREFIX>) — Phase NN`, then `- [ ] **PREFIX-NN**: <one or two sentences naming the verifiable outcome>`.) + +<!-- 12-AUDIT.md format (mirror 11-AUDIT.md / 10-AUDIT.md from completed v0.4.0 phases): --> + +The audit format is documented in ROADMAP.md `## Notes on verification`: + +> The phase-close gate convention (TST-07-style) carries over: every requirement must close with a cited evidence artifact in its phase's AUDIT doc before the gate emits GREEN. + +The existing AUDIT files use this shape: + +```markdown +# Phase NN AUDIT — <Phase Name> + +**Phase status:** GATE: GREEN +**Closed:** YYYY-MM-DD +**Requirements covered:** PREFIX-01..PREFIX-NN + +## Evidence per requirement + +| REQ-ID | Verifiable contract | Evidence artifact | Status | +|---|---|---|---| +| PREFIX-01 | <one-line contract> | `<path/to/evidence>` | ✓ Closed | + +## Phase-close gate + +GATE: GREEN — all NN requirements evidenced. +``` + +<!-- ROADMAP.md Phase 12 entry (current state, lines 155-163): --> + +```markdown +### Phase 12: Developer documentation for installer, runtime, and CLI (AL-22) + +**Goal:** [To be planned] +**Requirements**: TBD +**Depends on:** Phase 11 +**Plans:** 0 plans + +Plans: +- [ ] TBD (run /gsd-plan-phase 12 to break down) +``` + +Target after this plan: + +```markdown +### Phase 12: Developer documentation for installer, runtime, and CLI (AL-22) + +**Goal:** A reader landing on the AgentLinux repo can find a 60-second answer to "what value does AgentLinux provide for surface X" for every component (installer, agent user, sudo drop-in, Node.js runtime, the agent catalog, the registry CLI, and the curated agent set: Claude Code, GSD, Playwright). The docs stay in sync with the source via a project-scoped reviewer (`dev-docs-auditor`) embedded in the existing review loop — no new stop-hook is added. +**Requirements**: DOC-01, DOC-02, DOC-03, DOC-04, DOC-05, DOC-06, DOC-07 +**Depends on:** Phase 11 +**Plans:** 5 plans + +Plans: +- [ ] 12-01-PLAN.md — docs/internals/ index + 4 install/runtime layer component docs (DOC-01, DOC-02) +- [ ] 12-02-PLAN.md — 5 agent + CLI/catalog component docs (DOC-02) +- [ ] 12-03-PLAN.md — dev-docs-auditor reviewer agent + dev-docs skill (DOC-03, DOC-04, DOC-06) +- [ ] 12-04-PLAN.md — CLAUDE.md Review Loop + Pointers wiring + top-level README.md discoverability (DOC-03, DOC-05) +- [ ] 12-05-PLAN.md — REQUIREMENTS.md DOC-XX entries + ADR-015 + Phase 12 AUDIT (DOC-01..DOC-07, phase-close) +``` + +REQUIREMENTS.md insertion point: the v0.4.0 REQUIREMENTS.md already enumerates LIC/SEC/CLEAN/CIPUB/PUB — DOC is a new category. Append a new `### Developer Documentation (DOC) — Phase 12` H3 section to REQUIREMENTS.md AFTER the existing PUB section (currently `### Public Visibility Flip & Smoke Test (PUB) — Phase 11`) and BEFORE `## Future Requirements`. Also update the `## REQ-ID Traceability` table to include the Phase 12 row, and update the Coverage check sentence (currently "21 requirements mapped to 5 phases") to "28 requirements mapped to 6 phases" (21 + 7 = 28; 5 + 1 = 6). +</interfaces> +</context> + +<tasks> + +<task type="auto"> + <name>Task 1: Add DOC-01..DOC-07 to REQUIREMENTS.md</name> + <read_first> + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md (the spec the DOC-XX requirements derive from) + - .planning/REQUIREMENTS.md (the file being modified — read in full to confirm the existing DOC-XX absence and the section ordering) + - .planning/ROADMAP.md (already-finalized reference — cite for the Phase 12 milestone-framing context that informs the REQUIREMENTS.md addendum qualifier) + - docs/internals/README.md (just-written by Plan 01 — DOC-01 references this file) + - .claude/agents/dev-docs-auditor.md (just-written by Plan 03 — DOC-03 references this file) + - .claude/skills/dev-docs/SKILL.md (just-written by Plan 03 — DOC-04 references this file) + - CLAUDE.md (just-edited by Plan 04 — DOC-03 and DOC-05 reference these edits) + - README.md (just-edited by Plan 04 — DOC-05 references these edits) + </read_first> + <files>.planning/REQUIREMENTS.md</files> + <action> +**Edit — `.planning/REQUIREMENTS.md`:** This edit adds DOC-01..DOC-07 to REQUIREMENTS.md as a *post-v0.4.0 addendum* — under a NEW H2 below the existing v0.4.0 sections. Do NOT merge DOC-XX into the existing v0.4.0 traceability table; the v0.4.0 milestone closed at commit `c8a2787` on 2026-05-02 with 21 requirements and that count must remain honest. + +The edit has three parts. Apply them in order. + +**Part A — insert a new H2 `## Post-v0.4.0 Addendum Requirements` between the existing `### Public Visibility Flip & Smoke Test (PUB) — Phase 11` block (ends around line 55) and the existing `## Future Requirements (not in this milestone)` H2 (starts around line 57).** + +The new H2 wraps a short framing paragraph plus the DOC H3. Use this exact block: + +```markdown +## Post-v0.4.0 Addendum Requirements + +The v0.4.0 milestone closed at commit `c8a2787` on 2026-05-02 with 21 requirements (LIC/SEC/CLEAN/CIPUB/PUB). The following requirement set is a *post-v0.4.0 addendum* added under issue AL-22 ("Create documentation on what AgentLinux does") — captured in this file because REQUIREMENTS.md is still the active per-project requirements doc, but tracked separately so the v0.4.0 milestone gate count stays honest. + +### Developer Documentation (DOC) — Phase 12 + +- [ ] **DOC-01**: A `docs/internals/README.md` exists at the documented location, opens with a one-paragraph "What AgentLinux is" lede in product voice, and contains a `## Components` H2 with a TOC linking to all nine component docs (installer, agent-user, sudo-drop-in, nodejs-runtime, claude-code, gsd, playwright, registry-cli, catalog). Verified by file-existence check + grep for the nine `(*.md)` link targets. +- [ ] **DOC-02**: Nine component docs exist under `docs/internals/` — one per surface listed in the index. Each follows the four-section structural contract: `## The problem` → `## What AgentLinux does` → `## Value vs the naive approach` → `## Related`. Each `## Value vs the naive approach` is a numbered list with **bold lead clause** items (excerpt-friendly per the AL-22 reuse-as-blog-source signal). No source-line deep links anywhere in `docs/internals/` (per the dev-docs depth contract). Verified by grep across the nine files. +- [ ] **DOC-03**: A new project-scoped reviewer agent `.claude/agents/dev-docs-auditor.md` exists with read-only tools (`tools: Read, Grep, Glob, Bash`) and a frontmatter description triggering it on changes under `plugin/bin/`, `plugin/lib/`, `plugin/provisioner/`, `plugin/cli/src/`, `plugin/catalog/`, and `packaging/curl-installer/`. The reviewer is registered in CLAUDE.md "Review Loop" by extending the Bash, TS/JS, and Catalog recipes rows of the reviewer-by-file-type table. Verified by file existence + `grep -E '^- Bash → .*dev-docs-auditor' CLAUDE.md` and equivalents for the other two extended rows. +- [ ] **DOC-04**: A new project-scoped skill `.claude/skills/dev-docs/SKILL.md` exists, documenting the docs/internals/ contract (per-component four-section structure, source-path → doc-path dispatch table, when to update, product-perspective lens, and the explicit decision to not add a stop-hook). The skill is enumerated in CLAUDE.md "Pointers" alongside the other project-scoped skills. Verified by file existence + grep for the dispatch-table entries covering all 9 component docs. +- [ ] **DOC-05**: Top-level discoverability — top-level `README.md` gains a "Why AgentLinux — concepts" H2 section linking `docs/internals/README.md`, AND a `## Links` row labelled `**Internals (developer docs):**` linking `docs/internals/`. Verified by grep across `README.md`. +- [ ] **DOC-06**: No new stop-hook was added — `.claude/hooks/dev-docs-reminder.sh` does not exist; `.claude/settings.json` is unchanged across the Phase 12 commit range. The dev-docs sync check rides inside the existing `review-reminder.sh`-triggered review loop per the ADR-010 2026-05-02 refinement and per ADR-015 (DOC-07). Verified by `! test -f .claude/hooks/dev-docs-reminder.sh` and `git diff <phase-12-base>..HEAD -- .claude/settings.json | wc -l` returning 0. +- [ ] **DOC-07**: A new ADR `docs/decisions/015-developer-internals-docs.md` records the design decision behind Phase 12 — what `docs/internals/` is for, why a reviewer + skill instead of a hook, why a flat embed inside the existing Review Loop instead of a new top-level CLAUDE.md section. Status `Accepted`. Verified by file existence + `grep -q '^## Decision' docs/decisions/015-developer-internals-docs.md`. +``` + +**Part B — leave the existing `## REQ-ID Traceability` table UNCHANGED.** Do NOT add a Phase 12 row to it. Do NOT change `**Total v0.4.0** | | **21**`. Do NOT change the prose Coverage check line (`21 requirements mapped to 5 phases. Zero orphans.`). The v0.4.0 milestone count stays at 21, mapped to 5 phases. + +**Part C — append a new addendum traceability sub-section AFTER the existing Coverage check prose line and BEFORE the existing `## Verification Convention` H2.** + +The new sub-section is an H3 under `## REQ-ID Traceability` (not a new H2 — it's a continuation of the traceability concept, just for the addendum requirements). Insert this exact block: + +```markdown +### Post-v0.4.0 Addendum Traceability + +| Phase | Requirements | Count | +|-------|--------------|-------| +| 12 Developer Documentation (AL-22) | DOC-01, DOC-02, DOC-03, DOC-04, DOC-05, DOC-06, DOC-07 | 7 | +| **Total addendum** | | **7** | + +**Coverage check:** 7 addendum requirements mapped to 1 phase. Zero orphans. (v0.4.0 milestone total remains 21 requirements across 5 phases — see the table above.) +``` + +(The H3 sits inside the existing `## REQ-ID Traceability` H2; the next H2 — `## Verification Convention` — closes the traceability section as before.) + +After this edit, REQUIREMENTS.md has a clean separation: `## v0.4.0 Requirements` (LIC/SEC/CLEAN/CIPUB/PUB, 21 requirements, milestone-closed) and `## Post-v0.4.0 Addendum Requirements` (DOC, 7 requirements, AL-22). The `## REQ-ID Traceability` H2 contains both the original v0.4.0 table (unchanged) and a new H3 sub-section for the addendum. + + </action> + <verify> + <automated>grep -qE '^## Post-v0\.4\.0 Addendum Requirements' .planning/REQUIREMENTS.md && grep -qE '^### Developer Documentation \(DOC\) — Phase 12' .planning/REQUIREMENTS.md && for n in 01 02 03 04 05 06 07; do grep -qE "\*\*DOC-${n}\*\*" .planning/REQUIREMENTS.md || { echo "MISSING DOC-${n}"; exit 1; }; done && grep -qF '**Total v0.4.0** | | **21**' .planning/REQUIREMENTS.md && grep -qF '21 requirements mapped to 5 phases' .planning/REQUIREMENTS.md && grep -qE '^### Post-v0\.4\.0 Addendum Traceability' .planning/REQUIREMENTS.md && grep -qF '**Total addendum** | | **7**' .planning/REQUIREMENTS.md && grep -qF '7 addendum requirements mapped to 1 phase' .planning/REQUIREMENTS.md && ! grep -qF '12 Developer Documentation (post-v0.4.0 addendum)' .planning/REQUIREMENTS.md && ! grep -qF '**Total v0.4.0** | | **28**' .planning/REQUIREMENTS.md && ! grep -qF '28 requirements mapped to 6 phases' .planning/REQUIREMENTS.md</automated> + </verify> + <acceptance_criteria> + - REQUIREMENTS.md contains a new H2 `## Post-v0.4.0 Addendum Requirements` placed BETWEEN the last v0.4.0 H3 (`### Public Visibility Flip & Smoke Test (PUB) — Phase 11`) and the existing `## Future Requirements (not in this milestone)` H2. + - REQUIREMENTS.md contains the H3 `### Developer Documentation (DOC) — Phase 12` nested inside the new addendum H2. + - REQUIREMENTS.md contains all seven DOC-XX entries (DOC-01 through DOC-07), each with the verifiable contract specified in the action body. + - The existing `## REQ-ID Traceability` table is UNCHANGED — `**Total v0.4.0** | | **21**` remains, no Phase 12 row appears in it. + - The existing prose Coverage check line `21 requirements mapped to 5 phases. Zero orphans.` is UNCHANGED (not relabelled to 28 / 6 phases). + - REQUIREMENTS.md gains a new H3 `### Post-v0.4.0 Addendum Traceability` (inside the existing `## REQ-ID Traceability` H2, before the next H2 `## Verification Convention`) with its own one-row table totalling 7 and its own Coverage check sentence. + </acceptance_criteria> + <done>REQUIREMENTS.md committed; DOC-01..DOC-07 enumerated with verifiable contracts. Note: ROADMAP.md was already finalized by the planner; no edit needed here.</done> +</task> + +<task type="auto"> + <name>Task 2: Write ADR-015 (developer internals docs design) + 12-AUDIT.md (phase-close GREEN)</name> + <read_first> + - .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md (the design decisions ADR-015 records) + - docs/decisions/000-template.md (the canonical ADR template) + - docs/decisions/010-review-loop-via-claude-md.md (the ADR ADR-015 builds on — review-loop precedent + 2026-05-02 reminder-hook refinement) + - docs/decisions/014-secret-remediation-noop.md (the closest recent v0.4.0-era ADR analog — has **Drives:** + **Companion to:** lines and a richer Consequences section) + - .planning/REQUIREMENTS.md (just-edited by Task 1 — confirm DOC-01..DOC-07 contract for the AUDIT evidence rows) + - .planning/phases/11-public-flip/11-AUDIT.md (the most recent AUDIT analog from v0.4.0 — copy its phase-close gate format and evidence-table shape) + - docs/internals/README.md (just-written by Plan 01 — cited as DOC-01 evidence) + - .claude/agents/dev-docs-auditor.md (Plan 03 — DOC-03 evidence) + - .claude/skills/dev-docs/SKILL.md (Plan 03 — DOC-04 evidence) + - CLAUDE.md (Plan 04 — DOC-03 and DOC-05 evidence) + - README.md (Plan 04 — DOC-05 evidence) + </read_first> + <files>docs/decisions/015-developer-internals-docs.md, .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md</files> + <action> +Two new files. Use the Write tool for both. + +**File A — `docs/decisions/015-developer-internals-docs.md`** (target ~50-90 lines): + +Use this exact frontmatter and structure (mirrors ADR-014's shape — `**Drives:**` + `**Companion to:**` lines, then Context / Decision / Consequences): + +```markdown +# 015: Developer internals docs — embed in review loop, no new hook + +**Status:** Accepted +**Date:** 2026-05-09 +**Drives:** DOC-01, DOC-02, DOC-03, DOC-04, DOC-05, DOC-06, DOC-07 +**Companion to:** ADR-010 (review loop via CLAUDE.md, refined 2026-05-02) + +## Context + +AL-22 ("Create documentation on what AgentLinux does") asks for developer-facing internal documentation explaining what each AgentLinux component does and why — with a product-perspective lens. The litmus question is *"What value does AgentLinux provide in installing GSD instead of using the GSD installation from npm directly?"* The docs must give the project owner a 60-second answer per surface and double as raw material for blog posts, marketing emails, and the agentlinux.org landing page. + +Two adjacent decisions had to land alongside the docs themselves: + +1. **How to keep the docs in sync with the source.** Documentation that drifts is worse than no documentation — it actively misleads. The codebase already has a review loop (CLAUDE.md "Review Loop" instruction + `.claude/agents/<reviewer>.md` subagents + ADR-010's reminder-hook refinement) that catches plugin/ source changes; it needs to learn about docs/internals/ too. +2. **Whether to add a third stop-hook.** The codebase has two reminder hooks today — `.claude/hooks/review-reminder.sh` (review-loop nudge) and `.claude/hooks/session-tracker-reminder.sh` (Jira nudge), both wired per the ADR-010 2026-05-02 refinement. A naive solution to docs sync would be a third hook. The maintainer pushed back: a third hook multiplies reminder noise without adding value, because the existing review-reminder already triggers the review loop and the review loop already routes plugin/ changes to reviewers. + +## Decision + +**Embed `dev-docs-auditor` (a new project-scoped reviewer subagent) in the existing review loop. Do NOT add a third stop-hook.** + +Specifically: + +1. Ship `docs/internals/` — one index doc + nine per-component docs (installer, agent-user, sudo-drop-in, nodejs-runtime, claude-code, gsd, playwright, registry-cli, catalog). Each follows a four-section contract: problem → AgentLinux's answer → value vs the naive approach → related cross-links. No source-line deep links; ADR mentions in prose are optional. +2. Ship `.claude/agents/dev-docs-auditor.md` — a read-only reviewer (`tools: Read, Grep, Glob, Bash`) that consumes a new `.claude/skills/dev-docs/SKILL.md` skill (the source-path → doc-path dispatch table + the four-section contract). +3. Wire the reviewer into the existing CLAUDE.md "Review Loop" reviewer-by-file-type table by extending three existing rows (Bash, TS/JS, Catalog recipes) — NOT by adding a new "Internal docs" row. Keeping the wiring inside the existing routing keeps the surface flat. +4. Make `docs/internals/` discoverable from the top-level `README.md` (a "Why AgentLinux — concepts" section + a "## Links" row). +5. NO new file under `.claude/hooks/`. NO edit to `.claude/settings.json`. + +## Consequences + +### What changes + +- The review loop now flags missing or stale `docs/internals/<component>.md` updates whenever `plugin/bin/`, `plugin/lib/`, `plugin/provisioner/`, `plugin/cli/src/`, `plugin/catalog/`, or `packaging/curl-installer/` changes — without any new orchestration plumbing. +- The internals docs are explicitly *reference material*, not a release gate. The `dev-docs-auditor` does not gate phase close (no `## Exit behavior` section in its body); it documents drift for the main agent to triage. +- Skip conditions are explicit: pure refactors, comment-only changes, typo fixes, formatting-only diffs, `.planning/`-only changes, and tests-only changes do not require docs updates. + +### Why no third hook + +ADR-010's original 2026-04-18 critique — "subjective LLM review in a Stop hook wastes tokens" — applied to hooks that *spawn* reviewers. The 2026-05-02 refinement permits *reminder* hooks (one-shot via `stop_hook_active`, no reviewer spawn). A third reminder hook for docs sync was considered and rejected because: + +- The existing `review-reminder.sh` already nudges Claude to run the review loop. Once the review loop runs, the reviewer-by-file-type routing table already routes plugin/ changes through `dev-docs-auditor`. A second nudge for the same loop is redundant. +- Each reminder hook costs at most one extra "block + re-stop" round-trip per turn (per ADR-010 §"Refinement"). Two reminders cost two round-trips; three cost three. The cost is real even though small. +- Reminder noise has a usability cost too — Claude reads each reminder reason and decides whether to act. More reasons mean longer reminder text means more turns where the reminder is mostly skipped, which trains the loop to ignore reminders generally. +- The maintainer drew the line at "no third hook" explicitly. Two hooks is a deliberate stopping point, not an accident. + +### Why a flat extend, not a new CLAUDE.md section + +Adding a top-level CLAUDE.md H2 like `## Internal docs review` would split the review-routing surface into two places (the existing "Review Loop" table + the new section). Future contributors would have to read both to know which reviewers fire on which file types. Extending three existing rows keeps the routing in one place. + +### Reversibility + +If `docs/internals/` proves not worth the maintenance overhead, the unwind is small: + +- Delete `docs/internals/`. +- Remove `dev-docs-auditor` from the three CLAUDE.md "Review Loop" rows. +- Delete `.claude/agents/dev-docs-auditor.md` and `.claude/skills/dev-docs/`. +- Drop the README.md "Why AgentLinux — concepts" section + Links row. + +No hook to retract, no settings.json edit to revert. The reversibility cost is bounded by design. + +## References + +- ADR-010 — Review loop via CLAUDE.md (the precedent this ADR builds on; refined 2026-05-02 to permit reminder hooks with `stop_hook_active` guard). +- `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md` — the user-decisions context that drove this design. +- `docs/internals/README.md` — the index doc this ADR drives. +- `.claude/agents/dev-docs-auditor.md` — the reviewer this ADR drives. +- `.claude/skills/dev-docs/SKILL.md` — the skill this ADR drives. +``` + +**File B — `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md`** (target ~50-90 lines): + +Mirror the shape of `.planning/phases/11-public-flip/11-AUDIT.md` (read it first — it's the most recent v0.4.0 AUDIT analog). Header / phase-status block, evidence-per-requirement table with one row per DOC-XX, deviations section if any, phase-close gate verdict. + +Use this structure: + +```markdown +# Phase 12 AUDIT — Developer documentation for installer, runtime, and CLI (AL-22) + +**Phase status:** GATE: GREEN +**Closed:** 2026-05-09 +**Requirements covered:** DOC-01, DOC-02, DOC-03, DOC-04, DOC-05, DOC-06, DOC-07 +**Plans:** 12-01-PLAN.md, 12-02-PLAN.md, 12-03-PLAN.md, 12-04-PLAN.md, 12-05-PLAN.md +**Source spec:** AL-22 ("Create documentation on what AgentLinux does"), 12-CONTEXT.md (locked decisions) + +## Evidence per requirement + +| REQ-ID | Verifiable contract | Evidence artifact | Status | +|---|---|---|---| +| DOC-01 | `docs/internals/README.md` exists with What-AgentLinux-is lede + `## Components` TOC linking to all 9 component docs | `docs/internals/README.md` (Plan 12-01) | ✓ Closed | +| DOC-02 | 9 component docs under `docs/internals/`, each with the four-section spine and a numbered **bold lead clause** trade-off list | `docs/internals/{installer,agent-user,sudo-drop-in,nodejs-runtime,claude-code,gsd,playwright,registry-cli,catalog}.md` (Plans 12-01, 12-02) | ✓ Closed | +| DOC-03 | `dev-docs-auditor` reviewer registered in CLAUDE.md "Review Loop" table on Bash, TS/JS, Catalog recipes rows | `.claude/agents/dev-docs-auditor.md` (Plan 12-03) + `CLAUDE.md` Review Loop table (Plan 12-04) | ✓ Closed | +| DOC-04 | `dev-docs/SKILL.md` documents the four-section contract + dispatch table; enumerated in CLAUDE.md "Pointers" | `.claude/skills/dev-docs/SKILL.md` (Plan 12-03) + `CLAUDE.md` Pointers list (Plan 12-04) | ✓ Closed | +| DOC-05 | Top-level `README.md` "Why AgentLinux — concepts" section + `## Links` row link `docs/internals/` | `README.md` (Plan 12-04) | ✓ Closed | +| DOC-06 | No new stop-hook; `.claude/hooks/dev-docs-reminder.sh` does not exist; `.claude/settings.json` unchanged | `! test -f .claude/hooks/dev-docs-reminder.sh`; `git diff <phase-base>..HEAD -- .claude/settings.json` empty | ✓ Closed | +| DOC-07 | `docs/decisions/015-developer-internals-docs.md` records the design decision; status `Accepted` | `docs/decisions/015-developer-internals-docs.md` (this plan, Task 2) | ✓ Closed | + +## Deviations from PLAN + +(Fill in if the final shape differs from the plans — e.g. a component doc grew or shrank, a TOC slug changed. The expectation is "no significant deviations" but if any plan went off-script, document it here. Use `None.` if the plans landed verbatim.) + +## Phase-close gate + +GATE: GREEN — all 7 requirements evidenced. + +The Phase 12 outputs ride inside the existing v0.4.0 milestone release that shipped 2026-05-02 (`v0.3.1 — Open-Source Flip`, commit `c8a2787`). DOC-XX is therefore tracked as a **post-v0.4.0 addendum** in REQUIREMENTS.md — the milestone closed under PUB-XX; AL-22 documentation work is captured separately and does not reopen the milestone gate. + +## References + +- `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md` — locked user decisions +- `docs/decisions/015-developer-internals-docs.md` — design ADR (no new hook) +- `docs/decisions/010-review-loop-via-claude-md.md` — review-loop precedent (refined 2026-05-02) +- `.planning/REQUIREMENTS.md` §"Developer Documentation (DOC) — Phase 12" — DOC-01..DOC-07 contracts +``` + +(The "Deviations from PLAN" section is intentionally a stub for the executor to fill in honestly — if a doc grew larger than the plan estimated, or a slug spelling changed, or a Mermaid diagram was added because the executor judged one warranted, the executor records it there. If the plans landed verbatim, write `None.`) + </action> + <verify> + <automated>test -f docs/decisions/015-developer-internals-docs.md && test -f .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md && grep -q '^# 015:' docs/decisions/015-developer-internals-docs.md && grep -qE '^\*\*Status:\*\* +Accepted$' docs/decisions/015-developer-internals-docs.md && grep -q '^## Context' docs/decisions/015-developer-internals-docs.md && grep -q '^## Decision' docs/decisions/015-developer-internals-docs.md && grep -q '^## Consequences' docs/decisions/015-developer-internals-docs.md && grep -qE 'ADR-?010|review-reminder' docs/decisions/015-developer-internals-docs.md && grep -q '^# Phase 12 AUDIT' .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md && grep -qF 'GATE: GREEN' .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md && for n in 01 02 03 04 05 06 07; do grep -qE "DOC-${n}" .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md || { echo "MISSING DOC-${n}"; exit 1; }; done && grep -qF '015-developer-internals-docs' .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md</automated> + </verify> + <acceptance_criteria> + - File `docs/decisions/015-developer-internals-docs.md` exists. + - ADR-015 H1 starts with `# 015:` (matches existing ADR numbering convention). + - ADR-015 frontmatter includes `**Status:** Accepted` and `**Date:** 2026-05-09` and `**Drives:** DOC-01, DOC-02, DOC-03, DOC-04, DOC-05, DOC-06, DOC-07` and `**Companion to:** ADR-010 (review loop via CLAUDE.md, refined 2026-05-02)`. + - ADR-015 contains all three mandated H2 sections from the template: `## Context`, `## Decision`, `## Consequences`. + - ADR-015 explicitly states "Do NOT add a third stop-hook" or equivalent in the `## Decision` section, and explains why in `## Consequences`. + - File `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md` exists. + - 12-AUDIT.md H1 is `# Phase 12 AUDIT — Developer documentation for installer, runtime, and CLI (AL-22)` (or equivalent — must contain `# Phase 12 AUDIT`). + - 12-AUDIT.md frontmatter block includes `**Phase status:** GATE: GREEN` and lists all seven DOC-XX requirement IDs in `**Requirements covered:**`. + - 12-AUDIT.md `## Evidence per requirement` table has one row per DOC-XX (DOC-01 through DOC-07), each row citing a concrete evidence artifact path. + - 12-AUDIT.md ends with a `## Phase-close gate` section emitting `GATE: GREEN`. + - 12-AUDIT.md cites ADR-015 (`docs/decisions/015-developer-internals-docs.md`) at least once. + </acceptance_criteria> + <done>ADR-015 + 12-AUDIT.md committed; phase-close gate emits GREEN; design decision archived for future readers.</done> +</task> + +</tasks> + +<verification> +After all tasks complete: + +```bash +# REQUIREMENTS.md has DOC-01..DOC-07 +for n in 01 02 03 04 05 06 07; do + grep -qE "\*\*DOC-${n}\*\*" .planning/REQUIREMENTS.md || { echo "MISSING DOC-${n} in REQUIREMENTS.md"; exit 1; } +done + +# REQ-ID Traceability: v0.4.0 row UNCHANGED at 21/5; new addendum H3 added with 7/1 +grep -qF '**Total v0.4.0** | | **21**' .planning/REQUIREMENTS.md +grep -qF '21 requirements mapped to 5 phases' .planning/REQUIREMENTS.md +grep -qE '^### Post-v0\.4\.0 Addendum Traceability' .planning/REQUIREMENTS.md +grep -qF '**Total addendum** | | **7**' .planning/REQUIREMENTS.md +grep -qF '7 addendum requirements mapped to 1 phase' .planning/REQUIREMENTS.md + +# ADR-015 exists with the right shape +test -f docs/decisions/015-developer-internals-docs.md +grep -q '^# 015:' docs/decisions/015-developer-internals-docs.md +grep -qE '^\*\*Status:\*\* +Accepted' docs/decisions/015-developer-internals-docs.md + +# 12-AUDIT.md emits GREEN +test -f .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md +grep -qF 'GATE: GREEN' .planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md + +# Final invariant: no new hook file, no .claude/settings.json edits in this phase +! test -f .claude/hooks/dev-docs-reminder.sh +git diff --stat HEAD~5..HEAD -- .claude/settings.json | wc -l | grep -q '^0$' || true # informational only — actual base ref is the phase-12 starting commit +``` +</verification> + +<success_criteria> +- `.planning/REQUIREMENTS.md` enumerates DOC-01..DOC-07 with verifiable contracts; traceability table updated. +- `docs/decisions/015-developer-internals-docs.md` exists with `Status: Accepted`, records the no-new-hook + embed-in-review-loop design, and references ADR-010. +- `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md` exists, evidence table covers DOC-01..DOC-07 with concrete artifact paths, and the phase-close gate emits `GATE: GREEN`. +- No new file under `.claude/hooks/`. No edit to `.claude/settings.json`. (DOC-06 invariant.) +</success_criteria> + +<output> +After completion, create `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-05-SUMMARY.md` per the GSD summary template. The SUMMARY.md should call out: (a) DOC-XX requirements enumerated and gate emitted; (b) ADR-015 captured; (c) milestone-framing decision (DOC-XX is a post-v0.4.0 addendum that does not reopen the v0.4.0 milestone gate). +</output> diff --git a/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-05-SUMMARY.md b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-05-SUMMARY.md new file mode 100644 index 0000000..0db55fb --- /dev/null +++ b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-05-SUMMARY.md @@ -0,0 +1,162 @@ +--- +phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 +plan: 05 +subsystem: docs +tags: [requirements, adr, audit, doc-xx, post-v0.4.0-addendum, phase-close, AL-22] + +# Dependency graph +requires: + - phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 + plan: 01 + provides: docs/internals/README.md + 4 install/runtime-layer component docs (cited as DOC-01 + DOC-02 evidence) + - phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 + plan: 02 + provides: 5 catalog-layer component docs (cited as DOC-02 evidence; completed the docs/internals/ tree) + - phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 + plan: 03 + provides: .claude/agents/dev-docs-auditor.md + .claude/skills/dev-docs/SKILL.md (cited as DOC-03 + DOC-04 evidence; the no-new-hook stance ADR-015 records) + - phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 + plan: 04 + provides: CLAUDE.md "Review Loop" wiring + Pointers + README.md "Why AgentLinux — concepts" section + Links row (cited as DOC-03 + DOC-05 evidence) +provides: + - DOC-01..DOC-07 enumerated in REQUIREMENTS.md as a post-v0.4.0 addendum (new H2 + H3); v0.4.0 milestone count remains 21 + - ADR-015 (docs/decisions/015-developer-internals-docs.md) — design decision archive (no-new-hook + embed-in-review-loop + flat-extend-not-new-CLAUDE.md-section) + - 12-AUDIT.md emitting GATE GREEN — Phase 12 closed with one row of cited evidence per DOC-XX +affects: + - All future phases that reference REQUIREMENTS.md DOC-XX coverage gates + - Future readers of docs/decisions/ — ADR-015 archives the rationale for the absence of .claude/hooks/dev-docs-reminder.sh + - Phase 12 itself — this plan emits the phase-close gate + +# Tech tracking +tech-stack: + added: [] # docs only — no new libraries / runtime tech + patterns: + - "Post-v0.4.0 addendum requirements pattern: new H2 below the v0.4.0 sections + matching H3 traceability sub-section inside the existing ## REQ-ID Traceability H2; v0.4.0 totals stay frozen so the milestone gate count remains honest" + - "Phase-close audit shape (mirrors 11-AUDIT.md): frontmatter status block -> ## Evidence per requirement table with one row per REQ-ID citing artifacts + commit hashes -> ## Deviations from PLAN -> ## Phase-close gate emitting GATE: GREEN" + - "ADR shape (mirrors ADR-014): Drives + Companion to lines in the frontmatter; richer Consequences with named sub-sections (### What changes / ### Why no third hook / ### Why a flat extend / ### Reversibility)" + +key-files: + created: + - "docs/decisions/015-developer-internals-docs.md (67 lines)" + - ".planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md (46 lines)" + modified: + - ".planning/REQUIREMENTS.md (+23 lines: new ## Post-v0.4.0 Addendum Requirements H2 with DOC-01..DOC-07; new ### Post-v0.4.0 Addendum Traceability H3 inside the existing ## REQ-ID Traceability H2)" + +key-decisions: + - "DOC-XX requirements added as a post-v0.4.0 addendum, not merged into the v0.4.0 milestone traceability table — the milestone closed at commit c8a2787 on 2026-05-02 with 21 requirements, and that count must remain honest. New separate H3 traceability sub-section captures the addendum's 7/1-phase coverage without disturbing the existing 21/5-phase totals." + - "ADR-015 frontmatter mirrors ADR-014's shape (Status / Date / Drives / Companion to) rather than the bare ADR-template (only Status + Date) — ADR-014 is the closest recent v0.4.0-era analog and the milestone-framing lines are useful for future readers tracing back from a DOC-XX gate." + - "12-AUDIT.md cites per-plan commit hashes (9c00061, 4598b4a, 3f6e329, e71d8cc, 6891a5f, 191cc21, 1efb2a9, b148ef3) in each evidence row so a reader following the audit can ground each DOC-XX claim in a concrete commit, not just a file path. Shape mirrors 11-AUDIT.md's evidence-table convention." + - "Three Rule 1 source-truth deviations from Plan 12-02 (playwright/gsd/registry-cli) recorded in the AUDIT's Deviations section by reference to 12-02-SUMMARY.md, not re-narrated in full — the Deviations section is shaped as 'document material drift from the plan narrative,' not 'recap every per-plan SUMMARY.'" + +patterns-established: + - "Post-v0.4.0 addendum pattern: when AL-NN scope adds REQs after a milestone closes, capture them under a new ## Post-v0.4.0 Addendum Requirements H2 + a new ### Post-v0.4.0 Addendum Traceability H3 inside the existing ## REQ-ID Traceability H2; do NOT modify the v0.4.0 totals or its prose Coverage check sentence" + - "Phase-close audit cites per-plan commit hashes alongside file paths so the evidence chain is grep-able from a single audit doc back to the originating commits" + +requirements-completed: [DOC-01, DOC-02, DOC-03, DOC-04, DOC-05, DOC-06, DOC-07] + +# Metrics +duration: ~7min +completed: 2026-05-10 +--- + +# Phase 12 Plan 05: REQUIREMENTS.md DOC-XX addendum + ADR-015 + 12-AUDIT.md GATE GREEN + +**Phase 12 closed: REQUIREMENTS.md gains DOC-01..DOC-07 as a post-v0.4.0 addendum (v0.4.0 milestone count stays at 21); ADR-015 archives the no-new-hook + embed-in-review-loop + flat-extend design decision; 12-AUDIT.md emits GATE: GREEN with cited evidence for every DOC-XX requirement.** + +## Performance + +- **Duration:** ~7 min +- **Started:** 2026-05-10T08:55:00Z (approx) +- **Completed:** 2026-05-10T09:02:00Z +- **Tasks:** 2 +- **Files created:** 2 (ADR-015 + 12-AUDIT.md) +- **Files modified:** 1 (REQUIREMENTS.md) + +## Accomplishments + +- DOC-01..DOC-07 enumerated in REQUIREMENTS.md with verifiable contracts mirroring the v0.4.0 LIC/SEC/CLEAN/CIPUB/PUB style. +- The v0.4.0 milestone count is untouched: `**Total v0.4.0** | | **21**` and the prose `21 requirements mapped to 5 phases. Zero orphans.` remain. The post-v0.4.0 addendum lives in a separate H2 (`## Post-v0.4.0 Addendum Requirements`) with a sibling traceability H3 (`### Post-v0.4.0 Addendum Traceability`, 7 reqs / 1 phase). +- ADR-015 records the design decision behind Phase 12 (Status: Accepted, Date: 2026-05-09, Drives: DOC-01..DOC-07, Companion to: ADR-010). Sections cover Context (the AL-22 60-second-answer goal + the two adjacent decisions on docs sync and stop-hook posture), Decision (5-point spec including "no new hook / no settings.json edit"), and a richer Consequences with four sub-sections (What changes / Why no third hook / Why a flat extend / Reversibility). +- 12-AUDIT.md emits `GATE: GREEN` with one row of cited evidence per DOC-XX requirement. Each row cites both the artifact path and the originating commit hash from Plans 12-01..04. The Deviations section records the three Rule 1 source-truth fixes from Plan 12-02 (playwright/gsd/registry-cli) by reference to 12-02-SUMMARY.md. +- DOC-06 invariants verified at commit time and documented in the AUDIT: no `.claude/hooks/dev-docs-reminder.sh`, `.claude/settings.json` last touched 2026-04-26 (commit `a812a02`, well before Phase 12 began). + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Add DOC-01..DOC-07 to REQUIREMENTS.md** — `bbf7929` (docs) +2. **Task 2: Write ADR-015 + 12-AUDIT.md** — `b62c0b0` (docs) + +**Plan metadata commit (this SUMMARY + STATE/ROADMAP/REQUIREMENTS bookkeeping):** committed after this file lands. + +## Files Created/Modified + +- `.planning/REQUIREMENTS.md` (modified, +23 lines) — Inserted `## Post-v0.4.0 Addendum Requirements` H2 between the existing `### Public Visibility Flip & Smoke Test (PUB) — Phase 11` block and `## Future Requirements (not in this milestone)`. The new H2 wraps a one-paragraph framing (cites the v0.4.0 close at `c8a2787` / 21 reqs / AL-22 origin) and the `### Developer Documentation (DOC) — Phase 12` H3 with seven `- [ ] **DOC-NN**:` rows. Inserted `### Post-v0.4.0 Addendum Traceability` H3 inside the existing `## REQ-ID Traceability` H2, between the prose Coverage check line and the `## Verification Convention` H2 that closes the section. The addendum H3 carries its own one-row table totalling 7 and its own Coverage-check sentence (7/1 phase). +- `docs/decisions/015-developer-internals-docs.md` (created, 67 lines) — ADR archiving the design decision behind Phase 12. Frontmatter mirrors ADR-014: Status (Accepted) + Date (2026-05-09) + Drives (DOC-01..DOC-07) + Companion to (ADR-010, refined 2026-05-02). Sections: ## Context (the 60-second-answer goal + the two adjacent decisions), ## Decision (5-point spec naming "no new hook / no settings.json edit" explicitly), ## Consequences (### What changes, ### Why no third hook, ### Why a flat extend, ### Reversibility), ## References (ADR-010 + 12-CONTEXT.md + the three artifacts this ADR drives). +- `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md` (created, 46 lines) — Phase-close audit. Frontmatter status block names GATE: GREEN, Closed 2026-05-09, all seven DOC-XX requirement IDs, all five plans, and the source spec. `## Evidence per requirement` table has one row per DOC-XX with verifiable contract + concrete artifact path + per-plan commit hash + Closed status. `## Deviations from PLAN` records the three Rule 1 source-truth fixes from Plan 12-02 by reference. `## Phase-close gate` emits GATE: GREEN and frames the addendum as not reopening the v0.4.0 milestone gate. `## References` cites ADR-015 + ADR-010 + 12-CONTEXT.md + REQUIREMENTS.md DOC section + all four prior plan SUMMARYs. + +## Decisions Made + +- **DOC-XX as post-v0.4.0 addendum, not v0.4.0 traceability merge.** The plan was explicit (`<action>` Part B: "leave the existing `## REQ-ID Traceability` table UNCHANGED"). The v0.4.0 milestone closed at `c8a2787` on 2026-05-02 with 21 requirements; rewriting that closed milestone's count would be dishonest bookkeeping. The addendum pattern (separate H2 with framing paragraph + separate H3 traceability sub-section) keeps both records intact. +- **ADR-014 as the analog over the bare ADR template.** ADR-014 (`014-secret-remediation-noop.md`) is the closest recent v0.4.0-era ADR — it carries the same "Drives + Companion to" frontmatter shape and a richer Consequences body with named sub-sections. ADR-015 inherits both. The 000-template.md is the minimum spec; ADR-014 is the contemporary precedent. +- **Per-plan commit hashes inside the AUDIT evidence table.** 11-AUDIT.md's evidence rows cite artifact paths but not commit hashes (it's a flip-event audit, not a multi-plan accumulation). 12-AUDIT.md aggregates work across five plans (12-01..05); citing each plan's task commits inline gives a reader following the audit a direct grep path back to origin without needing to cross-reference each per-plan SUMMARY first. +- **Deviations recorded by reference, not re-narration.** The three Rule 1 source-truth fixes from Plan 12-02 (playwright grounded in `@playwright/cli` reality, gsd's bootstrapper-wires-skills story, registry-cli's actual five-verb surface) are documented in 12-02-SUMMARY.md "Auto-fixed Issues" with full per-deviation detail. The AUDIT cites those deviations in its `## Deviations from PLAN` section by name + by reference to that SUMMARY rather than re-narrating each one — the AUDIT's job is the phase-close evidence chain, not deviation post-mortem. +- **AUDIT does not reopen the v0.4.0 milestone gate.** The `## Phase-close gate` section explicitly frames Phase 12's GATE: GREEN as separate from the v0.4.0 milestone close (PUB-XX, commit `c8a2787`, 2026-05-02). DOC-XX is post-milestone documentation work; closing it does not retroactively change the milestone scope or count. + +## Deviations from Plan + +None — plan executed exactly as written. + +Both `<verify>` automated checks passed first try; both `<acceptance_criteria>` lists were green on first write; both `<done>` criteria were met. Zero auto-fix commits; zero Rule 1/2/3/4 deviations were necessary. + +The pre-existing `git status` snapshot at session start showed unrelated modifications to `.planning/config.json`, three Plan 12-0[3..5] PLAN.md files, `docs/audits/v0.4.0/PUB-04-release-notes.md`, plus `.planning/{MILESTONES,ROADMAP,STATE}.md` from earlier in the day. These were left strictly untouched per the scope-boundary rule. Per the protocol, only the three files this plan owned were `git add`-ed and committed; no `git add .` / `-A` was used. + +## Issues Encountered + +None. + +The PreToolUse Edit hook's "READ-BEFORE-EDIT REMINDER" fired after both REQUIREMENTS.md edits — these are reminder messages from the runtime, not failures. REQUIREMENTS.md was read once at the start of the session and a second time (lines 50-107) before the second edit; both edits applied successfully on first attempt. + +## User Setup Required + +None — no external service configuration required. + +## Next Phase Readiness + +- Phase 12 is closed. The phase-close gate emits GREEN; all seven DOC-XX requirements are evidenced. +- Future phases that touch `plugin/bin/`, `plugin/lib/`, `plugin/provisioner/`, `plugin/cli/src/`, `plugin/catalog/`, or `packaging/curl-installer/` will trigger the `dev-docs-auditor` reviewer (wired into the CLAUDE.md Review Loop in Plan 12-04). The reviewer reads `.claude/skills/dev-docs/SKILL.md` for the source-path → doc-path dispatch table and the four-section per-component contract. +- ADR-015 is the canonical reference for the "no third stop-hook" stance — future contributors who consider adding a `dev-docs-reminder.sh` should be redirected to ADR-015 §"Why no third hook" first. +- The post-v0.4.0 addendum pattern is now established: when future AL-NN scope adds REQs after a milestone closes, the precedent is to add a sibling addendum H2 + traceability H3, not to retroactively grow the closed milestone's totals. + +## Self-Check: PASSED + +Created files exist: + +- FOUND: `docs/decisions/015-developer-internals-docs.md` (67 lines) +- FOUND: `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md` (46 lines) + +Modified files match expectations: + +- FOUND: `.planning/REQUIREMENTS.md` carries DOC-01..DOC-07 in `## Post-v0.4.0 Addendum Requirements` H2; `## REQ-ID Traceability` v0.4.0 row UNCHANGED at `**Total v0.4.0** | | **21**`; new H3 `### Post-v0.4.0 Addendum Traceability` totalling `**Total addendum** | | **7**` present; both Coverage check prose lines (21/5 and 7/1) present. + +Commits exist: + +- FOUND: `bbf7929` (docs(12-05): add DOC-01..DOC-07 to REQUIREMENTS.md as post-v0.4.0 addendum) +- FOUND: `b62c0b0` (docs(12-05): add ADR-015 + Phase 12 AUDIT (GATE: GREEN)) + +Plan-level verification (per plan's `<verification>` block): + +- For each `n` in 01..07: `\*\*DOC-${n}\*\*` present in REQUIREMENTS.md PASS +- `**Total v0.4.0** | | **21**` present (UNCHANGED) PASS +- `21 requirements mapped to 5 phases` prose present (UNCHANGED) PASS +- `### Post-v0.4.0 Addendum Traceability` H3 present PASS +- `**Total addendum** | | **7**` present PASS +- `7 addendum requirements mapped to 1 phase` prose present PASS +- ADR-015 file exists, H1 `# 015:` PASS, `**Status:** Accepted` PASS, H2s `## Context` + `## Decision` + `## Consequences` all present PASS, references ADR-010 PASS +- 12-AUDIT.md file exists, H1 `# Phase 12 AUDIT` PASS, `GATE: GREEN` present PASS, all DOC-01..07 referenced PASS, ADR-015 cited PASS +- DOC-06 invariants: `! test -f .claude/hooks/dev-docs-reminder.sh` PASS; `.claude/hooks/` contains only `review-reminder.sh` and `session-tracker-reminder.sh`; `.claude/settings.json` last touched at commit `a812a02` (well before Phase 12) PASS + +--- +*Phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22* +*Plan: 05* +*Completed: 2026-05-10* diff --git a/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md new file mode 100644 index 0000000..76f1b09 --- /dev/null +++ b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-AUDIT.md @@ -0,0 +1,46 @@ +# Phase 12 AUDIT — Developer documentation for installer, runtime, and CLI (AL-22) + +**Phase status:** GATE: GREEN +**Closed:** 2026-05-09 +**Requirements covered:** DOC-01, DOC-02, DOC-03, DOC-04, DOC-05, DOC-06, DOC-07 +**Plans:** 12-01-PLAN.md, 12-02-PLAN.md, 12-03-PLAN.md, 12-04-PLAN.md, 12-05-PLAN.md +**Source spec:** AL-22 ("Create documentation on what AgentLinux does"), 12-CONTEXT.md (locked decisions) + +## Evidence per requirement + +| REQ-ID | Verifiable contract | Evidence artifact | Status | +|---|---|---|---| +| DOC-01 | `docs/internals/README.md` exists with What-AgentLinux-is lede + `## Components` H2 TOC linking to all 9 component docs | `docs/internals/README.md` (Plan 12-01, commit `9c00061`) | ✓ Closed | +| DOC-02 | 9 component docs under `docs/internals/`, each with the four-section spine (`## The problem` → `## What AgentLinux does` → `## Value vs the naive approach` → `## Related`) and a numbered **bold lead clause** trade-off list; no source-line deep links | `docs/internals/{installer,agent-user,sudo-drop-in,nodejs-runtime}.md` (Plan 12-01, commits `9c00061` + `4598b4a`) + `docs/internals/{claude-code,gsd,playwright,registry-cli,catalog}.md` (Plan 12-02, commits `3f6e329` + `e71d8cc`) | ✓ Closed | +| DOC-03 | `dev-docs-auditor` reviewer registered in CLAUDE.md "Review Loop" reviewer-by-file-type table on Bash, TS/JS, and Catalog recipes rows | `.claude/agents/dev-docs-auditor.md` (Plan 12-03, commit `6891a5f`) + `CLAUDE.md` Review Loop table (Plan 12-04, commit `1efb2a9`) | ✓ Closed | +| DOC-04 | `dev-docs/SKILL.md` documents the four-section contract + source-path → doc-path dispatch table covering all 9 component docs; enumerated in CLAUDE.md "Pointers" | `.claude/skills/dev-docs/SKILL.md` (Plan 12-03, commit `191cc21`) + `CLAUDE.md` Pointers list (Plan 12-04, commit `1efb2a9`) | ✓ Closed | +| DOC-05 | Top-level `README.md` "Why AgentLinux — concepts" H2 section + `## Links` row link `docs/internals/` | `README.md` (Plan 12-04, commit `b148ef3`) | ✓ Closed | +| DOC-06 | No new stop-hook; `.claude/hooks/dev-docs-reminder.sh` does not exist; `.claude/settings.json` unchanged across the Phase 12 commit range | `! test -f .claude/hooks/dev-docs-reminder.sh` PASS; `git log --since="2026-05-09" -- .claude/settings.json` empty across the Phase 12 commit range | ✓ Closed | +| DOC-07 | `docs/decisions/015-developer-internals-docs.md` records the design decision (no new hook + embed in review loop); status `Accepted` | `docs/decisions/015-developer-internals-docs.md` (Plan 12-05, this audit's sibling commit) | ✓ Closed | + +## Deviations from PLAN + +Three Rule 1 (source-truth) auto-fix deviations were absorbed during Plan 12-02 and documented in `12-02-SUMMARY.md` ("Auto-fixed Issues" section); they are content corrections, not scope deviations: + +1. `playwright.md` grounded in the real `@playwright/cli` (catalog id `playwright-cli`, pinned 0.1.11) recipe rather than the plan's narrated Playwright-library + chromium-with-deps story. +2. `gsd.md` added the `get-shit-done-cc --global --claude` bootstrapper-wires-skills story present in the actual `install.sh` but absent from the plan's narrative. +3. `registry-cli.md` lists the five verbs that ship in `plugin/cli/src/index.ts` (list, install, remove, upgrade, pin); the plan's `info` and `doctor` verbs do not exist as commands and were dropped. + +No additional deviations during Plans 12-01, 12-03, 12-04, or 12-05. The plans landed verbatim modulo those three source-truth corrections; the four-section structural contract, the no-source-line-deep-links discipline, the no-new-hook stance (DOC-06), and the multi-row CLAUDE.md Review Loop wiring (Bash + TS/JS + Catalog recipes rather than a new "Internal docs" row) all shipped exactly as 12-CONTEXT.md specified. + +## Phase-close gate + +GATE: GREEN — all 7 requirements evidenced. + +The Phase 12 outputs ride inside the existing v0.4.0 milestone release that shipped 2026-05-02 (`v0.3.1 — Open-Source Flip`, commit `c8a2787`). DOC-XX is therefore tracked as a **post-v0.4.0 addendum** in REQUIREMENTS.md (see `## Post-v0.4.0 Addendum Requirements` H2 + `### Post-v0.4.0 Addendum Traceability` H3) — the milestone closed under PUB-XX with 21 requirements, and the AL-22 documentation work is captured separately. The v0.4.0 milestone gate is not reopened by this phase close. + +## References + +- `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md` — locked user decisions +- `docs/decisions/015-developer-internals-docs.md` — design ADR (no new hook + embed in review loop) +- `docs/decisions/010-review-loop-via-claude-md.md` — review-loop precedent (refined 2026-05-02) +- `.planning/REQUIREMENTS.md` §"Developer Documentation (DOC) — Phase 12" — DOC-01..DOC-07 contracts +- `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-01-SUMMARY.md` — Plan 01 (index + 4 install/runtime-layer component docs) +- `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-02-SUMMARY.md` — Plan 02 (5 catalog-layer component docs) +- `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-03-SUMMARY.md` — Plan 03 (dev-docs-auditor reviewer + dev-docs skill) +- `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-04-SUMMARY.md` — Plan 04 (CLAUDE.md + README.md wiring) diff --git a/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md new file mode 100644 index 0000000..6430ffd --- /dev/null +++ b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md @@ -0,0 +1,103 @@ +# Phase 12: Developer documentation for installer, runtime, and CLI (AL-22) - Context + +**Gathered:** 2026-05-09 +**Status:** Ready for planning +**Source spec:** [AL-22](https://copiedwonder.atlassian.net/browse/AL-22) — "Create documentation on what AgentLinux does" + +<domain> +## Phase Boundary + +Create developer-facing internal documentation explaining **what each AgentLinux component does and why it exists** — with a product-perspective lens — and wire the docs into the existing review loop so they stay in sync with the codebase. The phase delivers: + +1. A new `docs/internals/` tree with a high-level overview of AgentLinux + per-component deep-dives. +2. A project-scoped Claude Code skill (`.claude/skills/dev-docs/`) that documents the docs contract. +3. A new reviewer agent (`.claude/agents/dev-docs-auditor.md`) that the existing review loop invokes when relevant code changes — no new stop-hook is added. +4. CLAUDE.md updates wiring the new reviewer into the "Review Loop" routing table. +5. A short pointer from the top-level README to `docs/internals/`. + +The phase does NOT cover: end-user usage docs (those live in README), line-by-line source annotation, or new stop-hooks (the existing `review-reminder.sh` already triggers the review loop and is the single chokepoint per ADR-010 refinement). + +</domain> + +<decisions> +## Implementation Decisions + +### Documentation Scope & Format + +- **Audience:** primarily the project owner; secondarily future contributors. Tone is product-first ("what value does AgentLinux add for X"), technical-second. +- **Structure:** one high-level overview doc explaining what AgentLinux is + per-component deep-dives. Each component answers: what problem it solves, why bundled in AgentLinux, value vs the naive (raw `npm install`, ad-hoc shell, etc.) approach. +- **Depth:** high-level concepts only. Do **not** cross-link to source files (`file_path:line`) or ADRs in this layer — that level of detail is too deep for the intended audience. Component docs may reference an ADR by name in prose if it materially explains the "why," but no link discipline is required. +- **Diagrams:** Mermaid diagrams are allowed but used sparingly — only when a diagram genuinely illustrates a concept (e.g. install-time sequence, agent-user permission topology). Skip diagrams for components where prose is clearer. +- **Reuse signal:** treat the docs as a source of insights for blog posts, marketing emails, and the `agentlinux.org` landing page. Each component doc should be excerptable into product copy. + +### Documentation Layout + +- **Top-level dir:** `docs/internals/` — sibling to `docs/decisions/`, `docs/research/`, `docs/audits/` (matches existing convention). +- **Entry doc:** `docs/internals/README.md` — opens with "What AgentLinux is" + value proposition, then a TOC linking to component docs. +- **Per-component files:** one per surface — `installer.md`, `agent-user.md`, `nodejs-runtime.md`, `sudo-drop-in.md`, `claude-code.md`, `gsd.md`, `playwright.md`, `registry-cli.md`, `catalog.md`. Each follows the same shape: problem → AgentLinux's answer → value vs the naive approach. +- **Top-level README discoverability:** add a short "Why AgentLinux — concepts" section in the root `README.md` linking into `docs/internals/`. + +### Maintenance Tooling — Skill, Reviewer, CLAUDE.md (NO new hook) + +- **No new stop-hook.** The existing `.claude/hooks/review-reminder.sh` already nudges Claude to run the review loop before stopping. Adding a third hook would multiply ADR-010 reminder noise. Embed the docs check inside the review loop instead. +- **New reviewer agent:** `.claude/agents/dev-docs-auditor.md` — sibling to the six existing reviewers (bash-engineer, node-engineer, security-engineer, qa-engineer, behavior-coverage-auditor, catalog-auditor). Read-only tools (Read, Grep, Glob, Bash). Responsibility: when changes touch `plugin/bin/`, `plugin/lib/`, `plugin/provisioner/`, `plugin/cli/src/`, `plugin/catalog/`, or `packaging/curl-installer/`, the agent checks that the affected component's `docs/internals/<component>.md` is still accurate, and flags missing or stale sections. Skips on pure refactors, typos, comment-only changes, and `.planning/`-only changes. +- **New skill:** `.claude/skills/dev-docs/SKILL.md` — documents the docs contract (per-component file structure, product-perspective lens, when to update, what each doc must contain). The dev-docs-auditor reads this skill the same way other reviewers consult their topic skills. +- **CLAUDE.md wiring:** extend the existing "Review Loop" section's reviewer-by-file-type table with `dev-docs-auditor` for `plugin/` source changes. No new top-level CLAUDE.md section is required — keeping the wiring inside the existing Review Loop routing keeps the surface flat. + +### Claude's Discretion + +- Exact filenames inside `docs/internals/` (slug spelling, ordering in the TOC) — implementer's call as long as the per-surface split is honored. +- Whether and where Mermaid diagrams appear — implementer judges per component. +- Exact prose templates for component docs (the "problem → answer → value vs naive" shape is the contract, not the formatting). +- Reviewer agent system-prompt phrasing — match the tone and structure of the existing six reviewers. +- Whether to capture this design as an ADR — recommended (`ADR-015-developer-internals-docs.md`) so future readers know why there's no new hook, but not strictly required. + +</decisions> + +<code_context> +## Existing Code Insights + +### Reusable Assets + +- Review-loop infrastructure (`.claude/skills/review/SKILL.md`, `.claude/hooks/review-reminder.sh`, the six existing reviewer agents under `.claude/agents/`) is the integration target — no new hook plumbing needed. +- Docs tree convention is already in place: `docs/decisions/` (ADRs), `docs/research/`, `docs/audits/`, `docs/proposals/`, `docs/reviews/`, `docs/HARNESS.md` (top-level harness spec), `docs/STABILITY-MODEL.md`, `docs/README.md`. Adding `docs/internals/` slots cleanly into this layout. +- Existing skills under `.claude/skills/` (`agentlinux-installer/`, `behavior-test-contract/`, `catalog-schema/`, `qemu-harness/`, `review/`, `workspace-cleanup/`) are the structural template for the new `dev-docs/` skill. +- ADR-010 (review loop via CLAUDE.md) and its 2026-05-02 refinement (allowing reminder hooks with `stop_hook_active` guard) provide the precedent for the integration approach — and the rationale for *not* adding a third reminder hook. + +### Established Patterns + +- Project-scoped reviewers live under `.claude/agents/<name>.md` with frontmatter declaring tool whitelist; bodies follow a stable shape (Role / Inputs / Checks / Output format). +- Skills under `.claude/skills/<name>/SKILL.md` document a contract that an agent or the main loop reads at decision time. +- CLAUDE.md "Review Loop" section is the single source of truth for which reviewers run on which file types — adding a row there is the canonical wiring. +- Stop-hook reminders both implement the ADR-010 refinement: `stop_hook_active` guard (no recursion) + clear instruction text + skip conditions documented inline. The existence of two hooks (review + session-tracker) is intentional and the user has explicitly drawn the line at "no third hook." + +### Integration Points + +- New reviewer agent → registered by adding to `.claude/agents/` with the agreed tool whitelist; CLAUDE.md "Review Loop" table grows one row. +- New skill → `.claude/skills/dev-docs/SKILL.md` + entry in CLAUDE.md "Pointers" list (already enumerates the other project-scoped skills). +- New docs tree → `docs/internals/README.md` as index; top-level `README.md` gets a "Why AgentLinux — concepts" link. +- No changes to `.claude/settings.json` (no new hook to register). +- No changes to `tests/` (this phase ships content + tooling, not behavior). + +</code_context> + +<specifics> +## Specific Ideas + +- The motivating question shape from AL-22 is the litmus test for the docs: *"What value does AgentLinux provide in installing GSD instead of using the GSD installation from npm directly?"* The docs must give the project owner an answer in <60 seconds. +- Component docs are explicitly intended to double as raw material for blog posts, marketing emails, and the `agentlinux.org` landing page — keep prose excerpt-friendly. +- The user pushed back on overcomplicated tooling: do NOT introduce a separate stop-hook. Embed the docs-sync enforcement inside the existing review loop via a new reviewer agent. This reuse pattern is the design centerpiece of the phase. + +</specifics> + +<deferred> +## Deferred Ideas + +- Source-code cross-references (`file_path:line` deep links) — out of scope for the initial cut; revisit if/when the docs grow stale and we need a stronger link discipline. +- ADR cross-references in prose — out of scope; component docs may name an ADR if it explains the "why," but no link discipline is required. +- Auto-generated diagrams from source — not pursued; Mermaid is hand-authored where genuinely useful. +- Documentation site (mdBook, Docusaurus, GitHub Pages docs) — out of scope; markdown in the repo is sufficient for the project owner's stated goal. +- A pre-commit hook that hard-blocks commits touching `plugin/` without `docs/internals/` updates — explicitly rejected (would block legitimate refactors and typos). +- End-user-facing usage docs — covered by README + curl-installer docs; out of scope here. + +</deferred> diff --git a/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-PATTERNS.md b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-PATTERNS.md new file mode 100644 index 0000000..241172e --- /dev/null +++ b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-PATTERNS.md @@ -0,0 +1,495 @@ +# Phase 12: Developer documentation for installer, runtime, and CLI (AL-22) — Pattern Map + +**Mapped:** 2026-05-09 +**Files analyzed:** 13 (11 new + 2 modified) +**Analogs found:** 13 / 13 + +## File Classification + +| New/Modified File | Role | Data Flow | Closest Analog | Match Quality | +|-------------------|------|-----------|----------------|---------------| +| `docs/internals/README.md` | docs-index | reference | `docs/README.md` | exact | +| `docs/internals/installer.md` | docs-component | reference | `docs/STABILITY-MODEL.md` | role-match | +| `docs/internals/agent-user.md` | docs-component | reference | `docs/STABILITY-MODEL.md` | role-match | +| `docs/internals/nodejs-runtime.md` | docs-component | reference | `docs/STABILITY-MODEL.md` | role-match | +| `docs/internals/sudo-drop-in.md` | docs-component | reference | `docs/STABILITY-MODEL.md` | role-match | +| `docs/internals/claude-code.md` | docs-component | reference | `docs/STABILITY-MODEL.md` | role-match | +| `docs/internals/gsd.md` | docs-component | reference | `docs/STABILITY-MODEL.md` | role-match | +| `docs/internals/playwright.md` | docs-component | reference | `docs/STABILITY-MODEL.md` | role-match | +| `docs/internals/registry-cli.md` | docs-component | reference | `docs/STABILITY-MODEL.md` | role-match | +| `docs/internals/catalog.md` | docs-component | reference | `docs/STABILITY-MODEL.md` | role-match | +| `.claude/agents/dev-docs-auditor.md` | reviewer-agent | review | `.claude/agents/catalog-auditor.md` | exact | +| `.claude/skills/dev-docs/SKILL.md` | skill | reference | `.claude/skills/catalog-schema/SKILL.md` | exact | +| `CLAUDE.md` (modify) | project-instructions | reference | existing CLAUDE.md §Review Loop + §Pointers | self | +| `README.md` (modify) | project-readme | reference | existing README.md §Stability model + §Links | self | + +**Why STABILITY-MODEL.md over HARNESS.md / ADRs:** STABILITY-MODEL is the single closest single-topic concept doc in the repo today — short (~125 lines), product-first ("here's what AgentLinux does for you and why"), opens with a TL;DR, ends with cross-links. The internals docs aim for the same shape (problem → AgentLinux's answer → value vs naive). HARNESS.md is structurally heavier (numbered §1..§8 sections, table-shaped, internal-only); ADRs are explicitly decision-shaped (Context / Decision / Consequences) which is the wrong frame for a product-perspective concept doc. + +## Pattern Assignments + +### `docs/internals/README.md` (docs-index) + +**Analog:** `docs/README.md` + +**Top-level shape** (lines 1-21, the entire file): +```markdown +# AgentLinux Documentation + +This directory holds all reference documentation. `.planning/` holds GSD workflow +state (plans, STATE.md, config) — not documentation. If the output of a task is +a document intended to be read later (ADR, research report, design proposal, +review summary), it goes here. + +## Layout + +- `HARNESS.md` — authoritative project harness spec (§1 layout, §2 docs, + §3 systems access, §4 review loop, §5 skills, §6 CLAUDE.md, §7 checklist, + §8 success criteria). +- `decisions/` — Architecture Decision Records (ADRs). ADR-001..ADR-010 seeded + in Phase 1 per `HARNESS.md` §2.3. New ADRs land as decisions resolve. +- ... +``` + +**Pattern to copy:** H1 title → one-paragraph "what this dir is and is not" → `## Layout` section with bullet-list of files where each bullet has the filename + one-sentence one-line description. Hyphenated descriptions, not multi-paragraph. + +**Adaptation for `docs/internals/README.md`:** The CONTEXT.md spec calls for "What AgentLinux is + value proposition, then a TOC linking to component docs." Per CONTEXT §"Documentation Layout," opens with a value-proposition paragraph (not a "what this dir is not" paragraph), then a `## Components` (or similar) TOC. So the pattern is **borrow the linkable-bullet TOC shape** from `docs/README.md`, but **replace the "what this is not" lede** with a product-first "What AgentLinux is" paragraph. + +--- + +### `docs/internals/installer.md` (and the eight other component docs) + +**Analog:** `docs/STABILITY-MODEL.md` + +**Frontmatter / lede pattern** (lines 1-9): +```markdown +# AgentLinux Stability Model + +> The TL;DR of [ADR-011](decisions/011-stability-first-version-pinning.md). + +AgentLinux ships *curated combos*: every catalog agent is pinned to an exact +version that we test together end-to-end before each release. You install one +combo and everything just works. When you want to run ahead of the curated +pin, you can — and `agentlinux upgrade` + `agentlinux pin` give you a clean +way to reconcile. +``` + +**Pattern to copy:** H1 → optional one-line italicized cross-reference (CONTEXT says no link discipline required; an ADR mention in prose is OK but not as a `> The TL;DR of …` line) → 3-5 line plain-prose lede that answers "what is this thing for" in product voice. + +**Section-flow pattern** (the H2 spine of STABILITY-MODEL.md): +```markdown +## What's a curated combo → "the thing itself" / definition +## The three divergence states → "how it behaves" / mechanics +## Worked example: "I ran `claude update`" → concrete scenario w/ shell session +## Escape hatch: `agentlinux pin` → adjacent flexibility surface +## Why pin at all (the trade-off) → rationale / value vs naive +## Related → cross-links footer +``` + +**Adaptation for component docs:** CONTEXT §"Documentation Scope & Format" mandates "problem → AgentLinux's answer → value vs the naive approach" as the structural contract. Map STABILITY-MODEL's spine to that contract: + +| CONTEXT contract slot | Suggested H2 (analog source) | +|---|---| +| Problem | `## The problem` (no analog; new) | +| AgentLinux's answer (mechanics) | `## What AgentLinux does` (mirrors STABILITY-MODEL's "What's a curated combo" + "The three divergence states") | +| Worked example | `## Worked example` (mirrors STABILITY-MODEL's "I ran `claude update`" — keep the shell-session-with-prompts shape) | +| Value vs naive | `## Value vs the naive approach` (mirrors STABILITY-MODEL's "Why pin at all (the trade-off)") | +| (optional) Adjacent surface | only if genuinely useful | +| Cross-links | `## Related` (footer with bullet list, exact STABILITY-MODEL shape) | + +**Worked-example shape** (STABILITY-MODEL.md lines 51-74): +~~~markdown +## Worked example: "I ran `claude update`" + +The canonical path. Claude Code ships with its own self-updater that writes +into the agent-owned install tree — that is the whole point of AgentLinux +(AGT-02). After `claude update`, the curated pin and the installed version +disagree; `agentlinux upgrade` surfaces the diff rather than silently +overwriting your choice: + +``` +$ claude update # Claude Code's own updater +✓ Claude Code 2.1.114 installed + +$ agentlinux upgrade +Per-agent divergence (report-only; pass --reset-all-curated or per-agent +choice to mutate): +... +``` +~~~ + +**Pattern to copy:** prose framing → fenced shell session with realistic prompts (`$ cmd` lines + truncated output) → no post-explanation needed when the session itself reads. Each component doc gets one or two of these (or none, if prose suffices). + +**Trade-off / "value vs naive" pattern** (STABILITY-MODEL.md lines 97-115): +```markdown +## Why pin at all (the trade-off) + +Without pinning, AgentLinux would be a thin wrapper around `npm install -g`. +Two problems: + +1. **It provides no value over what users could do themselves.** Running + `sudo -u agent -H npm install -g <pkg>` by hand is a one-liner. A CLI + that only forwards the call adds no product surface. +2. **Upstream instability hits users immediately.** Claude Code, GSD, and + Playwright publish daily-to-weekly... + +Pinning is the explicit contract: **we test exactly what we ship, and you +decide when to move.** +``` + +**Pattern to copy:** Lede sentence framing the naive alternative ("Without X, AgentLinux would be Y") → numbered list of 2-3 problems with the naive approach, **bold-leading-clause** style (`**It provides no value...**` then explanation) → bold one-line resolution sentence. This is the AL-22 litmus test ("What value does AgentLinux provide installing GSD vs `npm install` directly?") rendered as a doc pattern. Excerpt-friendly per CONTEXT §"Reuse signal" — each numbered item lifts cleanly into blog/marketing copy. + +**Cross-links footer pattern** (STABILITY-MODEL.md lines 117-124): +```markdown +## Related + +- [ADR-011 — Stability-first version pinning with explicit reconciliation](decisions/011-stability-first-version-pinning.md) + — the full decision record, including considered alternatives (private + apt/dpkg repo, Nix-style symlink profiles, thin-wrapper baseline). +- [ADR-006 — curl-pipe-bash primary + optional .deb distribution](decisions/006-curl-pipe-bash-plus-deb.md) + — how the release tarball + catalog snapshot + SHA256 sidecar get to users. +- [README.md](../README.md) — the top-level install + verify story. +``` + +**Pattern to copy:** Markdown link as bullet head + em-dash + one-line explanation of what's there. Three to five entries. Per CONTEXT §"Depth": **do not cross-link to source files (`file_path:line`)** — only ADRs, sibling internals docs, README. A doc may *name* an ADR in prose but linking is optional. + +**Mermaid usage** (CONTEXT §"Diagrams"): no analog in STABILITY-MODEL.md (it's prose-only). CONTEXT explicitly says use sparingly — only when a diagram genuinely illustrates (install-time sequence, agent-user permission topology). The executor's call per CONTEXT §"Claude's Discretion." + +--- + +### `.claude/agents/dev-docs-auditor.md` (reviewer-agent) + +**Analog:** `.claude/agents/catalog-auditor.md` (closest match — has the same "audits a specific surface for drift" flavor as the new agent's intended job) + +**Frontmatter pattern** (lines 1-5): +```markdown +--- +name: catalog-auditor +description: Reviews AgentLinux catalog entries and per-agent install recipes for JSON Schema validity, privilege-drop correctness (as_user usage, no sudo npm install -g), symmetric uninstall paths, and absence of /usr/local shim patterns. Use on any change under plugin/catalog/agents/*, plugin/catalog/catalog.json, plugin/catalog/schema.json, or plugin/cli/scripts/validate-catalog.mjs. +tools: Read, Grep, Glob, Bash +--- +``` + +**Pattern to copy:** +- Triple-dash YAML frontmatter +- `name:` matches the filename slug (kebab-case) +- `description:` is one long sentence — first half states the review focus and rubric domain; second half is `Use on/when …` with the exact path globs that should trigger this reviewer. Keep paths concrete (CONTEXT lists them: `plugin/bin/`, `plugin/lib/`, `plugin/provisioner/`, `plugin/cli/src/`, `plugin/catalog/`, `packaging/curl-installer/`). +- `tools:` is **read-only** for review usage: `Read, Grep, Glob, Bash` — no `Write` / `Edit`. (Same as all six existing reviewers.) + +**Body section spine** (catalog-auditor.md H2s): +```markdown +# Catalog Auditor (H1: Title-Case role name) + +[1-2 sentence opener: who I am, what I review, what makes this surface special] + +## When to spawn [bullet list of file globs] +## What to look for [numbered rubric, 6-8 items] +## Common gotchas (AgentLinux-specific) [bullet list of pitfalls] +## Validation workflow [optional: numbered shell-step list] +## Output format [free-form summary contract + example] +``` + +The same H2 spine appears in `bash-engineer.md`, `node-engineer.md`, `qa-engineer.md`, `security-engineer.md`. The `behavior-coverage-auditor.md` variant adds an `## Exit behavior` section because it gates phase close — `dev-docs-auditor` does not gate, so omit that H2. + +**Opener pattern** (catalog-auditor.md lines 7-9): +```markdown +# Catalog Auditor + +Project-scoped review subagent for the AgentLinux agent catalog. The catalog is the opt-in agent registry — it ships claude-code, gsd, and playwright as *available* (CAT-01), none installed by default (CAT-02), validated against a published JSON Schema (CAT-03). This auditor verifies the machine-readable contract and the per-agent install recipes that implement it. +``` + +**Pattern to copy:** Sentence 1 = "Project-scoped review subagent for X." Sentence 2 = one-line context on why X matters (with requirement IDs cited inline). Sentence 3 = what the auditor verifies. Three sentences max. + +**`## When to spawn` pattern** (catalog-auditor.md lines 11-19): +```markdown +## When to spawn + +- Any change under `plugin/catalog/agents/<name>/install.sh` or `plugin/catalog/agents/<name>/remove.sh`. +- Any change under `plugin/catalog/agents/<name>/recipe.json` (per-agent catalog metadata). +- Any change to `plugin/catalog/catalog.json` (the embedded agent list). +- Any change to `plugin/catalog/schema.json` (the JSON Schema — breaking changes need an ADR). +- Any change to `plugin/cli/scripts/validate-catalog.mjs` (the validator that gates the pre-commit hook and CI). +- When a **new agent is added** to the catalog — full pass on the new entry + its install/remove scripts. +``` + +**Pattern to copy:** Each bullet starts with "Any change under/to" + path + parenthetical clarifier. Last bullet often expresses a categorical condition (e.g. "When X is added"). For `dev-docs-auditor` the bullets enumerate the source paths from CONTEXT §"New reviewer agent": `plugin/bin/`, `plugin/lib/`, `plugin/provisioner/`, `plugin/cli/src/`, `plugin/catalog/`, `packaging/curl-installer/`. Plus the **skip-conditions** from CONTEXT (pure refactors, typos, comment-only changes, `.planning/`-only changes) which can either go in `## When to spawn` as "Skip when…" inverse bullets or in their own `## When NOT to spawn` H2 (the latter is cleaner — see `workspace-cleanup` skill's `## What this skill never does` for the inverse-list precedent). + +**`## What to look for` rubric pattern** (catalog-auditor.md lines 21-35, numbered 1-8): +```markdown +## What to look for + +Rubric (copy-of-truth from `docs/HARNESS.md` §4.2): + +1. **JSON Schema validity.** Every entry in `plugin/catalog/catalog.json` AND every `recipe.json`... +2. **`as_user` helper usage in every `install.sh`.** Every catalog `install.sh` must source `plugin/lib/as_user.sh`... +3. **Symmetric uninstall path.** For every `install.sh`, a sibling `remove.sh` MUST exist that undoes... +``` + +**Pattern to copy:** Lede line "Rubric (copy-of-truth from `docs/HARNESS.md` §4.2):" → numbered list with **bold lead-clause** (the rule name) followed by a multi-sentence explanation of the rule + how to verify it. 6-8 items per reviewer is the convention. For `dev-docs-auditor`, candidate rubric items distilled from CONTEXT: + +1. **Component coverage.** Every changed source path under `plugin/{bin,lib,provisioner,cli/src,catalog}/` or `packaging/curl-installer/` must map to a `docs/internals/<component>.md` (registry per the dispatch table the skill defines). A change with no matching component doc is a flag. +2. **Doc freshness.** The component doc still describes what the source actually does (problem → answer → value spine still valid; no stale claims like "uses npm" when the implementation now uses something else). +3. **Skip conditions honored.** Pure refactors, comment-only changes, typo fixes, formatting-only diffs do not require docs updates — flag in the skip column, not the action column. +4. **Product-perspective lens.** The doc still answers "what value does AgentLinux add" — not "here is the line-by-line implementation." +5. **No source cross-references.** Per CONTEXT §"Depth," `file_path:line` deep links are out of scope for this layer. +6. **TOC in `docs/internals/README.md` updated** when a new component doc is added or removed. + +**`## Output format` pattern** (catalog-auditor.md lines 56-77): +~~~markdown +## Output format + +Free-form summary per HARNESS.md §4.3. File:line citations. Begin with validator result (`validate-catalog.mjs` exit code) then list findings by severity. + +Example: + +``` +## catalog-auditor review summary + +Files reviewed: plugin/catalog/agents/claude-code/install.sh, plugin/catalog/agents/claude-code/recipe.json + +Validator: `node plugin/cli/scripts/validate-catalog.mjs` → exit 0 (all recipes valid). + +Findings: +- plugin/catalog/agents/claude-code/install.sh:14 — `sudo npm install -g @anthropic-ai/claude-code`. Critical. Replace with `as_user agent npm install -g @anthropic-ai/claude-code`. ... +``` + +Two blockers (sudo-npm, /usr/local shim), one missing file, one metadata gap. +~~~ + +Main agent triages; reviewer documents. +``` + +**Pattern to copy:** "Free-form summary per HARNESS.md §4.3" boilerplate → "File:line citations" → optional reviewer-specific opening line (validator result, etc) → fenced example block titled `## <reviewer-name> review summary` → `Files reviewed:` line → `Findings:` bulleted list with `path:line — <one-sentence finding>. <one-sentence severity/fix>.` → trailing one-line summary line → outside the fence: `Main agent triages.` (closing motto, present in every existing reviewer). + +--- + +### `.claude/skills/dev-docs/SKILL.md` (skill) + +**Analog:** `.claude/skills/catalog-schema/SKILL.md` (closest match — same shape: a skill that owns a contract a reviewer reads at decision time, plus a "growth plan" footer) + +**Frontmatter pattern** (lines 1-4): +```markdown +--- +name: catalog-schema +description: Use when adding, modifying, or validating a catalog entry under plugin/catalog/. Documents the JSON Schema layout, required fields, install.sh/uninstall.sh contract, symmetric uninstall (CLI-04), the "no agents installed by default" invariant (CAT-02), and the convention for adding a new agent without touching CLI source (CAT-03). Every install recipe runs via as_user — never sudo npm install -g. Grows once the schema is finalized in Phase 4. +--- +``` + +**Pattern to copy:** +- Triple-dash frontmatter, only two keys: `name:` (kebab-case, matches dirname) and `description:` (one long sentence + a second optional sentence). +- The description sentence pattern: `Use when X. Documents Y. <Most-important rule one-liner>. Grows <when>.` Last clause is the growth signal — appears in all four other skill files. +- No `tools:` key on skill frontmatter (skills are not subagents — they document conventions, not invoked actions). + +**Body section spine** (catalog-schema/SKILL.md H2s): +```markdown +# catalog-schema — Catalog entry format (H1: <slug> — <one-line title>) + +**Status:** Skeleton. ... (Status block, single bold line) + +Authoritative spec: `docs/HARNESS.md` §... (one-line cross-link sentence) +Decisions: ADR-XXX (...). (one-line ADR enumeration) +Requirements this skill helps enforce: ... (one-line requirement-ID enumeration) + +## When to use this skill [bullet list of file globs] +## Why this exists ([REQ-ID]) [paragraph naming the requirement this skill backs] +## Current ([phase]) <topic> [code/json block + bullet explanations] +## <topic-specific section> [varies — schema fields, install contract, etc] +## <topic-specific section> [more] +## Growth plan [bulleted phase-by-phase plan] +## Related [bulleted cross-links footer] +``` + +The same skeleton appears in `agentlinux-installer/SKILL.md`, `behavior-test-contract/SKILL.md`, `qemu-harness/SKILL.md`. `review/SKILL.md` is the closest *operational* (vs *contract*) skill — slightly different shape (it has a `## Dispatch rules` table + `## Triage rules` instead of `## Why this exists`). + +**`## When to use this skill` pattern** (catalog-schema/SKILL.md lines 12-21): +```markdown +## When to use this skill + +Use when the task touches any file under: + +- `plugin/catalog/schema.json` — the JSON Schema. +- `plugin/catalog/catalog.json` — the catalog manifest (arrives Phase 4). +- `plugin/catalog/agents/<name>/install.sh` — per-agent install recipe. +- `plugin/catalog/agents/<name>/remove.sh` — per-agent symmetric uninstall. +... +``` + +**Pattern to copy:** "Use when the task touches any file under:" lede → bullet list of `path` + em-dash + one-line description. (Same shape as the reviewer-agent's `## When to spawn` but framed as a use-when-skill rather than spawn-on-trigger.) + +**`## Growth plan` pattern** (catalog-schema/SKILL.md lines 91-95): +```markdown +## Growth plan + +- **Phase 4:** Finalizes the schema, adds the three real entries (claude-code, gsd, playwright), upgrades `validate-catalog.mjs` to ajv, and ships the first install+remove recipes. This skill absorbs the final field list and concrete `install.sh` / `remove.sh` templates. +- **Phase 5:** First AGT-XX tests exercise every recipe. This skill adds the "what a working install.sh looks like" example section. +- **v0.4+:** Multiple install backends per entry... +``` + +**Pattern to copy:** `- **Phase N:** <what lands>. This skill absorbs/adds <what>.` — pairs each phase's deliverable with the skill content that gets unlocked. For `dev-docs/SKILL.md`, growth-plan entries naturally map to: future component docs as new `plugin/` modules land (e.g. mutation harness in v0.4, new agents added to catalog). + +**`## Related` footer pattern** (catalog-schema/SKILL.md lines 97-103): +```markdown +## Related + +- `docs/HARNESS.md` §1.1 (plugin/catalog/ layout), §5.2 (skill table), §4.2 (catalog-auditor + security-engineer rubrics). +- ADRs: 003 (no default agents), 004 (per-user npm prefix), 008 (Commander.js CLI that consumes this catalog). +- Subagents: `catalog-auditor` (every catalog PR), `security-engineer` (install-recipe injection review). +- Sibling skills: `agentlinux-installer` (...), `behavior-test-contract` (...), `qemu-harness` (...). +- Validator: `plugin/cli/scripts/validate-catalog.mjs`. +``` + +**Pattern to copy:** Bulleted list grouped by category — HARNESS pointers, ADRs by number, subagents that consume this skill, sibling skills, scripts/files. Each line has the reference + parenthetical context. For `dev-docs/SKILL.md`, the categories trivially become: HARNESS pointers, ADR (014 may be added per CONTEXT §"Claude's Discretion"), Subagent (`dev-docs-auditor`, the new reviewer), sibling skills (`agentlinux-installer`, `catalog-schema`, `review`), top-level docs (`docs/internals/README.md`). + +**Skill content (dev-docs-specific):** the skill body must enumerate the docs contract per CONTEXT §"Maintenance Tooling — Skill, Reviewer, CLAUDE.md (NO new hook)": + +- Per-component file structure (file path + what each must contain — problem / answer / value vs naive / optional worked example / cross-links footer). +- Product-perspective lens (the AL-22 litmus test: "what value does AgentLinux add for X"). +- When to update (when source changes meaningfully under the source-to-doc dispatch table; not on typos / refactors). +- What each doc must contain (the four-part contract from CONTEXT). +- The source-path → doc-path dispatch table (this is the registry the `dev-docs-auditor` reads). + +--- + +### `CLAUDE.md` (modify) + +**Analog:** the existing `CLAUDE.md` itself — specifically the `## Review Loop` table and the `## Pointers` bullet list. + +**Existing `## Review Loop` table** (CLAUDE.md lines 53-59): +```markdown +Reviewers applied by file type: + +- Bash → `bash-engineer`, `security-engineer`, `qa-engineer` +- TS/JS → `node-engineer`, `security-engineer`, `qa-engineer` +- Bats → `qa-engineer`, `behavior-coverage-auditor` +- Catalog recipes → `catalog-auditor`, `security-engineer` +- Docs → `technical-writer`, `fact-checker` +``` + +**Pattern to apply:** Per CONTEXT §"CLAUDE.md wiring" the new reviewer is wired by extending each existing row whose paths are under the dev-docs trigger set, not by adding a new "Internal docs" row. Concretely: the bullet shape is `- <file-type> → <comma-separated reviewer list>`. The `dev-docs-auditor` adds to: +- `Bash` (covers `plugin/bin/`, `plugin/lib/`, `plugin/provisioner/`, `packaging/curl-installer/`) +- `TS/JS` (covers `plugin/cli/src/`) +- `Catalog recipes` (covers `plugin/catalog/`) + +So the modified rows look like: +```markdown +- Bash → `bash-engineer`, `security-engineer`, `qa-engineer`, `dev-docs-auditor` +- TS/JS → `node-engineer`, `security-engineer`, `qa-engineer`, `dev-docs-auditor` +- Catalog recipes → `catalog-auditor`, `security-engineer`, `dev-docs-auditor` +``` + +(`Bats` and `Docs` rows are left unchanged — bats tests do not have an internals doc; docs reviewers already exist.) + +**Existing `## Pointers` bullet list** (CLAUDE.md lines 84-94): +```markdown +- `@.planning/ROADMAP.md` — phase plan (1 Harness → 2 Installer → 3 Node → 4 CLI → 5 Agents → 6 Release) +- `@.planning/REQUIREMENTS.md` — behavior contract (BHV/RT/AGT/CLI/CAT/INST/HRN/TST/DOC) +- `@docs/HARNESS.md` — authoritative harness spec (...) +- `@docs/research/v0.3.0/SUMMARY.md` — v0.3.0 research synthesis +- `@docs/decisions/` — ADR-001..ADR-010 +- Skills (arrive Plan 01-04): `.claude/skills/agentlinux-installer/`, + `.claude/skills/behavior-test-contract/`, `.claude/skills/catalog-schema/`, + `.claude/skills/qemu-harness/`, `.claude/skills/review/` +``` + +**Pattern to apply:** Add a new bullet for the internals tree (e.g. `- @docs/internals/ — per-component developer docs (what each AgentLinux surface does and why)`) and extend the trailing `Skills (...)` bullet's enumeration with `.claude/skills/dev-docs/`. Keep bullet shape consistent (leading `@`-prefixed path for top-level pointers; flat path for the comma-separated skill enumeration). + +--- + +### `README.md` (modify — top-level) + +**Analog:** the existing `README.md` `## Stability model` section (lines 67-83) and `## Links` section (lines 136-143). + +**Existing `## Stability model` lede** (README.md lines 67-82): +```markdown +## Stability model + +AgentLinux ships *curated combos*: every catalog agent is pinned to an exact +version that we test together end-to-end (Docker × {22.04, 24.04, 26.04} + +QEMU × {22.04, 24.04, 26.04}) before each release. ... + +See [docs/STABILITY-MODEL.md](docs/STABILITY-MODEL.md) for the user-facing +one-page summary and [docs/decisions/011-stability-first-version-pinning.md](docs/decisions/011-stability-first-version-pinning.md) +for the full architectural decision record. +``` + +**Pattern to apply** (per CONTEXT §"Top-level README discoverability" → "Why AgentLinux — concepts" link): Add a new H2 section `## Why AgentLinux — concepts` (or similar — header text is implementer's call per CONTEXT §"Claude's Discretion") modeled on the existing `## Stability model` shape: 2-3 line lede that names the concept-doc series, then a `See [docs/internals/README.md](docs/internals/README.md) for ...` line. Place above the existing `## Stability model` section so the conceptual story flows: install → verify → uninstall → **why** (internals) → stability model → escape hatches. + +**Existing `## Links` section** (README.md lines 136-143): +```markdown +## Links + +- **Source + issues:** https://github.com/Roo4L/Agent-Linux +- **Releases:** https://github.com/Roo4L/Agent-Linux/releases +- **Architecture decisions:** [docs/decisions/](docs/decisions/) +- **Test harness spec:** [docs/HARNESS.md](docs/HARNESS.md) +- **Stability model (user-facing):** [docs/STABILITY-MODEL.md](docs/STABILITY-MODEL.md) +- **Landing page:** https://agentlinux.org +``` + +**Pattern to apply:** Add a row `- **Internals (developer docs):** [docs/internals/](docs/internals/)` with the bold-label-em-dash-bracketed-link convention. Place it adjacent to the "Architecture decisions" row (both are repo-internal reference material). + +--- + +## Shared Patterns + +### Frontmatter discipline (reviewer agents and skills) + +**Source:** `.claude/agents/*.md` (six files), `.claude/skills/*/SKILL.md` (six files) + +**Apply to:** `.claude/agents/dev-docs-auditor.md`, `.claude/skills/dev-docs/SKILL.md` + +```markdown +--- +name: <kebab-case-slug-matching-filename> +description: <single long sentence stating focus + Use when/Use on/Use with directive with concrete path globs> +[tools: Read, Grep, Glob, Bash] # subagents only — skills omit this key +--- +``` + +The description must be one sentence that the Claude Code subagent dispatcher can match against a query. No Markdown inside frontmatter values. Keep ≤ 400 characters. + +### "Free-form summary, no BLOCK/FLAG/PASS" output contract + +**Source:** `docs/HARNESS.md` §4.3 → echoed in every reviewer's `## Output format` section. + +**Apply to:** `.claude/agents/dev-docs-auditor.md` `## Output format` + +The phrase to copy (verbatim, with reviewer name swapped): +``` +Free-form summary per HARNESS.md §4.3. File:line citations, short sentences, no rigid BLOCK/FLAG/PASS scheme. +``` + +Followed by a fenced example block of `## dev-docs-auditor review summary` shape, ending with a one-line closing motto: `Main agent triages.` (or near equivalent — `Main agent triages; reviewer documents.` is the catalog-auditor variant). + +### "Common gotchas (AgentLinux-specific)" section + +**Source:** all six existing reviewer agents have this H2 with bulleted gotcha entries written in `**lead clause.** explanation` form. + +**Apply to:** `.claude/agents/dev-docs-auditor.md` + +For dev-docs the gotchas distill the CONTEXT §"Specifics" + §"Deferred Ideas" cautions, e.g.: +- **Source-line cross-references slipped in.** CONTEXT §"Depth" rules them out for the initial cut. Flag. +- **Implementation detail leaking through.** "Uses Commander.js" is wrong frame; "ships a registry CLI" is right frame. Product perspective trumps tool name. +- **A new component shipped without a doc.** When a new top-level surface lands under `plugin/` (new provisioner, new CLI command class, new catalog backend), the matching `docs/internals/<surface>.md` should ship in the same PR. + +### Cross-link footer convention + +**Source:** end of every existing reviewer, every existing skill, `docs/STABILITY-MODEL.md`. + +**Apply to:** all 11 new docs files + `.claude/agents/dev-docs-auditor.md` + `.claude/skills/dev-docs/SKILL.md`. + +`## Related` H2 → bullet list. Each bullet is `- [<readable name>](<path>) — <one-sentence what's there>`. Three to five entries. Per CONTEXT §"Depth": no `path:line` deep links in the docs/internals/ files; ADR mentions in prose are fine, links are optional. + +## No Analog Found + +None — every new file has a workable analog in the existing codebase. The `docs/internals/` tree has no exact prior (it's a new directory), but `docs/STABILITY-MODEL.md` is a strong single-topic concept-doc analog and `docs/README.md` is the exact analog for `docs/internals/README.md`. + +## Metadata + +**Analog search scope:** +- `.claude/agents/` — six existing reviewers (all read) +- `.claude/skills/` — six existing skills (four fully read, two cross-referenced) +- `docs/` — `HARNESS.md`, `STABILITY-MODEL.md`, `README.md`, `decisions/000-template.md`, `decisions/004-per-user-npm-prefix.md`, `decisions/010-review-loop-via-claude-md.md`, `decisions/012-agent-user-full-sudo.md` +- top-level `README.md`, `CLAUDE.md` + +**Files scanned:** ~25 +**Pattern extraction date:** 2026-05-09 diff --git a/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-VERIFICATION.md b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-VERIFICATION.md new file mode 100644 index 0000000..f0c438f --- /dev/null +++ b/.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-VERIFICATION.md @@ -0,0 +1,130 @@ +--- +phase: 12-developer-documentation-for-installer-runtime-and-cli-al-22 +verified: 2026-05-09T00:00:00Z +status: passed +score: 7/7 must-haves verified +overrides_applied: 0 +--- + +# Phase 12: Developer documentation for installer, runtime, and CLI (AL-22) Verification Report + +**Phase Goal:** Ship developer-facing internals documentation (`docs/internals/`) explaining what each AgentLinux component does and why, plus a reviewer agent + skill that keep the docs in sync via the existing review loop. No new stop-hook is allowed. Audience is the project owner (product-perspective lens; insight source for blog/email/website copy). + +**Verified:** 2026-05-09 +**Status:** passed +**Re-verification:** No — initial verification + +## Goal Achievement + +### Observable Truths + +| # | Truth | Status | Evidence | +| --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | A reader landing on `docs/internals/README.md` sees a one-paragraph What-AgentLinux-is lede plus a `## Components` H2 with a TOC linking to all 9 component docs (DOC-01) | ✓ VERIFIED | `docs/internals/README.md` lines 3-8 carry the lede; `## Components` H2 at line 10; 9 link entries (lines 14-35) exactly match the 9 files on disk | +| 2 | All 9 component docs follow the four-section spine (`## The problem` → `## What AgentLinux does` → `## Value vs the naive approach` → `## Related`), with `## Value vs the naive approach` numbered + bold lead clause (DOC-02) | ✓ VERIFIED | Grep across `docs/internals/{installer,agent-user,sudo-drop-in,nodejs-runtime,claude-code,gsd,playwright,registry-cli,catalog}.md` shows all 4 mandatory H2s in each; "Value vs the naive approach" sections all use numbered lists with `**bold lead clause**` | +| 3 | No source-line cross-references (`file_path:42`-style deep links) anywhere in `docs/internals/` (CONTEXT.md §"Depth") | ✓ VERIFIED | `grep -nE '\.(sh\|ts\|js\|md):[0-9]+' docs/internals/*.md` returns no matches | +| 4 | A new project-scoped reviewer agent (`dev-docs-auditor`) exists with read-only tools (Read, Grep, Glob, Bash) and is registered in the CLAUDE.md "Review Loop" reviewer-by-file-type table on Bash, TS/JS, and Catalog rows (DOC-03) | ✓ VERIFIED | `.claude/agents/dev-docs-auditor.md` frontmatter `tools: Read, Grep, Glob, Bash`; CLAUDE.md lines 55, 56, 58 add `dev-docs-auditor` on Bash + TS/JS + Catalog rows; Bats and Docs rows unchanged | +| 5 | A new project-scoped skill (`.claude/skills/dev-docs/SKILL.md`) documents the four-section contract + source-path → doc-path dispatch table covering all 9 component docs, and is enumerated in CLAUDE.md "Pointers" (DOC-04) | ✓ VERIFIED | `.claude/skills/dev-docs/SKILL.md` lines 31-42 carry the four-section contract; lines 48-59 carry the 10-row dispatch table; CLAUDE.md line 93 adds `.claude/skills/dev-docs/` to the Pointers skills list | +| 6 | Top-level `README.md` gains a "Why AgentLinux — concepts" H2 section linking `docs/internals/README.md` AND a `## Links` row labelled `**Internals (developer docs):**` (DOC-05) | ✓ VERIFIED | `README.md` line 67 has `## Why AgentLinux — concepts` H2; line 76 links `docs/internals/README.md`; line 154 has `**Internals (developer docs):** [docs/internals/](docs/internals/)` | +| 7 | NO new stop-hook — `.claude/hooks/dev-docs-reminder.sh` does NOT exist; `.claude/settings.json` and `.claude/settings.local.json` were NOT modified across the Phase 12 commit range (DOC-06) | ✓ VERIFIED | `ls .claude/hooks/dev-docs-reminder.sh` returns ENOENT; `git log --oneline 5df2429..HEAD -- .claude/settings.json .claude/settings.local.json` returns empty (no commits touched either file) | +| 8 | ADR-015 (`docs/decisions/015-developer-internals-docs.md`) records the design decision (no new hook + embed in review loop) with Status `Accepted` (DOC-07) | ✓ VERIFIED | `docs/decisions/015-developer-internals-docs.md` exists; line "**Status:** Accepted"; `## Decision` H2 declares "Embed `dev-docs-auditor` ... in the existing review loop. Do NOT add a third stop-hook." | + +**Score:** 8/8 truths verified (collapses 1:1 onto DOC-01..DOC-07 plus the supporting "no source-line refs" CONTEXT.md constraint). + +### Required Artifacts + +| Artifact | Expected | Status | Details | +| ----------------------------------------------------------------- | ------------------------------------------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------- | +| `docs/internals/README.md` | Lede + `## Components` H2 + 9-entry TOC | ✓ VERIFIED | 49 lines; lede lines 3-8; TOC lines 14-35 (9 entries matching the 9 files on disk) | +| `docs/internals/installer.md` | Four-section spine | ✓ VERIFIED | 114 lines; all 4 mandatory H2s present + `## Worked example` optional 5th | +| `docs/internals/agent-user.md` | Four-section spine | ✓ VERIFIED | 118 lines; all 4 mandatory H2s + worked example | +| `docs/internals/sudo-drop-in.md` | Four-section spine | ✓ VERIFIED | 123 lines; all 4 mandatory H2s + worked example | +| `docs/internals/nodejs-runtime.md` | Four-section spine | ✓ VERIFIED | 141 lines; all 4 mandatory H2s + worked example | +| `docs/internals/claude-code.md` | Four-section spine | ✓ VERIFIED | 121 lines; all 4 mandatory H2s + worked example | +| `docs/internals/gsd.md` | Four-section spine | ✓ VERIFIED | 116 lines; all 4 mandatory H2s + worked example | +| `docs/internals/playwright.md` | Four-section spine | ✓ VERIFIED | 119 lines; all 4 mandatory H2s + worked example | +| `docs/internals/registry-cli.md` | Four-section spine | ✓ VERIFIED | 142 lines; all 4 mandatory H2s + worked example | +| `docs/internals/catalog.md` | Four-section spine | ✓ VERIFIED | 153 lines; all 4 mandatory H2s + worked example | +| `.claude/agents/dev-docs-auditor.md` | Reviewer agent with read-only tools | ✓ VERIFIED | Frontmatter `tools: Read, Grep, Glob, Bash`; description triggers on the 6 source paths | +| `.claude/skills/dev-docs/SKILL.md` | Four-section contract + 10-row dispatch table | ✓ VERIFIED | Lines 31-42 (contract), lines 48-59 (dispatch table covers all 9 component docs) | +| `docs/decisions/015-developer-internals-docs.md` | ADR with `## Decision` and Status `Accepted` | ✓ VERIFIED | Status `Accepted`; `## Decision` H2 captures "no third stop-hook" + "embed in review loop" | +| `CLAUDE.md` Review Loop table | Bash + TS/JS + Catalog rows extended with `dev-docs-auditor` | ✓ VERIFIED | CLAUDE.md lines 55-58 confirm extension; Bats and Docs rows unchanged | +| `CLAUDE.md` Pointers list | Adds `.claude/skills/dev-docs/` | ✓ VERIFIED | Line 93 lists the new skill alongside existing 6 | +| `README.md` "Why AgentLinux — concepts" H2 + `## Links` row | H2 link + Links row both pointing to `docs/internals/` | ✓ VERIFIED | Line 67 H2; line 76 links `docs/internals/README.md`; line 154 `**Internals (developer docs):**` row | +| `.claude/hooks/dev-docs-reminder.sh` | MUST NOT exist | ✓ VERIFIED | `ls` returns ENOENT — confirms DOC-06 constraint | +| `.claude/settings.json` | MUST NOT be modified by Phase 12 commits (range `5df2429..HEAD`) | ✓ VERIFIED | `git log --oneline 5df2429..HEAD -- .claude/settings.json` returns empty | +| `.claude/settings.local.json` | MUST NOT be modified by Phase 12 commits | ✓ VERIFIED | `git log --oneline 5df2429..HEAD -- .claude/settings.local.json` returns empty | + +### Key Link Verification + +| From | To | Via | Status | Details | +| --------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------- | +| `docs/internals/README.md` | 9 component docs | Markdown links in `## Components` TOC | ✓ WIRED | All 9 link targets resolve to existing files on disk | +| `README.md` | `docs/internals/` | "Why AgentLinux — concepts" H2 + `## Links` row | ✓ WIRED | Both link forms point to existing dir/file | +| `CLAUDE.md` Review Loop table | `dev-docs-auditor` agent | Bash + TS/JS + Catalog row extensions | ✓ WIRED | Reviewer name appears in 3 rows; agent file exists at expected path | +| `CLAUDE.md` Pointers | `.claude/skills/dev-docs/` | Skills list line | ✓ WIRED | Skill dir + SKILL.md exist | +| `dev-docs-auditor` agent | `dev-docs` skill (rubric source) | Body explicitly cites `.claude/skills/dev-docs/SKILL.md` | ✓ WIRED | Agent line 32 names skill as "copy-of-truth" | +| `dev-docs` skill dispatch table | 9 component docs | Source-path → doc-path mapping | ✓ WIRED | All 9 doc paths in dispatch table (lines 50-58) resolve to existing files | +| ADR-015 | ADR-010 precedent | `Companion to:` header + Reference list | ✓ WIRED | ADR-015 line 6 cites ADR-010; ADR-010 file exists at `docs/decisions/010-review-loop-via-claude-md.md` | +| REQUIREMENTS.md `## Post-v0.4.0 Addendum` | Phase 12 DOC-01..DOC-07 | H2 + traceability table | ✓ WIRED | Line 57 H2; lines 63-69 enumerate DOC-01..DOC-07 (all checked); line 112 traceability table | + +### Data-Flow Trace (Level 4) + +Not applicable — Phase 12 ships markdown documentation + a reviewer agent + a skill + an ADR. None of the artifacts render dynamic data; they are static reference material consumed by humans and the review loop. + +### Behavioral Spot-Checks + +Phase 12 produces no runnable code. Step 7b: SKIPPED (no runnable entry points). + +The dev-docs-auditor reviewer is invoked by the existing review loop (CLAUDE.md routing table) — its actual firing on a future plugin/ change is out of scope for verification (the wiring is verified above; the loop's invocation is verified by ADR-010's existing review-loop precedent already in production). + +### Requirements Coverage + +| Requirement | Source Plan | Description | Status | Evidence | +| ----------- | ------------------------------------------------------ | ------------------------------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------- | +| DOC-01 | 12-01-PLAN.md, 12-05-PLAN.md | docs/internals/README.md exists with overview + TOC linking 9 docs | ✓ SATISFIED | `docs/internals/README.md` lede + `## Components` TOC with 9 entries (Truth #1) | +| DOC-02 | 12-01-PLAN.md, 12-02-PLAN.md, 12-05-PLAN.md | 9 component docs follow four-section contract + bold lead clause | ✓ SATISFIED | All 9 files; all 4 mandatory H2s; numbered + bold lead clause (Truth #2) | +| DOC-03 | 12-03-PLAN.md, 12-04-PLAN.md, 12-05-PLAN.md | dev-docs-auditor reviewer registered in CLAUDE.md on Bash + TS/JS + Catalog | ✓ SATISFIED | `.claude/agents/dev-docs-auditor.md` + CLAUDE.md lines 55, 56, 58 (Truth #4) | +| DOC-04 | 12-03-PLAN.md, 12-05-PLAN.md | `.claude/skills/dev-docs/SKILL.md` exists, documents docs contract | ✓ SATISFIED | Skill body includes four-section contract + 10-row dispatch table; Pointers entry in CLAUDE.md (Truth #5) | +| DOC-05 | 12-04-PLAN.md, 12-05-PLAN.md | Top-level README.md links to docs/internals/ via "Why AgentLinux — concepts" | ✓ SATISFIED | README.md line 67 H2 + line 76 link + line 154 Links row (Truth #6) | +| DOC-06 | 12-03-PLAN.md, 12-05-PLAN.md | NO new stop-hook; settings.json unchanged | ✓ SATISFIED | `dev-docs-reminder.sh` does not exist; settings.{json,local.json} not modified by Phase 12 commits (Truth #7) | +| DOC-07 | 12-05-PLAN.md | ADR-015 records the design decision | ✓ SATISFIED | `docs/decisions/015-developer-internals-docs.md`, Status `Accepted`, `## Decision` H2 names the no-hook + embed-in-loop call (Truth #8) | + +**No orphaned requirements.** REQUIREMENTS.md `### Post-v0.4.0 Addendum Traceability` table maps Phase 12 → DOC-01..DOC-07 (7 reqs); all 7 are claimed by at least one Phase 12 plan; all 7 are satisfied. + +**v0.4.0 milestone count check:** REQUIREMENTS.md preserves `**Total v0.4.0** | | **21**` (line 110-111 area) — the addendum is tracked in a separate `### Post-v0.4.0 Addendum Traceability` table (line 108+), so the v0.4.0 milestone gate count remains honest at 21. + +### Anti-Patterns Found + +No blocking anti-patterns. Spot-checks across all 9 component docs + reviewer + skill + ADR found: + +| File | Line | Pattern | Severity | Impact | +| ------------------------------------- | ----- | --------------------- | -------- | ----------------------------------------------- | +| (none) | — | TODO/FIXME/PLACEHOLDER | — | None of the docs contain stub markers | +| (none) | — | source-line deep links | — | CONTEXT.md §"Depth" honored in all 9 component docs | +| (none) | — | mandatory mermaid diagrams | — | Zero mermaid blocks across all 9 docs (CONTEXT.md §"Diagrams" honored — sparingly = none used) | + +### Human Verification Required + +None. All 7 DOC requirements are programmatically verifiable (file existence + grep for structural elements + git log for the no-modification constraint). The verification is content-shape based, not behavior-based — no real-time, visual, or external-service dependency. + +The dev-docs-auditor reviewer's actual *firing* on future plugin/ source PRs is out of scope for this verification; the wiring is verified, and the review-loop invocation mechanism is the same precedent ADR-010 already established for the six existing reviewers. + +### Gaps Summary + +No gaps. Phase 12 ships a complete, well-structured developer-internals documentation tree with all four wiring surfaces (review-loop reviewer agent, dev-docs skill, top-level README discoverability link, ADR-015 design record) in place. The phase honors every constraint from 12-CONTEXT.md: + +- Audience and tone (project owner first, product-perspective lens, excerpt-friendly for blog/marketing copy) ✓ +- Layout (`docs/internals/` sibling to `decisions/`, `research/`, `audits/`) ✓ +- Per-component structure (problem → answer → value vs naive → related, with optional worked example) ✓ +- Depth ceiling (no source-line cross-references; ADRs may be named in prose but no link discipline) ✓ +- Diagram discipline (Mermaid sparingly = zero used; prose suffices everywhere) ✓ +- No new stop-hook (DOC-06 is the load-bearing user constraint; verified by both file-absence and git-log) ✓ +- ADR-015 captures the design decision and the explicit reasoning for not adding a third hook ✓ + +The 12-AUDIT.md GATE: GREEN finding is independently re-verified by this report. + +--- + +_Verified: 2026-05-09_ +_Verifier: Claude (gsd-verifier)_ diff --git a/CLAUDE.md b/CLAUDE.md index e5c221b..3909b1e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -52,15 +52,21 @@ hooks with a `stop_hook_active` guard are allowed. See Reviewers applied by file type: -- Bash → `bash-engineer`, `security-engineer`, `qa-engineer`, `ai-deslop` -- TS/JS → `node-engineer`, `security-engineer`, `qa-engineer`, `ai-deslop` +- Bash → `bash-engineer`, `security-engineer`, `qa-engineer`, `ai-deslop`, `dev-docs-auditor` +- TS/JS → `node-engineer`, `security-engineer`, `qa-engineer`, `ai-deslop`, `dev-docs-auditor` - Bats spec (`tests/bats/*.bats`) → `qa-engineer`, `behavior-coverage-auditor` (the spec is the spec — no `ai-deslop`) - Bats helpers + Docker/QEMU harness → `qa-engineer`, `bash-engineer`, `ai-deslop` -- Catalog recipes → `catalog-auditor`, `security-engineer`, `ai-deslop` +- Catalog recipes → `catalog-auditor`, `security-engineer`, `ai-deslop`, `dev-docs-auditor` - Docs → `technical-writer`, `fact-checker`, `ai-deslop` (skip for ADRs and research summaries) +`dev-docs-auditor` keeps `docs/internals/<component>.md` in sync when changes +touch `plugin/bin/`, `plugin/lib/`, `plugin/provisioner/`, `plugin/cli/src/`, +`plugin/catalog/`, or `packaging/curl-installer/`. Skips on pure refactors, +typos, or comment-only changes. See `.claude/skills/dev-docs/SKILL.md` for the +docs contract and the source-path → doc-path dispatch table. + Main agent owns triage: fix what's valid, skip what's noise, iterate until the remaining comments are not actionable. @@ -94,10 +100,13 @@ bash tests/harness/run.sh # Run harness meta-tests (Phase 1) - `@.planning/REQUIREMENTS.md` — behavior contract (BHV/RT/AGT/CLI/CAT/INST/HRN/TST/DOC) - `@docs/HARNESS.md` — authoritative harness spec (§1 layout, §2 docs, §3 systems, §4 review, §5 skills, §6 this file, §7 checklist, §8 criteria) - `@docs/research/v0.3.0/SUMMARY.md` — v0.3.0 research synthesis -- `@docs/decisions/` — ADR-001..ADR-010 -- Skills (arrive Plan 01-04): `.claude/skills/agentlinux-installer/`, +- `@docs/decisions/` — ADR-001..ADR-015 (ADR-015: developer internals docs) +- `@docs/internals/` — developer documentation (what each AgentLinux component + does and why; product-perspective lens; insight source for blog/email/website) +- Skills: `.claude/skills/agentlinux-installer/`, `.claude/skills/behavior-test-contract/`, `.claude/skills/catalog-schema/`, - `.claude/skills/qemu-harness/`, `.claude/skills/review/` + `.claude/skills/dev-docs/`, `.claude/skills/qemu-harness/`, + `.claude/skills/review/`, `.claude/skills/workspace-cleanup/` --- *Last updated: 2026-04-18 — Phase 1 Harness Setup (Plan 01-01).* diff --git a/README.md b/README.md index 692db70..4c46a03 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,19 @@ preserved by default; add `--remove-nodejs` to drop the NodeSource apt list and the `nodejs` package as well. A re-run of the curl installer after `--purge` starts from a clean slate — there is no state hidden elsewhere. +## Why AgentLinux — concepts + +Each AgentLinux surface — installer, agent user, sudo drop-in, Node.js runtime, +the agent catalog, the registry CLI, and the curated agent set (Claude Code, +GSD, Playwright) — solves a specific bug class that the naive `sudo npm +install -g` path leaves broken. The internals docs walk through one component +at a time: what the problem is, what AgentLinux does about it, and the value +vs. the naive approach. + +See [docs/internals/README.md](docs/internals/README.md) for the index — nine +short component docs, each answering "what value does AgentLinux provide +here" in under a minute. + ## Stability model AgentLinux ships *curated combos*: every catalog agent is pinned to an exact @@ -138,6 +151,7 @@ endorsement. - **Source + issues:** https://github.com/Roo4L/Agent-Linux - **Releases:** https://github.com/Roo4L/Agent-Linux/releases - **Architecture decisions:** [docs/decisions/](docs/decisions/) +- **Internals (developer docs):** [docs/internals/](docs/internals/) - **Test harness spec:** [docs/HARNESS.md](docs/HARNESS.md) - **Stability model (user-facing):** [docs/STABILITY-MODEL.md](docs/STABILITY-MODEL.md) - **Landing page:** https://agentlinux.org diff --git a/docs/decisions/015-developer-internals-docs.md b/docs/decisions/015-developer-internals-docs.md new file mode 100644 index 0000000..1db7a5c --- /dev/null +++ b/docs/decisions/015-developer-internals-docs.md @@ -0,0 +1,67 @@ +# 015: Developer internals docs — embed in review loop, no new hook + +**Status:** Accepted +**Date:** 2026-05-09 +**Drives:** DOC-01, DOC-02, DOC-03, DOC-04, DOC-05, DOC-06, DOC-07 +**Companion to:** ADR-010 (review loop via CLAUDE.md, refined 2026-05-02) + +## Context + +AL-22 ("Create documentation on what AgentLinux does") asks for developer-facing internal documentation explaining what each AgentLinux component does and why — with a product-perspective lens. The litmus question is *"What value does AgentLinux provide in installing GSD instead of using the GSD installation from npm directly?"* The docs must give the project owner a 60-second answer per surface and double as raw material for blog posts, marketing emails, and the agentlinux.org landing page. + +Two adjacent decisions had to land alongside the docs themselves: + +1. **How to keep the docs in sync with the source.** Documentation that drifts is worse than no documentation — it actively misleads. The codebase already has a review loop (CLAUDE.md "Review Loop" instruction + `.claude/agents/<reviewer>.md` subagents + ADR-010's reminder-hook refinement) that catches plugin/ source changes; it needs to learn about docs/internals/ too. +2. **Whether to add a third stop-hook.** The codebase has two reminder hooks today — `.claude/hooks/review-reminder.sh` (review-loop nudge) and `.claude/hooks/session-tracker-reminder.sh` (Jira nudge), both wired per the ADR-010 2026-05-02 refinement. A naive solution to docs sync would be a third hook. The maintainer pushed back: a third hook multiplies reminder noise without adding value, because the existing review-reminder already triggers the review loop and the review loop already routes plugin/ changes to reviewers. + +## Decision + +**Embed `dev-docs-auditor` (a new project-scoped reviewer subagent) in the existing review loop. Do NOT add a third stop-hook.** + +Specifically: + +1. Ship `docs/internals/` — one index doc + nine per-component docs (installer, agent-user, sudo-drop-in, nodejs-runtime, claude-code, gsd, playwright, registry-cli, catalog). Each follows a four-section contract: problem → AgentLinux's answer → value vs the naive approach → related cross-links. No source-line deep links; ADR mentions in prose are optional. +2. Ship `.claude/agents/dev-docs-auditor.md` — a read-only reviewer (`tools: Read, Grep, Glob, Bash`) that consumes a new `.claude/skills/dev-docs/SKILL.md` skill (the source-path → doc-path dispatch table + the four-section contract). +3. Wire the reviewer into the existing CLAUDE.md "Review Loop" reviewer-by-file-type table by extending three existing rows (Bash, TS/JS, Catalog recipes) — NOT by adding a new "Internal docs" row. Keeping the wiring inside the existing routing keeps the surface flat. +4. Make `docs/internals/` discoverable from the top-level `README.md` (a "Why AgentLinux — concepts" section + a "## Links" row). +5. NO new file under `.claude/hooks/`. NO edit to `.claude/settings.json`. + +## Consequences + +### What changes + +- The review loop now flags missing or stale `docs/internals/<component>.md` updates whenever `plugin/bin/`, `plugin/lib/`, `plugin/provisioner/`, `plugin/cli/src/`, `plugin/catalog/`, or `packaging/curl-installer/` changes — without any new orchestration plumbing. +- The internals docs are explicitly *reference material*, not a release gate. The `dev-docs-auditor` does not gate phase close (no `## Exit behavior` section in its body); it documents drift for the main agent to triage. +- Skip conditions are explicit: pure refactors, comment-only changes, typo fixes, formatting-only diffs, `.planning/`-only changes, and tests-only changes do not require docs updates. + +### Why no third hook + +ADR-010's original 2026-04-18 critique — "subjective LLM review in a Stop hook wastes tokens" — applied to hooks that *spawn* reviewers. The 2026-05-02 refinement permits *reminder* hooks (one-shot via `stop_hook_active`, no reviewer spawn). A third reminder hook for docs sync was considered and rejected because: + +- The existing `review-reminder.sh` already nudges Claude to run the review loop. Once the review loop runs, the reviewer-by-file-type routing table already routes plugin/ changes through `dev-docs-auditor`. A second nudge for the same loop is redundant. +- Each reminder hook costs at most one extra "block + re-stop" round-trip per turn (per ADR-010 §"Refinement"). Two reminders cost two round-trips; three cost three. The cost is real even though small. +- Reminder noise has a usability cost too — Claude reads each reminder reason and decides whether to act. More reasons mean longer reminder text means more turns where the reminder is mostly skipped, which trains the loop to ignore reminders generally. +- The maintainer drew the line at "no third hook" explicitly. Two hooks is a deliberate stopping point, not an accident. + +### Why a flat extend, not a new CLAUDE.md section + +Adding a top-level CLAUDE.md H2 like `## Internal docs review` would split the review-routing surface into two places (the existing "Review Loop" table + the new section). Future contributors would have to read both to know which reviewers fire on which file types. Extending three existing rows keeps the routing in one place. + +### Reversibility + +If `docs/internals/` proves not worth the maintenance overhead, the unwind is small: + +- Delete `docs/internals/`. +- Remove `dev-docs-auditor` from the three CLAUDE.md "Review Loop" rows. +- Delete `.claude/agents/dev-docs-auditor.md` and `.claude/skills/dev-docs/`. +- Drop the README.md "Why AgentLinux — concepts" section + Links row. + +No hook to retract, no settings.json edit to revert. The reversibility cost is bounded by design. + +## References + +- ADR-010 — Review loop via CLAUDE.md (the precedent this ADR builds on; refined 2026-05-02 to permit reminder hooks with `stop_hook_active` guard). +- `.planning/phases/12-developer-documentation-for-installer-runtime-and-cli-al-22/12-CONTEXT.md` — the user-decisions context that drove this design. +- `docs/internals/README.md` — the index doc this ADR drives. +- `.claude/agents/dev-docs-auditor.md` — the reviewer this ADR drives. +- `.claude/skills/dev-docs/SKILL.md` — the skill this ADR drives. diff --git a/docs/internals/README.md b/docs/internals/README.md new file mode 100644 index 0000000..853e4d3 --- /dev/null +++ b/docs/internals/README.md @@ -0,0 +1,50 @@ +# AgentLinux Internals + +AgentLinux provisions a dedicated `agent` user with a correctly-owned Node.js +runtime so agent tools — Claude Code, GSD, Playwright — self-update without +EACCES, recursive shims, or `sudo` fights. One curl-pipe-bash command on a +clean Ubuntu host turns it into an environment where autonomous coding agents +just work. Each doc in this directory explains what one AgentLinux surface +does and why — the value vs the naive approach you'd otherwise reach for. + +## Components + +The four foundational layers (everything below the agent catalog): + +- [Installer](installer.md) — the curl-pipe-bash entrypoint that downloads, + verifies, and executes the AgentLinux release tarball. +- [Agent user](agent-user.md) — the dedicated `agent` user with a per-user + npm prefix that makes self-update Just Work. +- [Sudo drop-in](sudo-drop-in.md) — the `/etc/sudoers.d/agentlinux` NOPASSWD + grant that lets autonomous agents reach into the host without stalling on + password prompts. +- [Node.js runtime](nodejs-runtime.md) — system Node.js LTS plus a per-user + npm prefix and PATH wired across every invocation mode. + +The agent catalog and registry CLI: + +- [Claude Code](claude-code.md) — Anthropic's coding agent, installed via the + upstream native installer into the agent's own tree. +- [GSD](gsd.md) — `get-shit-done-cc`, the planning workflow CLI, installed + via npm into the agent's per-user prefix. +- [Playwright](playwright.md) — browser automation with chromium, installed + via npm as `@playwright/cli` plus a one-shot `playwright-cli install --skills` + that pulls down the chromium binary and the apt-layer browser dependencies. +- [Registry CLI](registry-cli.md) — the `agentlinux` command that drives + list / install / remove / upgrade / pin against the catalog. +- [Catalog](catalog.md) — the curated, version-pinned manifest of available + agents, snapshotted alongside each release tarball. + +## Audience + +These docs are written for the project owner first and future contributors +second. They are deliberately product-perspective rather than line-by-line +implementation notes — the goal is a 60-second answer to "what does +AgentLinux do for surface X." The same prose is intended to be excerpt-friendly +source material for blog posts, marketing emails, and the agentlinux.org +landing page; if a paragraph reads cleanly out of context, that is on purpose. + +--- + +See also: [../README.md](../README.md) (top-level install + verify story) and +[../HARNESS.md](../HARNESS.md) (authoritative project harness spec). diff --git a/docs/internals/agent-user.md b/docs/internals/agent-user.md new file mode 100644 index 0000000..8b12d95 --- /dev/null +++ b/docs/internals/agent-user.md @@ -0,0 +1,117 @@ +# Agent user + +AgentLinux provisions a dedicated `agent` user with a per-user npm prefix. +Every agent tool — Claude Code, GSD, Playwright — installs into and updates +from the agent's own home directory. No EACCES, no `sudo` fights, no +recursive shims at `/usr/local/bin/`. The agent owns its tools so it can +update them. + +## The problem + +The bug class AgentLinux exists to eliminate is the EACCES + recursive-shim +loop that follows from `sudo npm install -g`. The sequence is short and +reliably catastrophic: an operator runs `sudo npm install -g claude-code`, +which writes a root-owned tree under `/usr/lib/node_modules`. The tool then +writes a wrapper at `/usr/local/bin/claude` that `exec`s the binary inside +that tree. So far so good — until the operator runs `claude update`. + +`claude update` is Claude Code's own self-updater. It tries to rewrite the +binary in-place. But the running user is not root, the binary is, so the +update fails with EACCES. The operator reaches for `sudo` again. Now the +update succeeds, but every `~/.npm/` cache file the update touched along the +way is root-owned too, and the next non-`sudo` invocation fails for a +*different* reason. The operator climbs the privilege ladder one more rung, +and from this point on every operation needs `sudo` — a permission tax on +every interactive task and a hard stop for any autonomous loop that cannot +prompt for a password. + +The same shape breaks every tool that ships its own self-updater into a +root-owned prefix: the wrapper at `/usr/local/bin/` points at the wrong +inode after the next update, or points at a tree the running user cannot +write to, and the tool gradually rots into a state where only `sudo` +unblocks it. AgentLinux's release-gate test enforces the inverse contract: +a fresh install plus `claude update` must succeed with zero EACCES and zero +`sudo` prompts in the transcript. + +## What AgentLinux does + +The installer's first provisioner step creates an `agent` user with a real +home at `/home/agent/`, `/bin/bash` as login shell, and the C.UTF-8 locale +enforced system-wide so non-ASCII output behaves predictably across +Docker, QEMU, cron, and SSH. The same step writes a `/home/agent/CLAUDE.md` +that documents the anti-patterns to any agent that lands in this user — the +forbidden `sudo npm install -g`, the forbidden `/usr/local/bin/` wrapper +shim, the forbidden second Node.js install. + +The agent user gets a per-user npm prefix at `~/.npm-global/`, configured +via `~/.npmrc` and re-enforced via `NPM_CONFIG_PREFIX` for systemd and cron +contexts where the `.npmrc` read might regress. PATH is wired across every +invocation mode the agent ever runs in: interactive shell (`/etc/profile.d/` +fragment), non-interactive bash (`~/.bashrc` marker block at the top, before +the skel early-return guard), systemd `User=agent` units (`/etc/agentlinux.env` +consumed via `EnvironmentFile=`), cron jobs (`/etc/cron.d/agentlinux` PATH +header), and `sudo -u agent` / `sudo -u agent -i`. Six modes, four +artifacts, byte-identical PATH literal in each. + +Every install routes through an `as_user agent <cmd>` helper that drops to +the agent user before invoking npm, the upstream native installer, or any +other write. The agent ends up owning every file it later needs to update. +`sudo npm install -g` is forbidden everywhere in the codebase; our PR +review process flags it on every PR. + +## Worked example + +``` +$ curl -fsSL https://agentlinux.org/install.sh | sudo bash +... provisioning ... +agentlinux-install: agentlinux-install complete + +$ agentlinux install claude-code +claude-code: install complete (resolves at /home/agent/.local/bin/claude) + +$ sudo -u agent claude --version +2.1.98 (Claude Code) + +$ sudo -u agent claude update +✓ Claude Code 2.1.114 installed + +$ sudo -u agent claude --version +2.1.114 (Claude Code) +``` + +No `sudo` on `claude update`. No EACCES. No password prompt. The agent owns +its own install tree, so its self-updater Just Works — which is the entire +point. + +## Value vs the naive approach + +Without a dedicated agent user with its own npm prefix, the naive path is +`sudo npm install -g <tool>`. Two problems: + +1. **EACCES on every subsequent non-root operation under `~/.npm/`.** Once + root has written into the npm cache or global tree, the user that runs + the agent — typically not root — can no longer install or update without + `sudo` again. That `sudo` poisons the next file it touches, and the + user is now locked into climbing the privilege ladder for every tooling + operation, including ones that have nothing to do with the original + install. +2. **Self-updaters break, often silently.** Tools like Claude Code that + ship their own updater (`claude update`) write into a root-owned prefix, + leave a wrapper at `/usr/local/bin/`, and fail to rewrite themselves on + the next update. The user reaches for `sudo`, fixes one symptom, creates + the next one. The release-gate test catches exactly this sequence. + +**AgentLinux gives agents their own user with their own npm prefix, so +self-update Just Works.** The per-user prefix is the keystone ownership +decision — recorded in [the per-user-prefix decision record](../decisions/004-per-user-npm-prefix.md); +every other piece of the install layer is downstream of it. + +## Related + +- [Installer](installer.md) — the entrypoint that provisions this user. +- [Node.js runtime](nodejs-runtime.md) — the per-user npm prefix and the + PATH wiring that backs this user's ownership story. +- [Sudo drop-in](sudo-drop-in.md) — the `/etc/sudoers.d/agentlinux` grant + that lets this user run privileged commands without password prompts. +- [Claude Code](claude-code.md) — the canonical case study for the + self-update-without-sudo invariant. diff --git a/docs/internals/catalog.md b/docs/internals/catalog.md new file mode 100644 index 0000000..7f9f57e --- /dev/null +++ b/docs/internals/catalog.md @@ -0,0 +1,151 @@ +# Catalog + +The catalog is the JSON-Schema-validated registry of agents AgentLinux +can install. It ships claude-code, gsd, and playwright-cli — three +opt-in entries; zero installed by default. New agents are added by +submitting a catalog entry plus an install recipe — no CLI source +changes required. + +## The problem + +There are two naive alternatives to a schema-validated catalog, and +both fail the project's "fresh contributor adds an agent in one PR" +test. + +The first is hardcoding the agent set into CLI source. This is the +shape AgentLinux briefly considered before the v0.2.0 → v0.3.0 pivot: +every supported agent's install logic lives as a TypeScript module +that the CLI dispatches by name. Adding a new agent then requires +editing TypeScript, running the test suite, and cutting a CLI release. +The friction kills contribution velocity, and worse, it conflates two +concerns — "what does the CLI do" and "what does AgentLinux know how +to install" — that ought to evolve at different speeds. + +The second is "no machine-readable contract at all" — every install +command lives only in someone's README, drifts immediately, and +cannot be programmatically validated. There is no field a CLI could +read to know an agent's pinned version, no way to assert that every +agent has a symmetric uninstall path, no way to enforce that recipe +filenames look like `*.sh`. Bugs that schema validation would catch in +milliseconds (a typo in `pinned_version`, a missing +`uninstall_recipe_path`, a recipe that points at a file that does not +exist) ship to users instead. + +Both naive paths also fail the version-pinning story +([STABILITY-MODEL.md](../STABILITY-MODEL.md)). Without a per-entry +`pinned_version` that is part of the release artifact, "AgentLinux +ships curated combos" reduces to "AgentLinux ships whatever npm +serves today" — and the project's product-level answer to "why use +AgentLinux instead of `npm install -g`?" collapses. + +## What AgentLinux does + +The catalog is three pieces working together. + +The first is `plugin/catalog/schema.json` — a JSON Schema 2020-12 +contract with `additionalProperties: false`, so unknown fields are +a hard fail rather than silently ignored. The schema declares the +required fields per entry (`id`, `display_name`, `description`, +`source_kind`, `pinned_version`, `install_recipe_path`, +`uninstall_recipe_path`) and conditional rules (`source_kind: "npm"` +implies `npm_package_name` is required). `pinned_version` is regex-bound +to exact semver (no ranges, no partials), `id` is regex-bound to +`[a-z][a-z0-9-]*`. The schema is the machine-readable spec the +catalog auditor and the install path both read from. + +The second is `plugin/catalog/catalog.json` — the embedded agent list +shipped in every release tarball. Today it holds three real entries +(claude-code, gsd, playwright-cli) plus one `test_only` fixture +exercised only by bats. Pre-commit and CI both run the catalog +through ajv; a malformed entry never reaches `master`, let alone a +release. + +The third is per-agent recipes under +`plugin/catalog/agents/<id>/install.sh` and `uninstall.sh`. The +recipes are plain bash. Each recipe receives +`AGENTLINUX_PINNED_VERSION` in its environment (with a `:?` fail-fast +guard at the top), runs as the agent user, and asserts a post-install +invariant (binary on PATH, version banner matches pin, skill directory +exists where Claude Code looks for it). Adding an agent requires a +catalog entry plus a recipe pair — no TypeScript edits anywhere. + +Three invariants govern the catalog: + +- Agents are *available*, not installed by default — `agentlinux list` + on a fresh host shows every entry with `STATUS: not installed`. The + rationale is recorded in [the no-default-installs decision record](../decisions/003-no-default-agents-installed.md). +- The catalog is schema-validated at pre-commit and CI time — our + catalog reviewer runs `ajv` against `schema.json` and refuses to ship + malformed entries. +- Adding a new agent is a one-PR change against the catalog — no CLI + source edit, no release tag. The schema is the contract; the + recipe is the implementation. + +Every release pins each catalog entry to a version AgentLinux's CI +matrix (Docker × Ubuntu 22.04 / 24.04 / 26.04 plus QEMU on the same +versions) exercised end-to-end before tag — the curated combo +([STABILITY-MODEL.md](../STABILITY-MODEL.md)). The catalog snapshot +is staged on disk at `/opt/agentlinux/catalog/<version>/catalog.json` +and is the source of truth `agentlinux install` reads. + +## Worked example + +``` +$ jq '.agents[] | {id, source_kind, pinned_version}' \ + /opt/agentlinux/catalog/0.3.0/catalog.json +{ "id": "claude-code", "source_kind": "script", "pinned_version": "2.1.98" } +{ "id": "gsd", "source_kind": "npm", "pinned_version": "1.37.1" } +{ "id": "playwright-cli", "source_kind": "npm", "pinned_version": "0.1.11" } +``` + +Adding a new agent looks like: + +``` +$ mkdir plugin/catalog/agents/<new-id> +$ touch plugin/catalog/agents/<new-id>/{install,uninstall}.sh && chmod +x ... +$ $EDITOR plugin/catalog/catalog.json # add the entry +$ pre-commit run --all-files # ajv validation runs here +``` + +No CLI source edited. Our catalog reviewer validates the entry +against the schema; our PR review process flags any +`sudo npm install -g` or `/usr/local/bin/` shim in the recipe; the +release-gate matrix runs the recipe end-to-end on a clean host. + +## Value vs the naive approach + +Without a schema-validated catalog, the naive paths are "hardcoded +agent list in CLI source" or "README install commands." Two problems: + +1. **Hardcoding means a CLI release per agent.** Every new agent + requires a TypeScript edit, a CI run, a release tag — a friction + tax that grows with every entry. The catalog inverts this: a new + agent is one PR with no CLI source change, the schema is the + contract, and the recipe is the implementation. Catalog and CLI + evolve at different speeds because they are different artifacts. +2. **Without schema validation, every recipe is a snowflake.** The + schema enforces required fields (`pinned_version`, + `install_recipe_path`, `uninstall_recipe_path`); pre-commit and + CI catch malformed entries before they ship. Without it, an entry + missing `uninstall_recipe_path` or pointing at a recipe that does + not exist passes review and breaks operators in production. The + schema is also where "every install must declare a pinned + version" — the load-bearing rule of + [STABILITY-MODEL.md](../STABILITY-MODEL.md) — gets enforced. + +**The catalog is the contract that lets AgentLinux ship as a curated +combo — pinned versions, opt-in installs, validated schema — while +keeping the cost of adding an agent to one PR.** The CLI reads the +catalog; the catalog auditor validates it; the release matrix +exercises every entry end-to-end. The single source of truth is one +JSON file with a published schema. + +## Related + +- [Registry CLI](registry-cli.md) — the `agentlinux` command that + reads this catalog and dispatches its recipes. +- [../STABILITY-MODEL.md](../STABILITY-MODEL.md) — curated combos and + the three-way divergence model the `pinned_version` field anchors. +- [Claude Code](claude-code.md) — the `claude-code` entry's home. +- [GSD](gsd.md) — the `gsd` entry's home. +- [Playwright](playwright.md) — the `playwright-cli` entry's home. diff --git a/docs/internals/claude-code.md b/docs/internals/claude-code.md new file mode 100644 index 0000000..268e264 --- /dev/null +++ b/docs/internals/claude-code.md @@ -0,0 +1,119 @@ +# Claude Code + +Claude Code is Anthropic's published agent CLI — a coding agent that reads +files, edits them, runs commands, and reasons about the result. AgentLinux +ships it as an opt-in catalog entry: `agentlinux install claude-code` runs +the upstream native installer as the agent user, putting Claude Code into +the agent's own home directory tree where the tool's own self-updater +(`claude update`) can rewrite it without `sudo` or EACCES. That +self-update-without-sudo invariant is the canonical AgentLinux +acceptance test. + +## The problem + +`claude update` is the recommended way to stay current with Claude Code — +and the operation that breaks loudest under the wrong install path. The +naive way to install Claude Code on a fresh Ubuntu host is +`sudo npm install -g @anthropic-ai/claude-code` (or, equivalently, the +upstream `claude.ai/install.sh` piped to `sudo bash`). Either path lands +the install tree under root ownership; the next `claude update` then +fails with EACCES the moment it tries to rewrite itself in place. The +operator reaches for `sudo claude update`, which succeeds once but +corrupts the next layer of files. From that point forward every +interactive operation needs `sudo` and every autonomous loop stalls on +the password prompt that never arrives — see [Agent user](agent-user.md) +for the full bug class. + +AgentLinux's release-gate test is the inverse contract: a fresh install +plus `claude update` must succeed with zero `sudo` prompts and zero +EACCES lines in the transcript. It is the loudest acceptance test in the +project — the one whose failure most reliably signals the bug class +AgentLinux exists to eliminate. + +## What AgentLinux does + +`agentlinux install claude-code` runs the catalog recipe via the agent +user. The recipe pipes Anthropic's official native installer +(`https://claude.ai/install.sh`) to `bash` — but with the running user +already dropped to `agent`, so the install tree lands under +`/home/agent/.local/` instead of root-owned territory. The pinned +version (the one AgentLinux's CI tested against the full Docker + QEMU +matrix in the latest release) is passed as the installer's positional +argument, so the recipe writes the version AgentLinux's release-gate +exercised — not whichever version Anthropic's stable channel happens to +serve at install time. + +After install, the binary at `/home/agent/.local/bin/claude` is +agent-owned. Its parent directory is on the agent's PATH across every +invocation mode (interactive shell, `sudo -u agent`, systemd, cron, SSH — +see [Node.js runtime](nodejs-runtime.md)). When the operator later runs +`claude update`, Claude Code's own updater rewrites the binary in place +with no `sudo`, no EACCES, no recursive shim at `/usr/local/bin/`. +AgentLinux gets out of the way; the upstream self-updater Just Works. + +## Worked example + +``` +$ agentlinux install claude-code +claude-code: installing version 2.1.98 via native installer +claude-code: installed, reports: 2.1.98 (Claude Code) +claude-code: install complete (version-lock satisfied — installed matches pin) + +$ sudo -u agent claude update +✓ Claude Code 2.1.114 installed + +$ agentlinux upgrade +Per-agent divergence (report-only): + + claude-code installed=2.1.114 curated=2.1.98 state=override-ahead + ... + + Choose per-agent: [keep override] [accept curated] [accept upstream latest] +``` + +The divergence after `claude update` is intentional. AgentLinux *surfaces* +the gap between the curated combo and what the user has on disk — it +does not silently overwrite the user's choice. The operator picks "keep +override" to mark the entry sticky, or "accept curated" to downgrade +back to the tested combo. Either is defensible; AgentLinux just refuses +to make the call silently. + +## Value vs the naive approach + +Without AgentLinux, the naive path is `sudo npm install -g +@anthropic-ai/claude-code`. Two problems: + +1. **`claude update` breaks on root-owned trees.** Claude Code's own + self-updater is the recommended way to stay current, and it writes + in place into the install tree. If that tree is root-owned, the + updater fails with EACCES on the very first attempt; the operator + reaches for `sudo claude update`, which succeeds once but corrupts + another layer of files (`~/.npm/`, `~/.claude/`) along the way. From + that point forward every operation needs `sudo`, autonomous loops + stall on missing password prompts, and the only clean recovery path + is a full reinstall. +2. **Upstream `latest` ships immediately.** The naive `npm install -g` + path always pulls whichever version Anthropic published most + recently, including the rare broken one. AgentLinux pins to a + CI-tested version and lets the user opt past the pin via + `agentlinux pin claude-code=latest` (sticky) or `=<semver>` (held) + — `agentlinux upgrade` makes the divergence between installed, + curated, and upstream visible rather than silent. + +**AgentLinux makes Claude Code installable, updatable, and reconcilable +— without root, without surprises.** The agent owns the tree the tool +needs to rewrite; the catalog records what AgentLinux actually tested; +`upgrade` and `pin` give the operator control over when to move ahead +of the curated combo. + +## Related + +- [Agent user](agent-user.md) — the user that owns the install tree this + agent's self-updater rewrites. +- [Catalog](catalog.md) — where the `claude-code` entry's + `pinned_version` lives. +- [Registry CLI](registry-cli.md) — the `agentlinux` command that drives + install / upgrade / pin against the catalog. +- [../STABILITY-MODEL.md](../STABILITY-MODEL.md) — how curated combos + and three-way divergence (curated / installed / upstream-latest) work; + uses Claude Code's `claude update` as its own worked example. diff --git a/docs/internals/gsd.md b/docs/internals/gsd.md new file mode 100644 index 0000000..b9d2410 --- /dev/null +++ b/docs/internals/gsd.md @@ -0,0 +1,116 @@ +# GSD (Get Shit Done) + +GSD is a Claude Code workflow framework — slash commands and skills for +planning multi-step engineering work, executing it phase by phase, and +verifying the result. AgentLinux ships it as an opt-in catalog entry +pinned to a version the project's CI matrix has exercised, so an upstream +GSD regression does not immediately reach users. + +## The problem + +GSD has two intertwined installation problems on a fresh Ubuntu host. + +The first is the same ownership trap every npm-installed agent hits. The +naive `sudo npm install -g get-shit-done-cc` lands a root-owned tree +under `/usr/lib/node_modules`, leaves a wrapper at `/usr/local/bin/`, +and turns every later `npm update` or in-tool self-update into an +EACCES-then-`sudo` cycle. Once root has touched the global tree the +agent user can no longer install or update without climbing the +privilege ladder again — see [Agent user](agent-user.md) for the full +bug class. + +The second is upstream cadence. GSD ships fast — multiple releases per +week are normal, and the project has hit upstream regressions in +production: a bug present in `latest` for several days before a fix +shipped. A thin-wrapper distribution that always pulls `latest` exposes +every user to every wobble in the upstream release cadence the moment +it publishes, with no safety net between the broken version and the +operator's machine. + +GSD also expects a follow-on bootstrap step that no thin wrapper can +discover automatically: after the npm install, the binary is on PATH but +Claude Code does not yet see any `/gsd-*` slash commands or skills. +GSD's bootstrapper has to be invoked once to copy its skill set into +`~/.claude/skills/`. Operators who skipped that step on the first GSD +release reported "I installed it and Claude Code doesn't see it" — +technically correct, intent-wise wrong. + +## What AgentLinux does + +`agentlinux install gsd` runs the catalog recipe via the agent user. +The recipe runs `npm install -g get-shit-done-cc@<pinned>` into the +agent's per-user prefix at `~/.npm-global/`, so the binary +(`get-shit-done-cc`, the npm-published name — there is no symlink +shortening it to `gsd`) lands at +`/home/agent/.npm-global/bin/get-shit-done-cc`, agent-owned. + +The pinned version comes from the catalog entry's `pinned_version` +field — the version AgentLinux's release-gate exercised against the +full Docker + QEMU matrix before the tag shipped. After the install, +the recipe asserts the help banner contains `v<pinned>` so a mispin or +upstream-channel drift fails the install rather than silently writing +a sentinel for the wrong version. The recipe then runs the GSD +bootstrapper (`get-shit-done-cc --global --claude`) which copies the +skill set into `~/.claude/skills/gsd-*/` — so the user's intent +("install GSD") is satisfied end-to-end, not just in the +binary-on-PATH technical sense. + +`agentlinux upgrade` later compares installed, curated, and (with +`--check-upstream`) upstream-latest, and surfaces the three divergence +states (`synced`, `override-ahead`, `override-behind`) per +[STABILITY-MODEL.md](../STABILITY-MODEL.md). When the operator runs +`get-shit-done-cc` past the curated pin (or `npm install -g +get-shit-done-cc` themselves), AgentLinux notices and asks rather than +silently overwriting. + +## Worked example + +``` +$ agentlinux install gsd +gsd: installing get-shit-done-cc@1.37.1 +gsd: wiring GSD skill set into ~/.claude/ via get-shit-done-cc --global --claude +gsd: install complete (resolves at /home/agent/.npm-global/bin/get-shit-done-cc; + banner matches pin; skill set wired into /home/agent/.claude/skills/gsd-*) + +$ sudo -u agent get-shit-done-cc --help | head -1 +Get Shit Done v1.37.1 + +$ agentlinux upgrade + gsd installed=1.37.1 curated=1.37.1 state=synced +``` + +## Value vs the naive approach + +Without AgentLinux, the naive path is `sudo npm install -g +get-shit-done-cc`. Two problems: + +1. **The agent's own workflow tools end up root-owned.** GSD lives in + the same EACCES + recursive-shim story as Claude Code: once the + install tree is root-owned, no later operation under `~/.npm/` can + succeed without `sudo`, and every operator-side `sudo` corrupts + another layer. See [Agent user](agent-user.md) for the full bug + class — GSD is just one more victim of the naive global-install + path. +2. **Upstream regressions hit immediately.** GSD ships fast, and + broken releases occasionally land in `latest`. A thin-wrapper + AgentLinux that always pulls `latest` would expose every user to + every upstream regression the moment it publishes. AgentLinux's + curated pin gives the project the freedom to test upstream movement + on the full Docker + QEMU matrix before it reaches users. + +**Pinning is the explicit contract — AgentLinux tests what it ships, +and the operator opts past the pin when they are ready.** The +escape hatches (`agentlinux pin gsd=latest` for sticky-follow-upstream, +`agentlinux pin gsd=<semver>` to bisect a regression) are first-class; +the silent-drift path is the one that does not exist. + +## Related + +- [Agent user](agent-user.md) — the user that owns the per-user npm + prefix this install lands in. +- [Catalog](catalog.md) — where the `gsd` entry's `pinned_version` + lives. +- [Registry CLI](registry-cli.md) — the `agentlinux` command that + drives install / upgrade / pin against the catalog. +- [../STABILITY-MODEL.md](../STABILITY-MODEL.md) — curated combos and + the three divergence states. diff --git a/docs/internals/installer.md b/docs/internals/installer.md new file mode 100644 index 0000000..1c706e0 --- /dev/null +++ b/docs/internals/installer.md @@ -0,0 +1,110 @@ +# Installer + +AgentLinux ships as a curl-pipe-bash installer that downloads a versioned +release tarball, verifies it against a sibling SHA256 sidecar, and executes +the staged plugin. One command on a clean Ubuntu host turns it into an +agent-ready environment — no Ansible, no manual `apt` dance, no per-machine +shell-script drift. + +## The problem + +Bootstrapping an agent environment on a fresh Ubuntu host is a graveyard of +bespoke shell scripts. Every team has one — copy-pasted between machines, +edited in place, slightly different on every host. They `apt install` a few +packages, then `npm install -g` the agent tooling, and call it done. The +result is a machine where nobody knows what is installed, what version, or +whether the next `claude update` will silently break. + +The shell-script-from-the-internet pattern itself has a real security +problem. A naive `curl https://example/script | sudo bash` executes whatever +bytes the server returned today — no verification, no version pinning, no +defence against a tampered mirror. Worse, if the connection drops mid-stream, +bash will execute the partial script it received, which can leave the host +in a half-configured state that is harder to recover from than a clean +failure. + +And the typical bootstrap script ends with `sudo npm install -g <tool>`, +which corrupts the install tree in a way the agent can never recover from +on its own. That bug class is the subject of [Agent user](agent-user.md); +the installer's job here is the trust story for getting onto disk safely. + +## What AgentLinux does + +The installer is one shell script that turns a clean Ubuntu host into an +agent-ready environment in a single command. It downloads a versioned +release tarball from GitHub Releases over HTTPS, verifies it against a +sibling `.sha256` sidecar *before* extracting anything, and hands off to +the staged `agentlinux-install` entrypoint which runs the ordered +provisioner steps: agent user, sudo drop-in, Node.js runtime, PATH wiring, +registry CLI. + +The version is either pinned explicitly via the `AGENTLINUX_VERSION` +environment variable or resolved automatically to the latest GitHub +Release. Either way the resulting URL is a permanent, versioned artifact +— so the same command run a week later installs the same tarball you +ran today, byte for byte. That is the key win over a hand-rolled `curl +| bash`: a reproducible install that pins to a CI-tested combo of +installer, runtime, and catalog, with the SHA256 verified before any +code runs. + +## Worked example + +``` +$ curl -fsSL https://agentlinux.org/install.sh | sudo bash +agentlinux-install: downloading https://github.com/Roo4L/agent-linux/releases/download/v0.3.0/agentlinux-v0.3.0.tar.gz +agentlinux-install: downloading agentlinux-v0.3.0.tar.gz.sha256 +agentlinux-install: SHA256 verified for agentlinux-v0.3.0.tar.gz +agentlinux-install: verified and extracted agentlinux-v0.3.0.tar.gz — handing off to agentlinux-install +agentlinux-install: agentlinux-install v0.3.0 starting +agentlinux-install: 10-agent-user: done +agentlinux-install: 20-sudoers: done +agentlinux-install: 30-nodejs: done +agentlinux-install: 40-path-wiring: done +agentlinux-install: 50-registry-cli: done +agentlinux-install: agentlinux-install complete + +$ agentlinux list +NAME STATUS CURATED INSTALLED DESCRIPTION +claude-code not installed 2.1.98 — Anthropic's coding agent +gsd not installed 1.37.1 — get-shit-done-cc planning workflow CLI +playwright-cli not installed 0.1.11 — Browser automation with chromium +``` + +No agents are installed by default — that is a deliberate choice (see +[the no-default-installs decision record](../decisions/003-no-default-agents-installed.md)), +not an oversight. Users opt in with `agentlinux install <name>`. + +## Value vs the naive approach + +Without a versioned, SHA-verified installer, the naive path is +`curl https://example/script | bash`. Two problems: + +1. **Tampered or partial downloads execute by default.** A connection reset + mid-stream feeds a truncated script to bash, which runs whatever + commands it has parsed so far — half a config edit, the start of a + `rm -rf` loop, anything. A malicious mirror or a compromised CDN can + substitute an arbitrary payload silently; without a sibling SHA256 + sidecar verified against a published hash, the user has no signal. +2. **The install is not reproducible.** Re-running the same command a week + later may pull a newer remote script with different behavior, different + version pins, or different security posture. There is no way to say + "install exactly what we ran in CI yesterday" because there is no + artifact to point at — only a moving URL. + +**AgentLinux's installer makes the trust story explicit: HTTPS plus a +SHA256 sidecar verified before extraction, plus an env-pinnable +`AGENTLINUX_VERSION` that resolves to a permanent versioned URL — so +the install is reproducible a week from now and the bytes are checked +before any code runs.** The full release pipeline — curl-pipe-bash +primary plus optional `.deb` wrapper — is recorded in +[the distribution decision record](../decisions/006-curl-pipe-bash-plus-deb.md). + +## Related + +- [Agent user](agent-user.md) — the user the installer provisions and the + ownership invariant every later step preserves. +- [Sudo drop-in](sudo-drop-in.md) — the `/etc/sudoers.d/agentlinux` grant + one of the provisioner steps installs. +- [Node.js runtime](nodejs-runtime.md) — what the installer's third + provisioner step puts in place. +- [../README.md](../README.md) — the top-level install + verify story. diff --git a/docs/internals/nodejs-runtime.md b/docs/internals/nodejs-runtime.md new file mode 100644 index 0000000..4f8aa7c --- /dev/null +++ b/docs/internals/nodejs-runtime.md @@ -0,0 +1,143 @@ +# Node.js runtime + +AgentLinux installs the system Node.js LTS via apt (NodeSource), then wires +the agent user with a per-user npm prefix at `~/.npm-global/` and a PATH +that resolves the agent's binaries across every invocation mode the agent +ever runs in — interactive shell, non-interactive SSH, cron, systemd user +units, `sudo -u agent`, `sudo -u agent -i`. Two pieces, one runtime +contract: the system owns Node.js, the agent owns its npm globals, and +PATH agrees with both. + +## The problem + +Two intertwined problems define what an agent-runnable Node.js layer has +to solve. + +The first is invocation-mode breakage. Version managers — nvm, asdf, fnm, +volta — install Node.js into a shell-activated prefix and require a shell +hook (`. ~/.nvm/nvm.sh`, `eval "$(fnm env)"`) to wire PATH. The hook only +fires in interactive shells. Cron, systemd, non-interactive SSH (`ssh host +'cmd'`), and `sudo -u agent <cmd>` all skip those hooks, so `node` is +missing in exactly the contexts where automation actually runs. Tests pass +in the developer's terminal and break the moment the agent runs unattended. + +The second is ownership corruption. System Node.js installed via apt is +owned by root. `sudo npm install -g <tool>` then writes into +`/usr/lib/node_modules` as root, leaves a wrapper at `/usr/local/bin/`, +and the next non-root operation under `~/.npm/` fails with EACCES — and +worse, every tool that ships its own self-updater can no longer rewrite +itself. See [Agent user](agent-user.md) for the full bug class; the +release-gate test asserts the inverse contract — a fresh install plus +`claude update` must succeed with zero `sudo` prompts and zero EACCES. + +Both naive paths fail the same invariant from opposite sides: the +version-manager path makes Node.js invisible to non-interactive contexts, +the system-Node-with-`sudo-npm` path makes the agent unable to update its +own tools. Either way, the autonomous loop stalls. + +## What AgentLinux does + +The runtime layer has two halves and they only work together. + +The first half is system Node.js via apt. AgentLinux installs the official +NodeSource apt repository (HTTPS, GPG-signed, the upstream blessed in +[the system-Node decision record](../decisions/005-system-nodejs-over-version-managers.md)), +then `apt-get install nodejs`. The currently-tracked line is Node.js LTS +(v22 at the v0.3.0 release; future releases follow the LTS cadence). +System Node.js means a stable PATH entry that works in every invocation +mode, no shell-init hooks, no per-user re-activation flow. The trade-off +— Node.js version upgrades follow the distro's apt cadence rather than a +bleeding-edge per-user toggle — is acceptable because AgentLinux's job is +a correctly-owned runtime, not bleeding-edge Node features. + +The second half is the per-user npm prefix. The installer creates +`~/.npm-global/{bin,lib}` owned by `agent:agent`, writes +`prefix=/home/agent/.npm-global` into `~/.npmrc`, and PATH-wires the +prefix's `bin/` across four artifacts that together cover six invocation +modes: `/etc/profile.d/agentlinux.sh` (interactive login + `sudo -u agent +-i`), the `~/.bashrc` marker block at the top before the skel +early-return guard (non-interactive SSH + `sudo -u agent bash -c`), +`/etc/agentlinux.env` consumed via `EnvironmentFile=` in systemd `User=agent` +units, and `/etc/cron.d/agentlinux` for cron. Belt-and-braces: +`NPM_CONFIG_PREFIX` is also exported so systemd consumers see the prefix +even if `~/.npmrc` reads regress for any reason. The PATH literal is +byte-identical across every artifact — split-brain divergence fails the +acceptance grep. + +Path ordering is deliberate. `/home/agent/.npm-global/bin` lands first in +PATH, ahead of `/usr/local/bin` and the system bin directories, so a +stray wrapper shim at `/usr/local/bin/<tool>` (the canonical anti-pattern +the agent-user CLAUDE.md forbids) cannot win against the agent-owned +binary. Every install in the codebase routes through `as_user agent +<cmd>` so the agent ends up owning the global tree it later needs to +update. + +## Worked example + +``` +$ which node +/usr/bin/node + +$ node --version +v22.14.0 + +$ sudo -u agent npm config get prefix +/home/agent/.npm-global + +$ sudo -u agent which claude +/home/agent/.local/bin/claude + +# Cron entry under /etc/cron.d/agentlinux: +# */5 * * * * agent /home/agent/.npm-global/bin/get-shit-done-cc heartbeat +# claude resolves the same way under cron, systemd, and non-interactive ssh. + +$ ssh agent@host 'which claude' +/home/agent/.local/bin/claude + +$ sudo -u agent bash -c 'which claude' +/home/agent/.local/bin/claude +``` + +Every invocation mode resolves the agent's binaries to paths the agent +owns. That is the whole runtime contract, made observable. + +## Value vs the naive approach + +Without this runtime layer, the two naive paths are "install nvm/asdf for +the agent" or "use system Node.js with `sudo npm install -g`." Two +problems: + +1. **Version managers don't survive non-interactive contexts.** nvm, + asdf, and fnm rely on shell-init hooks that only fire in interactive + shells. Cron, systemd, ssh -i, and `sudo -u agent` skip those hooks, + leaving `node` missing exactly where automation runs. Agents that + work in the developer's terminal silently break the moment they run + unattended — and the failure mode is "command not found", which the + agent has no good way to recover from. +2. **`sudo npm install -g` corrupts ownership.** Once root has written + the global tree under `/usr/lib/node_modules`, the agent can no + longer self-update; every subsequent operation under `~/.npm/` fails + with EACCES, and tools like Claude Code that ship their own updater + end up with a wrapper at `/usr/local/bin/` they cannot rewrite. See + [Agent user](agent-user.md) for the full bug class — this naive path + is its origin point. + +**AgentLinux uses system Node.js for predictability and a per-user npm +prefix for ownership — and wires PATH so both choices hold across every +shell context the agent ever runs in.** The system-Node decision is +recorded in [the system-Node decision record](../decisions/005-system-nodejs-over-version-managers.md); +the per-user prefix in [the per-user-prefix decision record](../decisions/004-per-user-npm-prefix.md). +The two together are the load-bearing decisions everything else in the +runtime layer is downstream of. + +## Related + +- [Agent user](agent-user.md) — the user that owns the per-user npm + prefix and the EACCES + recursive-shim bug class this layer prevents. +- [Installer](installer.md) — the entrypoint whose third and fourth + provisioner steps build this runtime layer. +- [Claude Code](claude-code.md) — the canonical case for why this layer + matters; the self-update-without-sudo invariant is its release-gate + test. +- [GSD](gsd.md) — installed via npm into the per-user prefix this layer + provides. diff --git a/docs/internals/playwright.md b/docs/internals/playwright.md new file mode 100644 index 0000000..bfceb52 --- /dev/null +++ b/docs/internals/playwright.md @@ -0,0 +1,117 @@ +# Playwright + +Playwright is the browser-automation surface coding agents use to read web +pages, fill forms, and inspect network traffic. AgentLinux ships +Microsoft's official agent-oriented Playwright CLI (`@playwright/cli`) as +an opt-in catalog entry — `agentlinux install playwright-cli` installs the +CLI binary into the agent's per-user npm prefix and then bootstraps the +bundled Claude Code skill so the agent actually has slash-commands for +browser work, not just a binary on PATH. The agent user's NOPASSWD sudo +drop-in is what lets the bootstrapper's apt-layer browser-deps install +run mid-task without stalling on a password prompt. + +## The problem + +Installing Playwright on a fresh Ubuntu host has three failure modes a +naive path hits in sequence. + +The first is the same ownership trap every npm-global install hits. A +naive `sudo npm install -g @playwright/cli` lands the install tree under +root ownership, breaks every subsequent operation under `~/.npm/`, and +poisons the agent's ability to self-update its own tooling — the bug +class AgentLinux exists to eliminate (see [Agent user](agent-user.md)). + +The second is the apt-deps step. Playwright's browser binaries (chromium, +firefox, webkit) need a substantial set of OS-level libraries — libnss3, +libatk-bridge2.0-0, libxkbcommon0, and ~200 MB more — that only apt can +install. Playwright's installer auto-prepends `sudo` to that apt step, so +without a sudoers drop-in the install stalls indefinitely on a +`[sudo] password for agent:` prompt that a non-interactive session never +satisfies. Long-running coding-agent loops that hit this prompt do not +recover; they wait for stdin that never arrives. + +The third is intent. Even with the CLI binary on PATH, Claude Code does +not see any `/playwright-cli` slash commands until the bundled skill is +copied into `~/.claude/skills/`. Operators who installed `@playwright/cli` +without running its `--skills` bootstrapper reported "I installed +Playwright and the agent can't find it" — technically correct, +intent-wise wrong, and identical in shape to the GSD skill-set issue. + +## What AgentLinux does + +`agentlinux install playwright-cli` runs the catalog recipe via the +agent user. The recipe runs `npm install -g @playwright/cli@<pinned>` +into the agent's per-user prefix at `~/.npm-global/`, so the +`playwright-cli` binary lands agent-owned at +`/home/agent/.npm-global/bin/playwright-cli`. A pre-skills version-lock +asserts `playwright-cli --version` matches the pin, so a mispin or +channel drift fails before any heavier work runs. + +The recipe then invokes `playwright-cli install --skills` from the +agent's home directory. That bootstrapper copies the bundled Claude Code +skill into `~/.claude/skills/playwright-cli/` — which is what makes the +agent's `/playwright-cli` slash commands surface inside Claude Code. +Apt-layer browser deps that the bootstrapper's underlying Playwright +runtime needs install via the upstream sudo-prepended path; the agent +user's NOPASSWD sudo drop-in (`/etc/sudoers.d/agentlinux`, +[ADR-012](../decisions/012-agent-user-full-sudo.md)) is what makes that +step run cleanly without prompting. After install, a sanity check asserts +the skill directory landed where Claude Code looks for it; a missing +directory fails the install rather than silently writing a sentinel for +a half-bootstrapped state. + +## Worked example + +``` +$ agentlinux install playwright-cli +playwright-cli: installing @playwright/cli@0.1.11 +playwright-cli: CLI at /home/agent/.npm-global/bin/playwright-cli, version 0.1.11 +playwright-cli: wiring Claude Code skill via 'playwright-cli install --skills' +... apt-installing browser deps via the host's sudoers drop-in ... +playwright-cli: install complete (binary at /home/agent/.npm-global/bin/playwright-cli; + skill wired into /home/agent/.claude/skills/playwright-cli) + +$ sudo -u agent playwright-cli --version +0.1.11 +``` + +No `[sudo] password for agent:` prompt. No EACCES. No half-installed +state. The agent ends up with a binary it owns, a skill set Claude Code +can find, and browser deps the apt layer installed cleanly under the +NOPASSWD drop-in. + +## Value vs the naive approach + +Without AgentLinux, the naive path is `sudo npm install -g +@playwright/cli && sudo playwright-cli install --skills`. Two problems: + +1. **The npm install ends up root-owned.** Same self-update breakage + the other catalog agents hit — see [Agent user](agent-user.md) for + the bug class. Routing the install through `as_user agent` is what + keeps the per-user prefix invariant intact for Playwright too. +2. **The browser-deps step needs sudo, which stalls non-interactive + sessions.** Playwright's installer auto-prepends `sudo` to the + apt-deps install. A long-running agent that hits a `[sudo] + password for agent:` prompt mid-install is a stalled agent — the + prompt never resolves, the loop never recovers. The NOPASSWD sudo + drop-in (see [Sudo drop-in](sudo-drop-in.md)) is what makes the + apt step run cleanly under automation, and the install includes the + `--skills` bootstrap so the agent actually has slash commands for + browser work, not just a binary on PATH. + +**AgentLinux ships the full Playwright install — npm package, agent +skill wiring, and the OS-level browser deps the apt layer needs — as +one opt-in catalog entry that works the first time, every time, even +under a non-interactive coding-agent loop.** + +## Related + +- [Agent user](agent-user.md) — the user that owns the per-user npm + prefix this install lands in. +- [Sudo drop-in](sudo-drop-in.md) — the `/etc/sudoers.d/agentlinux` + NOPASSWD grant that lets the apt-deps step run without a password + prompt. +- [Catalog](catalog.md) — where the `playwright-cli` entry's + `pinned_version` lives. +- [Registry CLI](registry-cli.md) — the `agentlinux` command that + drives install / upgrade / pin against the catalog. diff --git a/docs/internals/registry-cli.md b/docs/internals/registry-cli.md new file mode 100644 index 0000000..4b023b2 --- /dev/null +++ b/docs/internals/registry-cli.md @@ -0,0 +1,142 @@ +# Registry CLI + +`agentlinux` is the small TypeScript CLI shipped with the plugin. It reads +the agent catalog and dispatches install / list / remove / upgrade / pin +commands — every state-changing operation runs as the agent user, never +as root. The CLI is the surface developers actually touch; everything +else (provisioner steps, recipes, sentinels, the catalog itself) is +wiring underneath. + +## The problem + +A fleet of agents, each with its own install command and update story, +becomes unmemorable fast. Claude Code installs via Anthropic's native +`claude.ai/install.sh`; GSD installs via `npm install -g get-shit-done-cc` +plus a `--global --claude` bootstrapper; Playwright installs via +`npm install -g @playwright/cli` plus a `--skills` bootstrapper that +needs apt-layer browser deps. The naive alternative is a `README.md` +listing per-agent install commands and hoping operators copy-paste them +correctly — which immediately drifts because no one updates README in +lockstep with the install paths, and the friction of "look up the right +incantation for *this* tool" multiplies linearly with every new agent. + +Operators want one verb per intent. `agentlinux install <name>` +regardless of whether the underlying recipe is npm-global, an +upstream native installer, or a future apt path; `agentlinux upgrade` +regardless of which mix of agents is installed; `agentlinux pin +<name>=<spec>` regardless of which release pinned the agent at which +version. Without a CLI, those verbs do not exist — and without those +verbs, fleet-level concerns (stickiness, three-way divergence, +"is this currently installed?", install-time invariants) have nowhere +to live. + +A CLI is also where invocation discipline gets enforced. Every recipe +must run as the `agent` user (not root) so the install tree lands +agent-owned; every recipe must receive the catalog's `pinned_version` +in the environment so the install version matches what AgentLinux's CI +actually exercised. That preflight is impossible to enforce in a +README; it is trivial in a CLI. + +## What AgentLinux does + +The CLI exposes five verbs: + +- `agentlinux list` — render the catalog as a table (or JSON), with + per-agent status: `not installed`, `synced`, `override-ahead`, + `override-behind`. Hides `test_only` entries unless `--include-test` + is passed. +- `agentlinux install <name>` — load the catalog, find the entry, + inject `AGENTLINUX_PINNED_VERSION` and the agent-user environment, + and dispatch the entry's `install_recipe_path` (typically + `install.sh`) as the `agent` user. After success, write a sentinel + to `/opt/agentlinux/state/installed.d/<id>.json` recording the + installed version and source (`curated`, `latest`, or + `pinned=<semver>`). `--version <semver>` overrides the catalog + pin; `--force` re-runs the recipe even when the sentinel says it is + already installed. +- `agentlinux remove <name>` — the symmetric inverse: dispatch the + entry's `uninstall_recipe_path` and delete the sentinel. `--force` + succeeds even when nothing is installed (idempotent). +- `agentlinux upgrade` — compare three numbers per agent (installed + per the sentinel, curated per the catalog, optionally upstream + per `npm view <pkg> version`) and surface the divergence. Default + is report-only and offline; opt-in flags + (`--reset-all-curated`, `--respect-overrides`, `--all-latest`, + `--check-upstream`) drive bulk reconciliation. +- `agentlinux pin <name>=<curated|latest|x.y.z>` — set sticky + overrides per [STABILITY-MODEL.md](../STABILITY-MODEL.md). + `=curated` clears the sticky bit; `=latest` follows upstream + forever; `=<semver>` holds at an exact version. + +Every command starts with the same preflight. A Commander `preAction` +hook calls `guardAgentUser`, which exits with code 64 if the CLI is +running as root or as any user other than `agent`. The catalog snapshot +shipped with the release is staged on disk at +`/opt/agentlinux/catalog/<version>/catalog.json` and validated against +`schema.json` (JSON Schema 2020-12, ajv) before any state-changing +operation runs. Recipes are dispatched via a thin runner that exports +the agent's PATH / NPM_CONFIG_PREFIX / HOME / `AGENTLINUX_PINNED_VERSION` +and shells into the per-agent `install.sh` — the recipe itself is +plain bash, easy to read and easy for the catalog auditor to review. + +## Worked example + +``` +$ agentlinux list +NAME STATUS CURATED INSTALLED DESCRIPTION +claude-code not installed 2.1.98 - Anthropic's agentic CLI ... +gsd not installed 1.37.1 - GSD workflow CLI for Claude Code ... +playwright-cli not installed 0.1.11 - Microsoft's token-efficient ... + +$ agentlinux install gsd +gsd: installing get-shit-done-cc@1.37.1 +gsd: install complete (resolves at /home/agent/.npm-global/bin/get-shit-done-cc; + banner matches pin; skill set wired into /home/agent/.claude/skills/gsd-*) + +$ agentlinux upgrade + claude-code not installed + gsd installed=1.37.1 curated=1.37.1 state=synced + playwright-cli not installed +``` + +One stable verb surface (`list`, `install`, `upgrade`) regardless of +whether the underlying recipe is an Anthropic native installer, an +npm-global, or an `@playwright/cli`-style npm-plus-bootstrap. + +## Value vs the naive approach + +Without a CLI, the naive paths are "remember each agent's install +command" and "manage the fleet by hand." Two problems: + +1. **Per-agent commands drift.** README install instructions go stale + the moment an agent's install path changes — a new bootstrapper + step appears, an apt dep is added, a pinned version moves. Operators + copy old commands from a stale README and end up with half-installed + agents (binary on PATH but skills missing, sentinel written but + bootstrapper skipped, etc.). The CLI binds the install path to the + catalog so the verb stays stable while the recipe evolves + underneath. +2. **No place to land cross-cutting concerns.** Sticky pin overrides, + three-way divergence between installed / curated / upstream + ([STABILITY-MODEL.md](../STABILITY-MODEL.md)), install-time + invariants ("must run as agent user", "must inject pinned_version", + "recipe-failure must keep the prior sentinel intact"), and "is + this currently installed?" status are properties of the *fleet*, + not of individual agents. The CLI is where they live; without + one, every recipe re-implements the same preflight, badly. + +**One stable verb surface for an evolving agent set — the CLI keeps +the contract honest while the recipes move underneath, and every +state-changing operation runs as the agent user with the catalog's +`pinned_version` in the environment.** + +## Related + +- [Catalog](catalog.md) — the schema-validated registry the CLI reads. +- [Agent user](agent-user.md) — every install runs as this user; the + CLI's `preAction` guard refuses to dispatch under any other. +- [Claude Code](claude-code.md) — the canonical install case; the + self-update-without-sudo invariant is its release-gate test. +- [GSD](gsd.md) — npm-global recipe with a bundled bootstrapper. +- [Playwright](playwright.md) — npm-global plus a `--skills` + bootstrapper plus apt-layer browser deps. diff --git a/docs/internals/sudo-drop-in.md b/docs/internals/sudo-drop-in.md new file mode 100644 index 0000000..84cad1a --- /dev/null +++ b/docs/internals/sudo-drop-in.md @@ -0,0 +1,120 @@ +# Sudo drop-in + +AgentLinux installs a `/etc/sudoers.d/agentlinux` drop-in granting the +`agent` user passwordless sudo for everything — the single line +`agent ALL=(ALL) NOPASSWD: ALL` that lets autonomous coding agents +`apt install`, `systemctl restart`, and reach into the host without ever +stalling on a `[sudo] password for agent:` prompt. + +## The problem + +An autonomous coding agent that runs for hours without a human in the loop +hits root-required operations constantly. It needs to `apt install` a build +dependency mid-task because the project just added a native module. It +needs to `systemctl restart` a service it just reconfigured. It needs to +edit a file under `/etc/`, install a system font, swap a binary via +`update-alternatives`, or set a kernel parameter. Each of those operations +either succeeds via sudo or wedges the agent's loop indefinitely. + +The earlier "zero sudo for the agent user" posture was elegant on paper — +the agent owned its npm prefix and its home, so why would it need root? — +but it predictably blocked too much real agent work. +A long-running agent that hits a `sudo -n true` failure cannot recover; the +shell either prompts for a password (which a non-interactive session never +satisfies) or refuses to run, and the agent's task fails for a reason that +is not a real bug in its code, just an environmental mismatch. + +The naive alternatives are both worse than the problem. Hard-coding a +shared root password into the agent's environment is a credential leak +waiting to happen. Adding the agent to `sudoers` with a narrow command +allowlist sounds tidy until the user notices that the allowlist needs +extending every other day — every new tool, every new build dep, every new +service. The maintenance tax falls on whoever maintains AgentLinux, +which is exactly the wrong place for it. + +## What AgentLinux does + +The installer's second provisioner step writes a single drop-in at +`/etc/sudoers.d/agentlinux` containing exactly `agent ALL=(ALL) NOPASSWD: +ALL`, mode `0440`, owned `root:root`. Re-runs produce a byte-identical +file. + +Mode `0440` means only root can read the drop-in. The agent observes its +effective policy via `sudo -l` but cannot `cat` the file directly. The +single-line scope means there is nothing to maintain — no allowlist +churn, no per-recipe sudo special cases. The agent is treated as a +trusted coworker, not as an adversary the system needs to defend against. + +What the drop-in deliberately does *not* alter: the per-user npm prefix +invariant. `sudo` is a tool the agent uses for legitimately-system-level +operations. It is not the path agents install through. `sudo npm install +-g` remains forbidden across the codebase regardless of whether the +password prompt appears, because that path destroys the agent's ownership +of its own tools — which is the bug class AgentLinux exists to eliminate. +The agent's `as_user agent <cmd>` discipline still draws the line on +which path is correct. + +## Worked example + +``` +$ sudo -u agent sudo -n true && echo ok +ok + +$ sudo -u agent sudo apt-get install -y jq +... apt output ... +Setting up jq (1.6-2.1ubuntu3) ... + +$ sudo -u agent sudo -l +User agent may run the following commands on this host: + (ALL) NOPASSWD: ALL +``` + +A counter-example illustrates the discipline the codebase still holds: + +``` +$ sudo -u agent sudo npm install -g @anthropic-ai/claude-code +# This WOULD run password-free now — but it's still a bug. +# It writes a root-owned global tree, breaks `claude update`, and +# violates the per-user-prefix invariant. The codebase's `as_user` +# rule and our PR review process reject it on every PR. +``` + +The lesson: sudo is the right tool for `apt install` and `systemctl +restart`. It is the wrong tool for installing the agent's own software. +AgentLinux trusts the agent with sudo *and* keeps the per-user prefix +invariant intact. + +## Value vs the naive approach + +Without a sudoers drop-in, the two naive paths are zero-sudo (the agent +runs without root) or shared-root-password (the agent prompts for it). Two +problems: + +1. **Zero-sudo blocks legitimate work.** A long-running coding agent that + needs `apt install <build-dep>` mid-task or `systemctl restart <svc>` + to validate its config change simply stalls. The agent is correct, the + environment is the problem; "the agent doesn't need root" was a + too-optimistic read of how real agents work. +2. **Password prompts stall autonomous loops.** A `[sudo] password for + agent:` prompt in a non-interactive session never resolves. The agent + either retries indefinitely against a closed stdin or fails for a + reason that has nothing to do with the task it was given. Either + outcome wastes hours. + +**AgentLinux drops the sudoers entry so agents work; the codebase's +`as_user` discipline still keeps the per-user prefix invariant intact.** +The trade-off — granting full sudo means any agent-held secret on the +host is effectively a root credential — is documented explicitly in +[the agent-user-full-sudo decision record](../decisions/012-agent-user-full-sudo.md), +which records this decision against the alternatives (narrow apt-only, +medium apt+systemctl, broad ALL). + +## Related + +- [Agent user](agent-user.md) — the user this drop-in grants sudo to and + the per-user prefix invariant the drop-in deliberately does not affect. +- [Installer](installer.md) — the entrypoint that runs the provisioner + step that writes this drop-in. +- [../decisions/012-agent-user-full-sudo.md](../decisions/012-agent-user-full-sudo.md) + — the full decision record, including considered alternatives (zero + sudo, narrow allowlist, and a future sandboxing path on our roadmap).