From a161cf6f63b005a4c470bbcd890daceb8b7f6f8a Mon Sep 17 00:00:00 2001 From: Nikita Ivanov Date: Sun, 10 May 2026 16:52:52 +0000 Subject: [PATCH 1/4] chore(docs): scrub internal-vocabulary leaks from user-facing surfaces (AL-33) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Externally-facing artifacts inherited internal GSD/Jira/requirement vocabulary (AL-XX, BHV/RT/AGT/CLI/CAT/INST IDs, Phase numbers, bare ADR-NN refs, .planning/ paths) by accident — copy-pasted from internal phase summaries or written while in plan-execute mode. Public readers (and the project owner excerpting into blog/email/agentlinux.org) cannot resolve those. This pass strips the leaks and rephrases the surrounding prose. Files modified: - README.md: drop AGT-02 token, drop .planning/REQUIREMENTS.md link, contextualize bare ADR-006 reference with the decision-record link. - CONTRIBUTING.md: drop the BHV/RT/AGT/CLI/CAT/INST/HRN/TST/DOC-XX list from PR guidance; rephrase to "describe what behavior changed and which bats test files cover it"; drop "cites the relevant requirement ID". - docs/STABILITY-MODEL.md: replace bare ADR-011 TL;DR token with a one-breath substance + decision-record link; drop AGT-02 / TST-08 / Phase 6 / ADR-012 tokens; clean up bare ADR-NNN prefixes in Related list (substance is already in the link text). - docs/README.md: drop "GSD workflow state" from the lede (internal harness vocabulary); drop "ADR-001..ADR-010 seeded in Phase 1"; rephrase HARNESS.md section descriptors to plain prose. - docs/internals/playwright.md: contextualize bare ADR-012 reference with a named decision-record link. - plugin/cli/src/index.ts: drop "(CLI-06)" from the `agentlinux upgrade` Commander description and "(CLI-07)" from the `agentlinux pin` Commander description — these surface in `--help` output. Kept on purpose: - Catalog agent name `gsd` and the npm package name `get-shit-done-cc` — these are the actual installable identifiers users type. - "GSD workflow CLI for Claude Code" in catalog example output and in catalog.json — that's the user-visible product description. - Source-comment references inside plugin/**, packaging/**, tests/** — out of audit scope per the external-audience-auditor (only user-visible strings are audited under packaging/, not source comments). - ADR-NNN references inside docs/decisions/** — internal-only by audit scope (cross-refs between ADRs are appropriate). Co-Authored-By: Claude Opus 4.7 (1M context) --- CONTRIBUTING.md | 5 ++--- README.md | 13 +++++++------ docs/README.md | 13 ++++++------- docs/STABILITY-MODEL.md | 19 ++++++++++--------- docs/internals/playwright.md | 6 +++--- plugin/cli/src/index.ts | 4 ++-- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d2afe50..fb1c502 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,14 +24,13 @@ behavior-test-driven — that shapes how we accept changes. that there is no reason to skip it. 5. **Open a PR.** Reference the issue. Describe what behavior changed and - which `BHV-XX` / `RT-XX` / `AGT-XX` / `CLI-XX` / `CAT-XX` / `INST-XX` / - `HRN-XX` / `TST-XX` / `DOC-XX` requirements are touched. + which `tests/bats/*.bats` test files cover it. ## Behavior-test contract `tests/bats/*.bats` is the spec. Implementation may change freely as long as the suite stays green. PRs that change observable behavior should add or -update a `@test` that cites the relevant requirement ID in its description. +update a `@test` that names the behavior it pins. See [`docs/HARNESS.md`](docs/HARNESS.md) §3 (test harness layout), §4 (review loop), and §5 (skill convention). diff --git a/README.md b/README.md index 4c46a03..dde6654 100644 --- a/README.md +++ b/README.md @@ -86,9 +86,10 @@ curated pin; when you want to run ahead of it, you can — `agentlinux upgrade` shows the 3-way divergence between installed, curated, and upstream latest, and `agentlinux pin` sets sticky overrides so power users are not re-nagged. -AGT-02 remains a permission invariant: whether you stay on the curated pin or -run `claude update` past it, AgentLinux's release-gate test verifies the -self-update path succeeds with zero `EACCES` and zero `sudo` prompts. +The self-update-without-sudo invariant is permanent: whether you stay on the +curated pin or run `claude update` past it, AgentLinux's release-gate test +verifies the self-update path succeeds with zero `EACCES` and zero `sudo` +prompts. 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) @@ -113,8 +114,7 @@ catalog's curated choice. Precedent: Homebrew's `brew pin`. - `curl` preinstalled (stock on all three releases) Not yet supported in v0.3.0: ARM64, Fedora/Alma/Rocky/Arch. Those are on the -v0.4+ roadmap. See [.planning/REQUIREMENTS.md](.planning/REQUIREMENTS.md) for -the full behavior contract. +v0.4+ roadmap. ## Security @@ -123,7 +123,8 @@ download (connection reset mid-transfer) yields a bash syntax error *before* any commands run — partial-download execution is not possible. The release tarball is fetched over HTTPS and verified against a sibling `.sha256` asset published on the same GitHub Release before extraction. GPG signatures are -on the v0.4+ roadmap (ADR-006); v0.3.0's trust story is HTTPS + SHA256 + +on the v0.4+ roadmap — see [`docs/decisions/006-curl-pipe-bash-plus-deb.md`](docs/decisions/006-curl-pipe-bash-plus-deb.md) +for the distribution decision; v0.3.0's trust story is HTTPS + SHA256 + maintainer 2FA + branch protection. Report vulnerabilities via the repository's Security tab (coordinated diff --git a/docs/README.md b/docs/README.md index 99c59ef..ed78123 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,17 +1,16 @@ # 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 +This directory holds all reference 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. +- `HARNESS.md` — authoritative project harness spec (project layout, + documentation routing, systems-access inventory, review loop, skills, + contributor checklist). +- `decisions/` — Architecture Decision Records (ADRs). New ADRs land as + decisions resolve. - `research/v0.3.0/` — v0.3.0 research outputs (STACK, FEATURES, ARCHITECTURE, PITFALLS, SUMMARY). - `research/v0.2.0/` — archived v0.2.0 research (carry-forward reference). diff --git a/docs/STABILITY-MODEL.md b/docs/STABILITY-MODEL.md index bb121ff..dd32a5c 100644 --- a/docs/STABILITY-MODEL.md +++ b/docs/STABILITY-MODEL.md @@ -1,6 +1,7 @@ # AgentLinux Stability Model -> The TL;DR of [ADR-011](decisions/011-stability-first-version-pinning.md). +> The user-facing summary of AgentLinux's curated-combo version pinning — +> the full decision record is at [`docs/decisions/011-stability-first-version-pinning.md`](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 @@ -22,11 +23,11 @@ v0.3.0 pins: - `gsd` (`get-shit-done-cc`) — **1.37.1** (npm global into the agent's per-user prefix) - `playwright` — **1.59.1** (npm global + `playwright install --with-deps - chromium`; apt-layer runs via ADR-012 NOPASSWD sudo drop-in) + chromium`; apt-layer runs via the agent user's NOPASSWD sudo drop-in) -The Phase 6 release-gate (`TST-08`) installs the full pinned combo on a clean -Ubuntu host and runs the agent bats suite before the tag can publish. A red -combo cannot ship. +The release-gate test installs the full pinned combo on a clean Ubuntu host +and runs the agent bats suite before the tag can publish. A red combo cannot +ship. ## The three divergence states @@ -50,8 +51,8 @@ Outcomes: ## 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 +into the agent-owned install tree — that is the whole point of AgentLinux. +After `claude update`, the curated pin and the installed version disagree; `agentlinux upgrade` surfaces the diff rather than silently overwriting your choice: @@ -116,9 +117,9 @@ behind is supported (`pin =`); reconciling is one command ## Related -- [ADR-011 — Stability-first version pinning with explicit reconciliation](decisions/011-stability-first-version-pinning.md) +- [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) +- [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. diff --git a/docs/internals/playwright.md b/docs/internals/playwright.md index bfceb52..6bee531 100644 --- a/docs/internals/playwright.md +++ b/docs/internals/playwright.md @@ -53,9 +53,9 @@ 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 +user's NOPASSWD sudo drop-in (`/etc/sudoers.d/agentlinux` — see +[the agent-user-full-sudo decision record](../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. diff --git a/plugin/cli/src/index.ts b/plugin/cli/src/index.ts index 9e2deec..405e901 100644 --- a/plugin/cli/src/index.ts +++ b/plugin/cli/src/index.ts @@ -79,7 +79,7 @@ program program .command("upgrade") - .description("Reconcile installed versions against the curated catalog (CLI-06)") + .description("Reconcile installed versions against the curated catalog") .option("--reset-all-curated", "accept curated versions for all agents; clear overrides") .option("--respect-overrides", "install curated only for non-overridden agents") .option("--all-latest", "install npm latest for all (implies --check-upstream)") @@ -91,7 +91,7 @@ program program .command("pin ") - .description("Set sticky override: =curated|latest|x.y.z (CLI-07)") + .description("Set sticky override: =curated|latest|x.y.z") .action(async (spec: string, opts) => { await pinCmd(spec, opts); }); From bb8f02f6dfb77eaeb7f468bbda3a3d233b4b2170 Mon Sep 17 00:00:00 2001 From: Nikita Ivanov Date: Sun, 10 May 2026 16:53:23 +0000 Subject: [PATCH 2/4] chore(claude): wire external-audience-auditor into review-loop dispatch (AL-33) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a new dispatch row under "Review Loop" for externally-facing artifacts (top-level README, CONTRIBUTING, docs/internals/, docs/HARNESS.md, docs/STABILITY-MODEL.md, docs/README.md, public release notes, blog/email drafts, agentlinux.org copy, user-visible packaging strings). The external-audience-auditor agent flags leakage of internal vocabulary — AL Jira keys, GSD plan filenames, BHV/RT/AGT/CLI/CAT/INST/HRN/TST/DOC requirement IDs, Phase/Plan numbering, bare ADR cross-refs, GSD orchestrator/executor/planner vocabulary, Claude Code self-references — that public readers cannot resolve. The new row sits alongside (not replacing) the per-file-type reviewers; for externally-facing docs both fire. Skip-list documented inline so contributors know which trees are internal-only by audit scope (.planning/, docs/decisions/, docs/audits/, docs/research/, .claude/, source under plugin/packaging/tests/). This complements the leak-scrubbing pass in the prior commit: the auditor catches future regressions automatically when externally-facing artifacts appear in the review scope. Co-Authored-By: Claude Opus 4.7 (1M context) --- CLAUDE.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 3909b1e..eebdc83 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -60,6 +60,17 @@ Reviewers applied by file type: - Catalog recipes → `catalog-auditor`, `security-engineer`, `ai-deslop`, `dev-docs-auditor` - Docs → `technical-writer`, `fact-checker`, `ai-deslop` (skip for ADRs and research summaries) +- Externally-facing artifacts (top-level `README.md`, `CONTRIBUTING.md`, + `docs/internals/`, `docs/HARNESS.md`, `docs/STABILITY-MODEL.md`, + `docs/README.md`, public release notes, blog/email drafts, `agentlinux.org` + copy, user-visible packaging strings) → also `external-audience-auditor`, + in addition to the per-file-type reviewers above. Audits for leakage of + internal vocabulary (AL Jira keys, GSD plan filenames, BHV/RT/AGT/CLI/CAT/ + INST/HRN/TST/DOC requirement IDs, Phase/Plan numbering, bare ADR cross-refs, + GSD orchestrator/executor/planner vocabulary, Claude Code self-references). + Skip for `.planning/`, `docs/decisions/`, `docs/audits/`, `docs/research/`, + `.claude/`, source under `plugin/`/`packaging/`/`tests/` (only user-visible + *strings* under packaging/ are in scope, not source comments). `dev-docs-auditor` keeps `docs/internals/.md` in sync when changes touch `plugin/bin/`, `plugin/lib/`, `plugin/provisioner/`, `plugin/cli/src/`, From 26938e59c28722bc5378f0ae81d6891fa1bfbe6d Mon Sep 17 00:00:00 2001 From: Nikita Ivanov Date: Sun, 10 May 2026 16:58:06 +0000 Subject: [PATCH 3/4] docs(quick-260510-n7e): AL-33 strip GSD vocabulary leaks + wire auditor PLAN.md, SUMMARY.md, and STATE.md update for the quick task. The two code commits (a161cf6 vocabulary scrub + bb8f02f auditor wiring) merged in via worktree-agent-ac895ebc no-ff merge. Co-Authored-By: Claude Opus 4.7 (1M context) --- .planning/STATE.md | 3 +- .../260510-n7e-PLAN.md | 319 ++++++++++++++++++ .../260510-n7e-SUMMARY.md | 152 +++++++++ 3 files changed, 473 insertions(+), 1 deletion(-) create mode 100644 .planning/quick/260510-n7e-remove-gsd-artifacts-from-help-and-proje/260510-n7e-PLAN.md create mode 100644 .planning/quick/260510-n7e-remove-gsd-artifacts-from-help-and-proje/260510-n7e-SUMMARY.md diff --git a/.planning/STATE.md b/.planning/STATE.md index 5ed2f6b..d8b4a20 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -36,7 +36,7 @@ Earlier: v0.3.0 — Phase 6 of 6 — Distribution + Release Pipeline — ✓ COM Plan: 05-04 ✓ complete — tests/bats/50-agents.bats (NEW, 272 lines, 9 @tests) + .planning/phases/05-agent-installability/05-04-AUDIT.md (NEW, 92 lines, behavior-coverage-auditor phase-close report). 9 non-destructive Phase 5 integration @tests: AGT-01 × 3 (six-mode × claude/gsd/playwright), AGT-02b (claude version-lock via catalog-driven jq pin lookup), AGT-03 (claude --help diagnostic substitute — failure-prefix regex, not bare-word "error"), AGT-04 (get-shit-done-cc --help banner-grep), AGT-05 × 3 (version + chromium cache owner agent + CLI-03 idempotent re-install). setup_file does double-primitive recovery after 40-*.bats INST-04 --purge: (a) re-runs plugin/bin/agentlinux-install when agentlinux symlink absent (mirror of 51-*.bats precedent), (b) re-authorizes /root/.ssh/id_ed25519.pub → ~agent/.ssh/authorized_keys when absent (--purge's userdel -r agent wipes ~/.ssh/; extension of 51-*.bats single-primitive recovery). All version pins resolved via `jq -r '.agents[] | select(.id=="") | .pinned_version' /opt/agentlinux/catalog/0.3.0/catalog.json` — zero hardcoded versions in @test bodies (ADR-011 compliance). Two atomic commits: fa386af (test Task 1 bats file), 6156b2b (docs Task 2 AUDIT.md). Two Rule 1/3 auto-fix deviations inline-incorporated in fa386af: (1) AGT-03 regex tightened `grep -Eiq 'error|traceback|permission denied|EACCES'` → `grep -Eq 'error:|Error:|ERROR:|Traceback|traceback \('` + case-insensitive `permission denied|EACCES` — upstream `claude --help` has legitimate noun "errors" in --mcp-debug option description; failure-prefix regex catches `: error: ...` convention without false-positive on help-text nouns (Rule 1 — bug-of-plan-regex-vs-upstream-shape); (2) 40-*.bats's INST-04 --purge `userdel -r agent` wipes ~/.ssh/authorized_keys → AGT-01 ssh-mode six-mode fails exit 255 "Permission denied" → setup_file re-installs pubkey from /root/.ssh/id_ed25519.pub when absent + starts sshd + polls sshd ready (Rule 3 — blocking; double-primitive setup_file recovery pattern). ~41 min total. Task 2 (checkpoint:human-verify TST-07 phase-close behavior-coverage-auditor gate) executed inline-rubric per ADR-010 + 02-05/04-07/05-01..03 precedent (Task-tool subagent dispatch unavailable on executor host): mechanical grep over `tests/bats/*.bats` for every Phase 5 req ID citation produced the 05-04-AUDIT.md coverage table — every req (AGT-01 × 3 hits + AGT-02 × 1 + AGT-02b × 1 + AGT-03 × 1 + AGT-04 × 1 + AGT-05 × 3 hits = 10 total Phase 5 @tests) COVERED. `TST-07 gate: GREEN` emitted. Full verify green: 18-grep plan automated-verify chain PASS (@test counts + helper loads + fixture hooks + install dispatch + six-mode markers + jq catalog lookup + chromium assertions + anti-pattern exclusions); `./tests/docker/run.sh ubuntu-24.04` → 66/66 PASS (was 57/57 baseline + 9 new); `./tests/docker/run.sh ubuntu-22.04` → 66/66 PASS; `bash tests/harness/run.sh` → 104/104 PASS. AGT-01 ✓ COMPLETE (bats); AGT-02b ✓ COMPLETE (bats-side); AGT-03 ✓ COMPLETE (bats); AGT-04 ✓ COMPLETE (bats); AGT-05 ✓ COMPLETE (bats). Phase 5 acceptance gate CLOSED. Earlier: Plan 05-03 ✓ complete — plugin/catalog/agents/playwright/{install,uninstall}.sh (real bodies, 79 + 23 lines). install.sh REPLACES Phase 4 scaffold with RESEARCH Pattern 5 3-part body: (1) `npm install -g playwright@${AGENTLINUX_PINNED_VERSION} --omit=dev --no-fund --no-audit` — CLI + JS bindings agent-owned per ADR-004; (2) `command -v playwright` PATH-resolve + `playwright --version | grep -q -F -- "${PINNED}"` pre-download version-lock (catches mispin BEFORE 281 MB download); (3) `npx --yes playwright install --with-deps chromium` upstream-recommended one-shot that downloads chromium + runs apt-install-deps via Playwright's internal sudo auto-prepend (playwright-core/src/server/registry/dependencies.ts; ADR-012 NOPASSWD makes non-interactive); plus post-install `find ${AGENTLINUX_AGENT_HOME}/.cache/ms-playwright -name 'chromium-*'` assertion. uninstall.sh REPLACES scaffold with Pattern 6 symmetric inverse: `npm uninstall -g playwright || true` + `rm -rf "${AGENTLINUX_AGENT_HOME}/.cache/ms-playwright"` (~631 MB reclaimed — chromium + chromium-headless-shell + ffmpeg) + `command -v playwright` absence check. Chromium-only (no firefox/webkit — Phase 5 deferred scope). No `sudo` in recipe body; ADR-012 dependency documented in comments. Preserves `:?` guards on AGENTLINUX_PINNED_VERSION + AGENTLINUX_AGENT_HOME as first non-comment lines (27-28). FIRST catalog recipe to exercise ADR-012 end-to-end. One atomic commit (dc46bd8 feat Task 1 — no fix commits), ~41 min. End-to-end smoke on BOTH Ubuntu 22.04 + 24.04 via AGENTLINUX_DOCKER_KEEP_CONTAINER=1: install exit 0, chromium-1217 cache owned agent:agent, pw_version=Version 1.59.1 (pin ✓), 98/102 apt packages Setting-up (chromium-scoped — T-05-05e scope-creep mitigated), zero "password is required" transcript lines (ADR-012 sentinel GREEN); uninstall exit 0, command -v playwright → exit 1, cache removed. One textual deviation documented in SUMMARY: softened user-facing echo "uses sudo for apt" → "uses elevated privileges for apt" (line 53) + dropped "sudo" prefix from apt-get literal example in comment (lines 14-15) — forward-compat against stricter future `^[^#]*\bsudo\b` regex without `[[:space:]]` anchor; identical shape to Plan 02-04/04-02/05-01 rephrases. Review loop (catalog-auditor + security-engineer + bash-engineer rubrics applied inline per Phase 2/3/4/5-01/5-02 precedent — Task tool for subagent dispatch unavailable) clean one iteration, zero actionable findings. AGT-05 ✓ (recipe body; bats-side lands 05-04). Full verify green: shellcheck + shfmt + bash -n clean; all 16 acceptance greps pass; negative env smoke passes; harness 104/104; Docker 57/57 green both Ubuntu versions (bats suite unchanged — AGT-05 bats is 05-04). Earlier: Plan 05-02 ✓ complete — plugin/catalog/agents/gsd/{install,uninstall}.sh (real npm-global bodies, 51 + 19 lines). install.sh uses `npm install -g get-shit-done-cc@${PINNED} --omit=dev --no-fund --no-audit` (binary name `get-shit-done-cc`, NOT `gsd` — no symlink per 05-RESEARCH Open Q1 hidden-shim anti-pattern) + `command -v get-shit-done-cc` PATH-resolve + `--help | head -20 | grep -q -F v${PINNED}` banner-grep version-lock (no `--version` flag). Symmetric uninstall + idempotent `|| true`. AGT-04 ✓ (recipe body; bats in 05-04). One atomic commit (a8a9a18 feat Task 1), ~45 min. Earlier: Plan 05-01 ✓ complete — plugin/catalog/agents/claude-code/{install,uninstall}.sh (real native-installer bodies, 51 + 23 lines) + tests/bats/51-agt02-release-gate.bats (NEW, 97 lines, 1 @test AGT-02 release-gate) + 2 Dockerfile touch-ups (curl added). install.sh REPLACES Phase 4 scaffold with Pattern 1 body: `curl -fsSL https://claude.ai/install.sh | bash -s "${AGENTLINUX_PINNED_VERSION}"` + PIPESTATUS guard + binary-exists at ~agent/.local/bin/claude + in-recipe AGT-02b version-lock via `grep -q -F -- "${PINNED}"` against `claude --version`; `:?` fail-fast guards preserved. uninstall.sh REPLACES scaffold with symmetric inverse per Anthropic docs — rm -f binary + rm -rf share + rm -rf ~/.claude/downloads; preserves ~/.claude/ user data (CAT-04). 51-agt02-release-gate.bats: one @test (Anti-Pattern: don't loop 8 MB fetch × 6 INVOKE_MODES); `timeout 120s sudo -u agent -H bash --login -c 'claude update' >${transcript} 2>&1` via mktemp file (Pitfall 4 binary-stdio interleave mitigation); assert_exit_zero + assert_no_eacces + sort -V monotonicity check; transcript cleaned on pass only; setup_file recovers from preceding 40-*.bats's INST-04 --purge by re-running plugin/bin/agentlinux-install when symlink absent; filename prefix `51-` reserves the file for Phase 6 TST-05 release-gate glob. Four atomic commits (8f7d1bf feat install+uninstall, 762f80f test 51-*.bats, ed46da0 fix Rule 3 curl, af1c4f5 fix Rule 3 setup_file recovery), ~59 min. End-to-end Docker: 57/57 bats green on both Ubuntu 22.04 + 24.04; observed first install claude@2.1.98 (pin ✓ AGT-02b); `claude update` bumped to 2.1.114; monotonicity 2.1.114 ≥ 2.1.98 passed (sort -V); transcript zero EACCES / permission-denied lines (AGT-02 ✓ THE canonical test v0.3.0 exists to pass). Two Rule 3 auto-fix deviations documented in SUMMARY: (1) Ubuntu minimal Docker images lack curl — added to apt-get alongside jq in both Dockerfiles (same Rule 3 shape as Plan 04-07 jq, Plan 02-05 dbus); (2) bats filename-sort puts 40-*.bats's INST-04 --purge before 51-*.bats, destroying /opt/agentlinux + agent user — setup_file guards on symlink presence + re-runs installer. Review loop (catalog-auditor + security-engineer + bash-engineer on recipes; qa-engineer + behavior-coverage-auditor on bats — rubrics applied inline per Phase 2-4 precedent) clean one iteration per task; zero actionable findings beyond the two Rule 3 fixes. AGT-02 ✓ COMPLETE (bats); AGT-02b ✓ COMPLETE (in-recipe; bats-side assertion in 05-04). Full verify: bash -n + shellcheck --severity=warning + shfmt -i 2 -ci -bn clean on all 3 files; bats --count tests/bats/51-agt02-release-gate.bats → 1; bash tests/harness/run.sh 104/104; negative env smoke (unset PINNED_VERSION) exits non-zero with clear error; ./tests/docker/run.sh ubuntu-22.04 + ubuntu-24.04 both PASS 57/57. Earlier: Plan 05.1-01 ✓ complete — plugin/provisioner/20-sudoers.sh (97 lines) + tests/bats/22-agent-sudo.bats (120 lines, 7 @tests). Sudoers drop-in `/etc/sudoers.d/agentlinux` installed at mode 0440 root:root containing exactly `agent ALL=(ALL) NOPASSWD: ALL` per ADR-012. Write path: single-quoted heredoc → tmpfile → `visudo -cf tmpfile` gate (T-05.1-01: never ship an invalid sudoers) → `install -m "0440" -o root -g root` atomic install (T-05.1-02: mode+ownership at rename time) → post-install `visudo -cf $SUDOERS_FILE` TOCTOU belt. RETURN-scoped tmpfile cleanup trap. Uses `return 1` (sourced fragment) for ERR-trap src:line attribution matching 30-nodejs.sh pattern. Bats coverage: 4 BHV-07 file-integrity tests (existence, mode 0440 + root:root via stat, exact NOPASSWD line via grep -Fx, visudo -cf clean) + 2 INST-06 functional tests (`sudo -u agent sudo -n true` exit 0 via run_sudo_u, `sudo -l` output contains "(ALL) NOPASSWD: ALL") + 1 BHV-07 idempotency test (sha256 byte-stable across re-run via `bash /opt/agentlinux-src/plugin/bin/agentlinux-install`). Two atomic commits (9d4ea32 feat provisioner, edae58a test bats), ~12 min execution. Zero deviations beyond shfmt-driven lint fixes before first commit (redirect spacing + mode literal-inlining for grep audit visibility). Review loop (bash-engineer + security-engineer + qa-engineer on provisioner; qa-engineer + behavior-coverage-auditor on bats) clean one iteration, zero actionable findings, zero fix commits. INST-06 ✓ COMPLETE; BHV-07 ✓ COMPLETE. Full verify green: shellcheck + shfmt + bash -n clean on provisioner; `./tests/docker/run.sh ubuntu-22.04 + ubuntu-24.04` both PASS 56/56 bats; `bash tests/harness/run.sh` 104/104. Phase 5.1 acceptance gate GREEN — 2/2 requirements (INST-06 + BHV-07) satisfied. Plan: 04-05 ✓ complete — plugin/cli/src/commands/pin.ts (stub→145-line impl) + plugin/cli/test/pin.test.ts (20 unit tests). Three pin targets via discriminated PinTarget union: =curated clears sticky (source=curated, sticky=false), =latest sets sticky=true + source=latest (version preserved — Open Q4), = sets sticky=true + source=pinned + version=. parsePinSpec exported separately as a pure-function parser (no catalog/filesystem deps — testable in isolation). Error shape: exit 64 (EX_USAGE) for bad spec / unknown agent / bogus target / missing '=' / empty name; exit 1 reserved for missing sentinel (distinguishes "real agent, not installed yet" from "bad spec"). T-04-14 mitigation: semver.valid() (not regex) rejects partials 2.1 + ranges ^2.1 + typos; parsePinSpec gates all sentinel writes; user spec flows only into JSON-serialized sentinel fields (no shell); atomic-rename preserved. Partial-update via {...existing, source, sticky, [version]} spread — id + installed_at preserved across pin. 3 integration-sanity tests confirm pin→upgrade contract end-to-end: post-pin=latest sentinel shape = upgrade input, pin=latest skipped by upgrade --all-latest, pin= reset by upgrade --reset-all-curated (ADR-011). Test count 92→112 (+20). Two atomic commits (b6b8932 test RED, 55c55dc feat GREEN), ~4 min. Zero functional deviations; 1 procedural (biome useTemplate collapsed two-line template concats — pre-GREEN fix, no separate commit). Review loop (node-engineer + security-engineer + qa-engineer inline) clean one iteration; zero fix commits. CLI-07 ✓ COMPLETE (TypeScript side; bats enforcement lands Plan 04-07). Full verify green: build+test+check+harness all clean, `node dist/index.js pin --help` renders. Earlier: Plan 04-04 ✓ complete — plugin/cli/src/upgrade/{divergence,npm_ls}.ts + plugin/cli/src/commands/upgrade.ts (stub→orchestrator) + types.ts append with DivergenceReport. computeDivergence + resolveLatestFor are pure; queryGlobalNpm + queryNpmViewLatest are the only impure seam (DI-testable). Offline-default via willTouchUpstream() gate; report-only default; 4 opt-in bulk flags (--reset-all-curated / --respect-overrides / --all-latest / --check-upstream) + --json. Sticky entries skipped unless --reset-all-curated (ADR-011). Pitfall 4 defensive parse; T-04-13 maxSatisfying null-guard with explicit message; npm-view single-string coercion. Per-entry upstream errors non-fatal; recipe-failure preserves prior sentinel. 38 new unit tests (26 divergence + 12 upgrade), 92/92 total green. Two atomic commits: 01cbfff (Task 1), 897c4e3 (Task 2). CLI-06 ✓ COMPLETE (TypeScript side). Earlier: Plan 04-03 ✓ complete — plugin/cli/src/runner.ts (dispatchRecipe + AGENT_PATH byte-identical to 40-path-wiring.sh line 146 — T-04-07 mitigation, cross-verified via grep -F) + plugin/cli/src/commands/{list,install,remove}.ts replacing Plan 04-01 stubs with real impls. list: loadCatalog(validate:false) + classify() + text/JSON + test_only filter (--include-test opts in). install: loadCatalog(validate:true) + catalog.find(id) + test_only guard + semver.valid on --version + decideVersion + idempotent short-circuit (semver.eq + !force) + dispatchRecipe + writeSentinel. remove: sentinel required unless --force + dispatchRecipe(uninstall.sh) + deleteSentinel; non-zero recipe exit propagates and keeps sentinel (retryable). DI seam via optional third-param Dispatcher (mock.module undefined on Node 20.20.1; DI portable across Node 20 dev + Node 22 LTS). --include-test flag added to install subcommand in index.ts (Rule 2 — Plan 04-01 registered it only on list). 23 new unit tests (5 runner + 6 list + 12 install + 5 remove), 54/54 total green. ~7 min. Two atomic commits: 86ff777 (Task 1 runner.ts), 93fb37d (Task 2 three commands + 23 tests + --include-test). End-to-end smoke against real catalog.json verified. CLI-02/CLI-03/CLI-04/CLI-05 ✓ COMPLETE (TypeScript side; bats enforcement lands 04-07). Earlier: Plan 04-02 ✓ complete — plugin/catalog/catalog.json with 4 ajv-validated entries + 8 strict-mode recipes (test-dummy functional, 3 real agents scaffolded). Earlier: Plan 04-01 ✓ — plugin/cli/ TypeScript scaffold + ajv 2020-12 schema + interface surface + Commander bootstrap with five subcommand STUBS + 26 unit tests. Status: Phase 6 ✓ COMPLETE (5/5 plans; TST-07 phase-close gate: GREEN for all 6 Phase 6 req IDs). Plan 06-05 landed README.md (138-line Pattern 7 landing page — Install/Verify/Uninstall/Stability model/Escape hatch/Requirements/Security/Links/About + version stamp `v0.3.0`) + docs/STABILITY-MODEL.md (124-line user-friendly ADR-011 companion — curated combos + v0.3.0 pins 2.1.98/1.37.1/1.59.1 + 3-way divergence states + worked `claude update` reconcile example + `agentlinux pin` escape hatch) + 06-05-AUDIT.md (behavior-coverage-auditor inline phase-close report). Plan 06-05 atomic commits: 672bf6f (docs README.md), 6b0e091 (docs STABILITY-MODEL.md), metadata commit (AUDIT + SUMMARY + STATE/ROADMAP/REQUIREMENTS updates). Phase 6 acceptance gate CLOSED — 3 bats-covered (INST-03 × 3 @tests in 60-curl-installer.bats + CAT-05 × 2 @tests in 10-installer.bats + TST-05 via 51-*.bats selector invoked by release.yml gate-2-docker + gate-3-qemu) + 2 CI-gate-covered (TST-03 nightly-qemu.yml + TST-08 release.yml gate-4-pinned-combo) + 1 docs-covered (DOC-01 README + STABILITY-MODEL). Runtime verification (first v0.3.0-rc1 tag push + real `curl | sudo bash` against live GH Release assets + Part C ship-smoke) deferred per 06-VALIDATION.md Manual-Only Verifications row 3 — the first tag push IS the shipping event. v0.3.0 READY to ship. Next: v0.3.0-rc1 tag push. -Last activity: 2026-05-09 — Quick task 260509-kuv (AL-37) complete: provisioner-installer bugfix. Added `DEBIAN_FRONTEND=noninteractive apt-get update` inside the gated auto-install branches in `plugin/provisioner/10-agent-user.sh` (locales install, line ~44) and `plugin/provisioner/20-sudoers.sh` (sudo install, line ~47), mirroring the canonical pattern at `30-nodejs.sh:33`. Without this update the installer aborted with "Package locales has no installation candidate" on hosts with empty `/var/lib/apt/lists/` (freshly pulled Ubuntu containers, long-idle hosts) — the bug class introduced under AL-30's auto-install gates. Both new `apt-get update` calls live INSIDE the `if ! command -v ; then` blocks so the gate's no-op-when-already-installed property is preserved, and neither carries `|| true` so real apt failures still trip the entrypoint's ERR trap with src:line attribution. Strengthened `tests/docker/Dockerfile.dogfood` to drop the previous AL-37 tactical workaround (which kept `/var/lib/apt/lists/` populated by NOT running `rm -rf /var/lib/apt/lists/*`) — it now cleans lists, so the dogfood image starts in the exact "empty apt cache" state that triggered AL-37, converting the failure scenario into permanent regression coverage. Three atomic feature commits: `f12c94f` (10-agent-user fix), `86d5cbf` (20-sudoers fix), `94c4064` (Dockerfile.dogfood empty-cache + comment rewrite). End-to-end validation: built `agentlinux-dogfood-al37:24.04`, confirmed empty cache + absent locale-gen + absent visudo at container start, ran the LOCAL worktree installer in the container; installer logged `[WARN] locale-gen not found; installing 'locales' package` → 66-line apt-get update transcript → `Setting up locales` → `locale C.UTF-8 enforced`; then `[WARN] visudo not found; installing 'sudo' package` → fast-path apt-get update → `Setting up sudo` → `wrote /etc/sudoers.d/agentlinux`; provisioners 10/20/30/40 all reached "done" banners. Zero "no installation candidate" matches in 240+ KB install log. The trailing 50-registry-cli failure (`CLI dist/index.js missing`) is unrelated — gitignored CLI bundle that the Dockerfile.ubuntu-XX matrix splices in pre-install, intentionally bypassed in the AL-37-focused validation. Earlier: 2026-05-02 — Quick task 260502-i4p (AL-23) complete: added `.claude/hooks/review-reminder.sh` + project `.claude/settings.json` Stop-hook wiring; amended ADR-010 with a 2026-05-02 Refinement section that allows reminder Stop hooks (one-shot via `stop_hook_active`) while keeping reviewer-invoking hooks rejected; softened CLAUDE.md "Review Loop" paragraph to point at both the CLAUDE.md instruction (primary) and the hook (backstop). Smoke tests green: block path emits the JSON reminder naming all six AgentLinux reviewers (bash-engineer, node-engineer, security-engineer, qa-engineer, behavior-coverage-auditor, catalog-auditor); guard path (`stop_hook_active:true`) emits zero stdout. Two atomic feature commits + worktree merge into `worktree-review-hook`. Earlier: 2026-04-20 — Plan 06-05 complete + Phase 6 CLOSED + v0.3.0 READY (one `type="auto"` task + one `type="checkpoint:human-verify"` task-as-inline-rubric = 2 atomic commits fa386af + 6156b2b, ~41 min total). tests/bats/50-agents.bats shipped with 9 Phase 5 non-destructive AGT-XX @tests exercising the catalog-driven jq pin lookup + six-mode INVOKE_MODES loops against real agent binaries for the first time + chromium cache ownership verification. Plan 05-04 is the first bats file to do double-primitive setup_file recovery (agentlinux symlink + SSH keypair authorization) so the six-mode AGT-01 ssh branch works after 40-*.bats INST-04 --purge. Two Rule 1/3 deviations inline-incorporated: AGT-03 regex tightened to failure-prefix tokens after upstream `claude --help` noun "errors" false-positive; setup_file adds ~agent/.ssh/authorized_keys re-install primitive. TST-07 phase-close gate: GREEN (all 6 Phase 5 req IDs covered across 50-agents.bats + 51-agt02-release-gate.bats). Docker 66/66 PASS on both Ubuntu 22.04 + 24.04; harness 104/104. Phase 5 acceptance gate CLOSED; transition to Phase 6 (Distribution + Release Pipeline). Earlier: 2026-04-19 — Plan 05-03 complete (one `type="auto"` task, one atomic commit dc46bd8, ~41 min total). Phase 5 Wave 3 playwright recipe landed: AGT-05 recipe body is the first catalog recipe to exercise ADR-012's NOPASSWD sudoers drop-in end-to-end. Observed on both Ubuntu 22.04 + 24.04 smoke: install exit 0, chromium-1217 cache agent:agent-owned (ADR-004 ✓), pw_version=1.59.1 matches pin (AGT-05 version-lock ✓), 98/102 apt packages Setting-up (chromium-scoped — T-05-05e scope-creep mitigated), zero "password is required" transcript lines (ADR-012 sentinel GREEN); uninstall exit 0, PATH clean, cache removed. One textual deviation documented (softened "sudo" → "elevated privileges" in echo + comment for forward-compat regex compliance). Earlier: 2026-04-19 — Plan 05-01 complete (two `type="auto"` tasks + two Rule 3 auto-fix commits = 4 atomic commits, ~59 min total). AGT-02 canonical acceptance test is GREEN end-to-end on both Ubuntu 22.04 + 24.04 — this is THE test v0.3.0 exists to pass. Observed: first install claude@2.1.98 (pin ✓ AGT-02b); `claude update` bumped to 2.1.114; sort -V monotonicity 2.1.114 ≥ 2.1.98 passed; transcript zero EACCES / permission-denied lines. Two Rule 3 auto-fixes: curl missing from Ubuntu Docker images + 40-*.bats --purge breaking 51-*.bats setup. Earlier: 2026-04-19 — Plan 04-02 complete. Two `type="auto"` tasks, two atomic commits (e0ee67b catalog.json + d319419 8 recipe scripts), ~4 min total. 4 ajv-validated catalog entries + 8 strict-mode bash recipes landed. Key pinning decisions: claude-code 2.1.98 (stable dist-tag per ADR-011), gsd npm_package_name `get-shit-done-cc` (registry-verified — eliminates Phase 5 correction risk), playwright 1.59.1. Fail-fast `: "${AGENTLINUX_PINNED_VERSION:?msg}"` on all 4 install.sh — exit 1 unset, exit 0 on any non-empty value; negative smoke passes. Scaffold-documents-Phase-5 pattern: each stub's block comment details the Phase 5 install body (curl|bash + PIPESTATUS for claude-code, `npm install -g` for gsd/playwright), so Phase 5 AGT-02/04/05 plans replace only the body. test-dummy fully functional for Plan 04-07's bats (printf quoted format + args, rm -f -- path-terminated). version_constraint `^2.1` only on claude-code to exercise --all-latest upper-bound in Plan 04-04's CLI-06. Zero functional deviations; 2 textual/procedural logged (Rule 2 comment rephrase "WITHOUT sudo" → "WITHOUT privilege escalation" avoids catalog-auditor grep self-match per 02-04 precedent; Rule 3 used individual hooks since pre-commit wrapper not installed on host — CI re-runs full wrapper). Review loop clean one-iteration (catalog-auditor + security-engineer + bash-engineer + qa-engineer rubrics inline). Full verify green: ajv "4 entries OK", shellcheck+shfmt clean, forbidden-substring greps empty, test-dummy roundtrip OK, 3 scaffold smoke tests OK, harness 104/104. Earlier: 2026-04-19 — Plan 04-01 complete (3 tasks, 3 commits, ~11 min, 26/26 unit tests, 8 auto-fixes documented; compile-first TS test strategy + Ajv strict-mode + CJS-interop bridge + walk-up resolver patterns established). Earlier: 2026-04-18 — Plan 03-02 complete (3 plan tasks + 1 Rule 1 auto-fix commit = 4 atomic commits, ~15 min). Rule 1 fix discovered during Task 2's end-to-end Docker ubuntu-24.04 smoke: 2/27 bats failed on first run (RT-02 cron + RT-04 systemd_user). Root causes: (a) run_cron's hardcoded PATH header didn't include /home/agent/.npm-global/bin after Plan 03-01's cron.d extension — fixed by prepending it FIRST to match installer's final PATH ordering; (b) systemd-run's "Running as unit: ... Finished with result: ..." banner polluted $output and broke assert_user_prefix_in_home's prefix-match (Phase 2 BHV-04 tolerated it because assert_path_has is substring-match) — fixed by passing --quiet to systemd-run. Both fixes in c4c9fbf. 27/27 bats PASS on both Ubuntu 22.04 + 24.04 after the fix (up from 22/22 Phase 2 baseline). Pinned cowsay@1.6.0 for reproducibility + Pitfall 9 two-bin layout stability (cowsay + cowthink). Five @tests instead of minimum four — RT-02 reinforcement satisfies VALIDATION task 03-02-05 (no-EACCES under npm install pressure). Earlier: Plan 03-01 complete (2 plan tasks + 2 Rule 3 auto-fix commits = 4 commits, ~15 min). Two Rule 3 auto-fixes discovered during end-to-end Docker smoke: (1) apt-get install failed on empty /var/lib/apt/lists — added apt-get update first (commit c6d9b41); (2) compgen -G returned readdir order, not lexical — 30-nodejs.sh ran before 10-agent-user.sh creating the agent user → 'install: invalid user agent' failure; piped compgen through sort (commit 3dbfcff, fixing a pre-existing Phase 2 code-comment lie in run_provisioners()). Both fixes forward-only, no rollback. INST-02 byte-stable re-run still green. Earlier: Plan 02-05 complete (3 tasks, 6 commits, ~16 min). Phase 2 acceptance gate GREEN. Earlier: Plan 02-04 complete (1 task, 1 commit 5c8a095, ~4 min). Second dispatched provisioner lands green: ensure_dir /home/agent/.local{,/bin} 0755 agent:agent. Four artefacts in sequence — (1) install -m 0644 /dev/stdin /etc/profile.d/agentlinux.sh with re-source guard AGENTLINUX_PROFILE_SOURCED + case-prepend /home/agent/.local/bin + `export LANG=${LANG:-C.UTF-8}` override-respect. (2) /home/agent/.bashrc fallback-create via `install -m 0644 -o agent -g agent /dev/null` if absent, then `ensure_marker_block /home/agent/.bashrc "agentlinux-path" --top` with a minimal `if [ -f /etc/profile.d/agentlinux.sh ]; then . /etc/profile.d/agentlinux.sh; fi` body, then chown agent:agent + chmod 0644 after (ensure_marker_block writes root:root via install -m 0644). --top placement is critical per RESEARCH Pitfall 2: the Ubuntu skel .bashrc opens with `case $- in *i*) ;; *) return;; esac`, so any agentlinux block placed AFTER that guard never runs under `ssh host 'cmd'` or `sudo -u agent bash -c 'cmd'`. (3) install -m 0644 /dev/stdin /etc/agentlinux.env with literal KEY=VALUE lines (PATH + LANG + LC_ALL) for systemd EnvironmentFile= consumers. (4) install -m 0644 /dev/stdin /etc/cron.d/agentlinux with literal PATH header (Pitfall 4: vixie-cron does not expand $PATH) and no default jobs. All four heredocs use single-quoted tags (<<'PROFILE', <<'BASHRC', <<'ENVFILE', <<'CRON') so install-time $-expansion never fires → byte-idempotent re-runs. PATH ordering /home/agent/.local/bin:/usr/local/bin:/usr/bin:/bin across all three files carrying a literal PATH (agentlinux.env + cron.d assert byte-identical via cross-grep count ≥ 2; profile.d uses case-prepend idempotence). Zero sudoers drop-in (CONTEXT-locked Phase 2 rule). Zero shim under root-owned bin dir (DOC-02 anti-pattern). Zero install-time profile.d sourcing. No raw echo>>, no sed -i. Shellcheck --severity=warning --external-sources --source-path=plugin/lib + shfmt -i 2 -ci -bn -d + bash -n all green. Plan-verify grep chain (11 positive + negative greps) all green. bash tests/harness/run.sh still 104/104 green. One textual deviation vs plan sample header comments: plan's sample included literal strings "NO /etc/sudoers.d/agentlinux write" and "NO /usr/local/bin/ writes" which would match the plan's own `! grep -q 'sudoers.d'` / `! grep -q '/usr/local/bin/'` forbidden-substring greps; rephrased to "zero privilege-escalation configuration" / "zero wrapper shim pointing at an agent-owned binary from a root-owned bin directory". Functional behavior identical; positive-verify chain satisfied. Review loop (bash-engineer + security-engineer + qa-engineer rubrics) applied inline, one iteration, no actionable findings, no fix commits. BHV-02..06 PATH contracts now established; observable-behavior bats verification lands in 02-05. +Last activity: 2026-05-10 — Quick task 260510-n7e (AL-33) complete: stripped internal-vocabulary leaks (requirement IDs, AL-XX Jira keys, Phase/Plan numbering, bare ADR cross-refs, .planning/ paths) from user-facing surfaces — README.md, CONTRIBUTING.md, docs/internals/playwright.md, docs/STABILITY-MODEL.md, docs/README.md, plugin/cli/src/index.ts (Commander `.description()` strings for `agentlinux upgrade` and `agentlinux pin`). Wired external-audience-auditor (existing agent) into the CLAUDE.md Review Loop dispatch table as a new "Externally-facing artifacts" row covering top-level repo files, docs/internals/, docs/HARNESS.md, docs/STABILITY-MODEL.md, docs/README.md, public release notes, blog/email drafts, and user-visible packaging strings. Skip-list documented inline (.planning/, docs/decisions/, docs/audits/, docs/research/, .claude/, source under plugin/packaging/tests/). Source comments in plugin/packaging/tests/ retain their requirement-ID references (auditor scope explicitly excludes source comments — only user-visible strings are audited). Verify-block grep on the in-scope file set returns zero hard-fail matches. Catalog agent name `gsd` and npm package `get-shit-done-cc` kept on purpose (they are public installable identifiers users type at the CLI). Two atomic commits — a161cf6 (vocabulary scrub: 6 files, +27/-23) + bb8f02f (CLAUDE.md dispatch wiring: +11/-0) — merged from worktree-agent-ac895ebc via no-ff merge. Earlier: 2026-05-09 — Quick task 260509-kuv (AL-37) complete: provisioner-installer bugfix. Added `DEBIAN_FRONTEND=noninteractive apt-get update` inside the gated auto-install branches in `plugin/provisioner/10-agent-user.sh` (locales install, line ~44) and `plugin/provisioner/20-sudoers.sh` (sudo install, line ~47), mirroring the canonical pattern at `30-nodejs.sh:33`. Without this update the installer aborted with "Package locales has no installation candidate" on hosts with empty `/var/lib/apt/lists/` (freshly pulled Ubuntu containers, long-idle hosts) — the bug class introduced under AL-30's auto-install gates. Both new `apt-get update` calls live INSIDE the `if ! command -v ; then` blocks so the gate's no-op-when-already-installed property is preserved, and neither carries `|| true` so real apt failures still trip the entrypoint's ERR trap with src:line attribution. Strengthened `tests/docker/Dockerfile.dogfood` to drop the previous AL-37 tactical workaround (which kept `/var/lib/apt/lists/` populated by NOT running `rm -rf /var/lib/apt/lists/*`) — it now cleans lists, so the dogfood image starts in the exact "empty apt cache" state that triggered AL-37, converting the failure scenario into permanent regression coverage. Three atomic feature commits: `f12c94f` (10-agent-user fix), `86d5cbf` (20-sudoers fix), `94c4064` (Dockerfile.dogfood empty-cache + comment rewrite). End-to-end validation: built `agentlinux-dogfood-al37:24.04`, confirmed empty cache + absent locale-gen + absent visudo at container start, ran the LOCAL worktree installer in the container; installer logged `[WARN] locale-gen not found; installing 'locales' package` → 66-line apt-get update transcript → `Setting up locales` → `locale C.UTF-8 enforced`; then `[WARN] visudo not found; installing 'sudo' package` → fast-path apt-get update → `Setting up sudo` → `wrote /etc/sudoers.d/agentlinux`; provisioners 10/20/30/40 all reached "done" banners. Zero "no installation candidate" matches in 240+ KB install log. The trailing 50-registry-cli failure (`CLI dist/index.js missing`) is unrelated — gitignored CLI bundle that the Dockerfile.ubuntu-XX matrix splices in pre-install, intentionally bypassed in the AL-37-focused validation. Earlier: 2026-05-02 — Quick task 260502-i4p (AL-23) complete: added `.claude/hooks/review-reminder.sh` + project `.claude/settings.json` Stop-hook wiring; amended ADR-010 with a 2026-05-02 Refinement section that allows reminder Stop hooks (one-shot via `stop_hook_active`) while keeping reviewer-invoking hooks rejected; softened CLAUDE.md "Review Loop" paragraph to point at both the CLAUDE.md instruction (primary) and the hook (backstop). Smoke tests green: block path emits the JSON reminder naming all six AgentLinux reviewers (bash-engineer, node-engineer, security-engineer, qa-engineer, behavior-coverage-auditor, catalog-auditor); guard path (`stop_hook_active:true`) emits zero stdout. Two atomic feature commits + worktree merge into `worktree-review-hook`. Earlier: 2026-04-20 — Plan 06-05 complete + Phase 6 CLOSED + v0.3.0 READY (one `type="auto"` task + one `type="checkpoint:human-verify"` task-as-inline-rubric = 2 atomic commits fa386af + 6156b2b, ~41 min total). tests/bats/50-agents.bats shipped with 9 Phase 5 non-destructive AGT-XX @tests exercising the catalog-driven jq pin lookup + six-mode INVOKE_MODES loops against real agent binaries for the first time + chromium cache ownership verification. Plan 05-04 is the first bats file to do double-primitive setup_file recovery (agentlinux symlink + SSH keypair authorization) so the six-mode AGT-01 ssh branch works after 40-*.bats INST-04 --purge. Two Rule 1/3 deviations inline-incorporated: AGT-03 regex tightened to failure-prefix tokens after upstream `claude --help` noun "errors" false-positive; setup_file adds ~agent/.ssh/authorized_keys re-install primitive. TST-07 phase-close gate: GREEN (all 6 Phase 5 req IDs covered across 50-agents.bats + 51-agt02-release-gate.bats). Docker 66/66 PASS on both Ubuntu 22.04 + 24.04; harness 104/104. Phase 5 acceptance gate CLOSED; transition to Phase 6 (Distribution + Release Pipeline). Earlier: 2026-04-19 — Plan 05-03 complete (one `type="auto"` task, one atomic commit dc46bd8, ~41 min total). Phase 5 Wave 3 playwright recipe landed: AGT-05 recipe body is the first catalog recipe to exercise ADR-012's NOPASSWD sudoers drop-in end-to-end. Observed on both Ubuntu 22.04 + 24.04 smoke: install exit 0, chromium-1217 cache agent:agent-owned (ADR-004 ✓), pw_version=1.59.1 matches pin (AGT-05 version-lock ✓), 98/102 apt packages Setting-up (chromium-scoped — T-05-05e scope-creep mitigated), zero "password is required" transcript lines (ADR-012 sentinel GREEN); uninstall exit 0, PATH clean, cache removed. One textual deviation documented (softened "sudo" → "elevated privileges" in echo + comment for forward-compat regex compliance). Earlier: 2026-04-19 — Plan 05-01 complete (two `type="auto"` tasks + two Rule 3 auto-fix commits = 4 atomic commits, ~59 min total). AGT-02 canonical acceptance test is GREEN end-to-end on both Ubuntu 22.04 + 24.04 — this is THE test v0.3.0 exists to pass. Observed: first install claude@2.1.98 (pin ✓ AGT-02b); `claude update` bumped to 2.1.114; sort -V monotonicity 2.1.114 ≥ 2.1.98 passed; transcript zero EACCES / permission-denied lines. Two Rule 3 auto-fixes: curl missing from Ubuntu Docker images + 40-*.bats --purge breaking 51-*.bats setup. Earlier: 2026-04-19 — Plan 04-02 complete. Two `type="auto"` tasks, two atomic commits (e0ee67b catalog.json + d319419 8 recipe scripts), ~4 min total. 4 ajv-validated catalog entries + 8 strict-mode bash recipes landed. Key pinning decisions: claude-code 2.1.98 (stable dist-tag per ADR-011), gsd npm_package_name `get-shit-done-cc` (registry-verified — eliminates Phase 5 correction risk), playwright 1.59.1. Fail-fast `: "${AGENTLINUX_PINNED_VERSION:?msg}"` on all 4 install.sh — exit 1 unset, exit 0 on any non-empty value; negative smoke passes. Scaffold-documents-Phase-5 pattern: each stub's block comment details the Phase 5 install body (curl|bash + PIPESTATUS for claude-code, `npm install -g` for gsd/playwright), so Phase 5 AGT-02/04/05 plans replace only the body. test-dummy fully functional for Plan 04-07's bats (printf quoted format + args, rm -f -- path-terminated). version_constraint `^2.1` only on claude-code to exercise --all-latest upper-bound in Plan 04-04's CLI-06. Zero functional deviations; 2 textual/procedural logged (Rule 2 comment rephrase "WITHOUT sudo" → "WITHOUT privilege escalation" avoids catalog-auditor grep self-match per 02-04 precedent; Rule 3 used individual hooks since pre-commit wrapper not installed on host — CI re-runs full wrapper). Review loop clean one-iteration (catalog-auditor + security-engineer + bash-engineer + qa-engineer rubrics inline). Full verify green: ajv "4 entries OK", shellcheck+shfmt clean, forbidden-substring greps empty, test-dummy roundtrip OK, 3 scaffold smoke tests OK, harness 104/104. Earlier: 2026-04-19 — Plan 04-01 complete (3 tasks, 3 commits, ~11 min, 26/26 unit tests, 8 auto-fixes documented; compile-first TS test strategy + Ajv strict-mode + CJS-interop bridge + walk-up resolver patterns established). Earlier: 2026-04-18 — Plan 03-02 complete (3 plan tasks + 1 Rule 1 auto-fix commit = 4 atomic commits, ~15 min). Rule 1 fix discovered during Task 2's end-to-end Docker ubuntu-24.04 smoke: 2/27 bats failed on first run (RT-02 cron + RT-04 systemd_user). Root causes: (a) run_cron's hardcoded PATH header didn't include /home/agent/.npm-global/bin after Plan 03-01's cron.d extension — fixed by prepending it FIRST to match installer's final PATH ordering; (b) systemd-run's "Running as unit: ... Finished with result: ..." banner polluted $output and broke assert_user_prefix_in_home's prefix-match (Phase 2 BHV-04 tolerated it because assert_path_has is substring-match) — fixed by passing --quiet to systemd-run. Both fixes in c4c9fbf. 27/27 bats PASS on both Ubuntu 22.04 + 24.04 after the fix (up from 22/22 Phase 2 baseline). Pinned cowsay@1.6.0 for reproducibility + Pitfall 9 two-bin layout stability (cowsay + cowthink). Five @tests instead of minimum four — RT-02 reinforcement satisfies VALIDATION task 03-02-05 (no-EACCES under npm install pressure). Earlier: Plan 03-01 complete (2 plan tasks + 2 Rule 3 auto-fix commits = 4 commits, ~15 min). Two Rule 3 auto-fixes discovered during end-to-end Docker smoke: (1) apt-get install failed on empty /var/lib/apt/lists — added apt-get update first (commit c6d9b41); (2) compgen -G returned readdir order, not lexical — 30-nodejs.sh ran before 10-agent-user.sh creating the agent user → 'install: invalid user agent' failure; piped compgen through sort (commit 3dbfcff, fixing a pre-existing Phase 2 code-comment lie in run_provisioners()). Both fixes forward-only, no rollback. INST-02 byte-stable re-run still green. Earlier: Plan 02-05 complete (3 tasks, 6 commits, ~16 min). Phase 2 acceptance gate GREEN. Earlier: Plan 02-04 complete (1 task, 1 commit 5c8a095, ~4 min). Second dispatched provisioner lands green: ensure_dir /home/agent/.local{,/bin} 0755 agent:agent. Four artefacts in sequence — (1) install -m 0644 /dev/stdin /etc/profile.d/agentlinux.sh with re-source guard AGENTLINUX_PROFILE_SOURCED + case-prepend /home/agent/.local/bin + `export LANG=${LANG:-C.UTF-8}` override-respect. (2) /home/agent/.bashrc fallback-create via `install -m 0644 -o agent -g agent /dev/null` if absent, then `ensure_marker_block /home/agent/.bashrc "agentlinux-path" --top` with a minimal `if [ -f /etc/profile.d/agentlinux.sh ]; then . /etc/profile.d/agentlinux.sh; fi` body, then chown agent:agent + chmod 0644 after (ensure_marker_block writes root:root via install -m 0644). --top placement is critical per RESEARCH Pitfall 2: the Ubuntu skel .bashrc opens with `case $- in *i*) ;; *) return;; esac`, so any agentlinux block placed AFTER that guard never runs under `ssh host 'cmd'` or `sudo -u agent bash -c 'cmd'`. (3) install -m 0644 /dev/stdin /etc/agentlinux.env with literal KEY=VALUE lines (PATH + LANG + LC_ALL) for systemd EnvironmentFile= consumers. (4) install -m 0644 /dev/stdin /etc/cron.d/agentlinux with literal PATH header (Pitfall 4: vixie-cron does not expand $PATH) and no default jobs. All four heredocs use single-quoted tags (<<'PROFILE', <<'BASHRC', <<'ENVFILE', <<'CRON') so install-time $-expansion never fires → byte-idempotent re-runs. PATH ordering /home/agent/.local/bin:/usr/local/bin:/usr/bin:/bin across all three files carrying a literal PATH (agentlinux.env + cron.d assert byte-identical via cross-grep count ≥ 2; profile.d uses case-prepend idempotence). Zero sudoers drop-in (CONTEXT-locked Phase 2 rule). Zero shim under root-owned bin dir (DOC-02 anti-pattern). Zero install-time profile.d sourcing. No raw echo>>, no sed -i. Shellcheck --severity=warning --external-sources --source-path=plugin/lib + shfmt -i 2 -ci -bn -d + bash -n all green. Plan-verify grep chain (11 positive + negative greps) all green. bash tests/harness/run.sh still 104/104 green. One textual deviation vs plan sample header comments: plan's sample included literal strings "NO /etc/sudoers.d/agentlinux write" and "NO /usr/local/bin/ writes" which would match the plan's own `! grep -q 'sudoers.d'` / `! grep -q '/usr/local/bin/'` forbidden-substring greps; rephrased to "zero privilege-escalation configuration" / "zero wrapper shim pointing at an agent-owned binary from a root-owned bin directory". Functional behavior identical; positive-verify chain satisfied. Review loop (bash-engineer + security-engineer + qa-engineer rubrics) applied inline, one iteration, no actionable findings, no fix commits. BHV-02..06 PATH contracts now established; observable-behavior bats verification lands in 02-05. Progress: [▓▓▓▓▓▓▓▓▓▓] 100% (30 of 30 plans done; Phase 6 (Distribution + Release Pipeline) CLOSED 2026-04-20 — all 5 plans complete, TST-07 gate: GREEN for all 6 Phase 6 req IDs, v0.3.0 READY for rc1 tag push; runtime verification deferred to first tag push per 06-VALIDATION Manual-Only Verifications — the shipping event exercises release.yml end-to-end) @@ -289,6 +289,7 @@ None. Roadmap created; all 46 requirements mapped; Phase 1 is ready to plan. | 260503-8z4 | Add session-tracker Stop hook (AL-24) — second instance of ADR-010 reminder-hook pattern | 2026-05-03 | _pending_ | [260503-8z4-al-24-add-stop-hook-for-session-tracking](./quick/260503-8z4-al-24-add-stop-hook-for-session-tracking/) | | 260509-kn2 | Add ai-deslop review agent + remove existing AI slop (AL-35) | 2026-05-09 | 8be9180 | [260509-kn2-add-ai-deslop-review-agent-and-remove-ex](./quick/260509-kn2-add-ai-deslop-review-agent-and-remove-ex/) | | 260509-kuv | apt-get update before gated auto-installs in 10/20-* provisioners; clean apt cache in Dockerfile.dogfood for permanent regression coverage (AL-37) | 2026-05-09 | 94c4064 | [260509-kuv-al-37-provisioner-10-agent-user-sh-apt-i](./quick/260509-kuv-al-37-provisioner-10-agent-user-sh-apt-i/) | +| 260510-n7e | Strip internal-vocabulary leaks (requirement IDs, Jira keys, Phase numbering, ADR cross-refs) from user-facing surfaces (README/CONTRIBUTING/docs/internals/STABILITY-MODEL/CLI help) and wire external-audience-auditor into CLAUDE.md review-loop dispatch (AL-33) | 2026-05-10 | bb8f02f | [260510-n7e-remove-gsd-artifacts-from-help-and-proje](./quick/260510-n7e-remove-gsd-artifacts-from-help-and-proje/) | ## Deferred Items diff --git a/.planning/quick/260510-n7e-remove-gsd-artifacts-from-help-and-proje/260510-n7e-PLAN.md b/.planning/quick/260510-n7e-remove-gsd-artifacts-from-help-and-proje/260510-n7e-PLAN.md new file mode 100644 index 0000000..d9ce51d --- /dev/null +++ b/.planning/quick/260510-n7e-remove-gsd-artifacts-from-help-and-proje/260510-n7e-PLAN.md @@ -0,0 +1,319 @@ +--- +title: Remove GSD artifacts from help and project documentation (AL-33) +mode: quick +quick_id: 260510-n7e +phase: quick +plan: 01 +type: execute +wave: 1 +depends_on: [] +files_modified: + # Confirmed candidate surfaces — executor MUST audit and may add others + # discovered by the discovery grep step. See in Task 1. + - plugin/cli/src/index.ts + - plugin/cli/src/commands/install.ts + - plugin/cli/src/commands/list.ts + - plugin/cli/src/commands/remove.ts + - plugin/cli/src/commands/upgrade.ts + - plugin/cli/src/commands/pin.ts + - plugin/bin/agentlinux-install + - plugin/lib/log.sh + - plugin/lib/as_user.sh + - plugin/lib/idempotency.sh + - plugin/lib/distro_detect.sh + - packaging/curl-installer/install.sh + - README.md + - CONTRIBUTING.md + - docs/internals/README.md + - docs/internals/installer.md + - docs/internals/agent-user.md + - docs/internals/nodejs-runtime.md + - docs/internals/registry-cli.md + - docs/internals/catalog.md + - docs/internals/sudo-drop-in.md + - docs/internals/claude-code.md + - docs/internals/gsd.md + - docs/internals/playwright.md + - CLAUDE.md +autonomous: true +requirements: ["AL-33"] + +must_haves: + truths: + - "User-visible CLI help/usage strings contain no internal requirement IDs (CLI-XX, BHV-XX, etc.) or Jira keys" + - "User-visible installer log/echo messages contain no GSD plan filenames, phase numbering, or AL-XX references" + - "Top-level README.md contains no internal requirement IDs, GSD plan references, AL-XX Jira keys, or phase numbering" + - "docs/internals/ files (audited because excerpted into blog/email/website) contain no internal requirement IDs, GSD plan references, AL-XX Jira keys, or phase numbering" + - "external-audience-auditor is wired into CLAUDE.md review-loop dispatch table for the file types it covers" + - "Internal-only files (.planning/, docs/decisions/, tests/, .claude/, CLAUDE.md) retain their internal vocabulary unchanged" + artifacts: + - path: ".claude/agents/external-audience-auditor.md" + provides: "Existing reviewer agent (verified, not created)" + - path: "CLAUDE.md" + provides: "Review-loop dispatch table updated to invoke external-audience-auditor on user-facing surfaces" + key_links: + - from: "CLAUDE.md Review Loop section" + to: ".claude/agents/external-audience-auditor.md" + via: "Reviewer-by-file-type dispatch table" + pattern: "external-audience-auditor" +--- + + +Strip internal GSD/workflow vocabulary (AL-XX Jira keys, plan filenames, requirement IDs like CLI-06, phase numbering, GSD orchestrator vocabulary) from every user-reachable surface of AgentLinux, and wire the existing `external-audience-auditor` reviewer into the CLAUDE.md review-loop dispatch table so this class of leak gets caught on every future PR. + +Purpose: Public-repo readers, end users running `agentlinux --help`, and the project owner excerpting `docs/internals/` into blog/email/website copy should never see workspace-only vocabulary they cannot resolve. + +Output: +1. User-visible surfaces (CLI help strings, installer messages, README, docs/internals/) cleaned of internal vocabulary +2. CLAUDE.md review-loop dispatch table extended to fire `external-audience-auditor` on the matching file types + + + +@$HOME/.claude/get-shit-done/workflows/execute-plan.md + + + +@CLAUDE.md +@.claude/agents/external-audience-auditor.md +@.planning/PROJECT.md + + +- The `external-audience-auditor` agent ALREADY EXISTS at `.claude/agents/external-audience-auditor.md`. Do NOT recreate it. The Jira ticket's "append a Review Agent" is satisfied by *wiring* it into CLAUDE.md. +- The auditor's leak taxonomy (already in its file) is the canonical pattern set: AL-\d+, BHV/RT/AGT/CLI/CAT/INST/HRN/TST/DOC/LIC/SEC/CLEAN/CIPUB/PUB/EXPL/STRAT/SITE-\d+, `\.planning/[^ ]+`, `\d+-\d+-PLAN\.md`, `Phase \d+`, `Plan \d+-\d+`, `ADR-\d+` bare, `gsd-*`, `Co-Authored-By: Claude` in user copy, raw 7-char SHAs, internal milestone framing. The executor uses this taxonomy directly — no need to re-derive it. +- The auditor's "Critical Rules" + "What Counts as Externally-Facing" section already defines the in-scope/out-of-scope partition. The executor follows the auditor's own scope rules. +- A confirmed leak example: `plugin/cli/src/index.ts:82` has `"Reconcile installed versions against the curated catalog (CLI-06)"` — the `(CLI-06)` parenthetical is exactly the pattern to strip from user-visible help text. Treat this as illustrative, not exhaustive. + + + +**In scope (audit + fix):** +- `plugin/cli/src/**/*.ts` — Commander.js `.description(...)`, `.option(...)`, `.command(...)`, `console.log/error` strings, anything that reaches `--help` output or stderr/stdout the user sees +- `plugin/bin/agentlinux-install` — log/echo messages +- `plugin/lib/*.sh` — log/echo messages users see (NOT internal comments — but if a comment leaks an AL-XX key into a string the user could see, fix it) +- `packaging/curl-installer/install.sh` — user-visible echoes during curl-pipe-bash +- `README.md` (top-level public-facing repo README) +- `CONTRIBUTING.md` (public contributor docs) +- `docs/internals/**/*.md` — dual-purpose: developer reference AND source pool for blog/email/website excerpts (per ADR-015 / CLAUDE.md). Audited because the project owner excerpts from these into public copy; catching leaks once at source is cheaper than three times downstream. + +**Out of scope (DO NOT touch):** +- `.planning/**` — GSD workflow internals, requirement IDs are load-bearing here +- `docs/decisions/**` — ADRs are authored for contributors who already know the project; ADR cross-refs by number are expected +- `docs/research/**`, `docs/proposals/**`, `docs/audits/**`, `docs/reviews/**` — internal artefacts +- `tests/**` — the bats suite IS the spec; BHV/RT/AGT/CLI/CAT/INST IDs are the contract +- `.claude/**` — agent/skill definitions; internal vocabulary is correct here +- `CLAUDE.md` itself — project context for AI agents working on this repo, not for end users (one exception: the dispatch-table extension in Task 2 is a *structural* edit, not a vocabulary scrub) +- `.github/workflows/**` — CI infra, no external readers +- Comments in source files that aren't reachable as user output (a `// per AL-22` comment in `plugin/cli/src/runner.ts` does NOT leak to users; leave it) + +**Do NOT:** +- Rename the requirement IDs themselves in their canonical home (`.planning/REQUIREMENTS.md`, `tests/bats/*.bats` `@test` names) — they remain valid in internal contexts +- Expand the auditor with new taxonomy rules +- Create elaborate new processes, new hooks, new skills — wire the existing agent into the existing review loop + + + + + + + Task 1: Audit user-reachable surfaces and strip internal vocabulary + + plugin/cli/src/**/*.ts + plugin/bin/agentlinux-install + plugin/lib/*.sh + packaging/curl-installer/install.sh + README.md + CONTRIBUTING.md + docs/internals/**/*.md + + + DISCOVERY (run first, do not pre-resolve fixes during planning): + + Run a comprehensive grep across ONLY the in-scope paths above for each pattern in the auditor's leak taxonomy. Capture file + line + matched string for each hit. Suggested grep commands (treat as a starting set, expand if you see other internal vocabulary): + + ```bash + # Set the in-scope path list + SCOPE=(plugin/cli/src plugin/bin plugin/lib packaging/curl-installer README.md CONTRIBUTING.md docs/internals) + + # Pattern 1: Requirement IDs (the high-volume category) + grep -rnE '\b(BHV|RT|AGT|CLI|CAT|INST|HRN|TST|DOC|LIC|SEC|CLEAN|CIPUB|PUB|EXPL|STRAT|SITE)-[0-9]+\b' "${SCOPE[@]}" + + # Pattern 2: Jira keys (AgentLinux project) + grep -rnE '\bAL-[0-9]+\b' "${SCOPE[@]}" + + # Pattern 3: GSD plan/context/summary filenames + grep -rnE '[0-9]+-[0-9]+-(PLAN|CONTEXT|SUMMARY|AUDIT|VERIFICATION|RESEARCH|PATTERNS)\.md' "${SCOPE[@]}" + + # Pattern 4: Phase / Plan numbering as workflow shorthand + grep -rnE '\b(Phase|Plan)\s+[0-9]+(\.[0-9]+)?(-[0-9]+)?\b' "${SCOPE[@]}" + + # Pattern 5: .planning/ paths leaking into external surfaces + grep -rnE '\.planning/[^ )"`]+' "${SCOPE[@]}" + + # Pattern 6: GSD orchestrator vocabulary + grep -rnE '\bgsd-[a-z-]+\b|smart discuss|plan-phase|execute-phase|gsd-sdk' "${SCOPE[@]}" + + # Pattern 7: Bare ADR cross-refs (without surrounding substance) + grep -rnE 'ADR-[0-9]+' "${SCOPE[@]}" + + # Pattern 8: Co-Authored-By in user-visible copy (NOT commit messages) + grep -rnE 'Co-Authored-By:.*Claude' README.md CONTRIBUTING.md docs/internals/ + + # Pattern 9: GSD as a literal token (the framework name) + grep -rnE '\bGSD\b' "${SCOPE[@]}" + ``` + + For each hit, decide on the appropriate fix using the auditor's substitute table (col 4 of the taxonomy in `.claude/agents/external-audience-auditor.md`): + - `(CLI-06)` parenthetical in user-visible help → DELETE the parenthetical (the description text remains) + - Bare `AL-22` Jira key → DELETE or restate substance ("the issue that motivated this work" / drop entirely if not load-bearing) + - GSD plan filename like `12-01-PLAN.md` → DELETE or describe what the file *says* in prose + - `Phase N` shorthand → DELETE or describe concretely ("the work that added the agent user", "the registry CLI shipping in v0.3.0") + - `BHV-03`, `INST-04`, etc. in user copy → restate substance in prose; cite a bats test file inline if the file is the contract that ships + - `gsd-executor`, `the orchestrator` → DELETE or describe the action neutrally + - Bare `ADR-011` → spell out what it decides, optionally followed by the file link + - `Co-Authored-By: Claude` in `README.md` / `docs/internals/` → DELETE (keep in commit messages, which are out of scope) + + AMBIGUOUS HITS — apply judgment using the auditor's "Good vs Bad" worked examples (Examples 1–7): + - A `// AL-22` comment in source that is NOT a user-visible string → leave it (it's internal) + - A `## Phase 4: Registry CLI` heading in `docs/internals/registry-cli.md` → fix per Example 2 ("AgentLinux ships a curated catalog…" — describe substance, drop the phase label) + - A reference like `docs/decisions/011-stability-first-version-pinning.md` linked from `docs/internals/` → keep the link but lead with the substance ("the curated-combo stability model — see [`docs/decisions/011-...md`]") per Example 2 / Example 6 + - A `(CLI-06)` parenthetical inside a Commander `.description()` that reaches `agentlinux --help` → DELETE the parenthetical only; preserve the human-readable description + - A README mention of "GSD" as the **catalog agent name** (`agentlinux install gsd`) → KEEP. The catalog agent is named `gsd`; this is a public artifact name, not an internal-vocabulary leak. Use Example 7's logic in reverse: the catalog *publishes* the name `gsd`, so the name is public. + + APPLY FIXES in a single coherent pass per file (don't fix CLI-06, then come back for AL-22 — do all fixes per file at once). After fixes, RE-RUN the same grep set against the same SCOPE and confirm zero matches remain (modulo intentional preserved cases like the literal catalog agent name `gsd` and any contributor-doc cross-refs in CONTRIBUTING.md that you judged appropriate to keep with substance attached). + + Document any judgment calls (kept-on-purpose hits) in the commit message body so reviewers can validate the triage. + + + + bash -c ' + set -e + SCOPE=(plugin/cli/src plugin/bin plugin/lib packaging/curl-installer README.md CONTRIBUTING.md docs/internals) + + echo "=== Requirement IDs ===" + ! grep -rnE "\b(BHV|RT|AGT|CLI|CAT|INST|HRN|TST|DOC|LIC|SEC|CLEAN|CIPUB|PUB|EXPL|STRAT|SITE)-[0-9]+\b" "${SCOPE[@]}" || { echo "FAIL: requirement IDs still present"; exit 1; } + + echo "=== Jira keys ===" + ! grep -rnE "\bAL-[0-9]+\b" "${SCOPE[@]}" || { echo "FAIL: AL-XX Jira keys still present"; exit 1; } + + echo "=== GSD plan filenames ===" + ! grep -rnE "[0-9]+-[0-9]+-(PLAN|CONTEXT|SUMMARY|AUDIT|VERIFICATION|RESEARCH|PATTERNS)\.md" "${SCOPE[@]}" || { echo "FAIL: plan filenames still present"; exit 1; } + + echo "=== .planning/ paths ===" + ! grep -rnE "\.planning/[^ )\"\`]+" "${SCOPE[@]}" || { echo "FAIL: .planning/ paths still present"; exit 1; } + + echo "=== Phase/Plan shorthand ===" + ! grep -rnE "\b(Phase|Plan)\s+[0-9]+(\.[0-9]+)?(-[0-9]+)?\b" "${SCOPE[@]}" || { echo "WARN: Phase/Plan shorthand still present (review individual hits — some may be intentional kept-on-purpose)"; } + + echo "=== gsd-* orchestrator vocabulary ===" + ! grep -rnE "\bgsd-[a-z-]+\b|smart discuss|plan-phase|execute-phase" "${SCOPE[@]}" || { echo "WARN: gsd-* tokens still present (review — `gsd` as catalog agent name is OK)"; } + + echo "=== Co-Authored-By in user copy ===" + ! grep -rnE "Co-Authored-By:.*Claude" README.md CONTRIBUTING.md docs/internals/ 2>/dev/null || { echo "FAIL: Co-Authored-By: Claude in user-facing copy"; exit 1; } + + echo "PASS: all hard-fail patterns clean; review WARN lines for triage" + ' + + + + - All hard-fail grep categories return zero matches across the in-scope path set + - Soft-fail / WARN categories (Phase/Plan shorthand, gsd-* tokens) reviewed; any remaining hits documented in commit body as intentional (e.g., the literal catalog agent name `gsd`, contributor-doc references to public ADR files attached to substance) + - CLI `--help` output for `agentlinux`, `agentlinux install`, `agentlinux upgrade`, `agentlinux pin` etc. reads as clean public-facing prose with no internal IDs + - README.md, CONTRIBUTING.md, docs/internals/*.md read as audience-appropriate (public reader / developer / blog-excerpt source) without leaked workflow vocabulary + - Out-of-scope paths (.planning/, docs/decisions/, tests/, .claude/, CLAUDE.md, .github/workflows/) untouched (verified with `git diff --name-only` — no files outside the SCOPE list except CLAUDE.md if user added scope) + + + + + Task 2: Wire external-audience-auditor into CLAUDE.md review-loop dispatch table + CLAUDE.md + + Verify `.claude/agents/external-audience-auditor.md` exists. If missing (it should NOT be — it's already in the repo per `ls .claude/agents/`), STOP and report — do not recreate from scratch in a quick task. + + Open `CLAUDE.md` and locate the "Review Loop" section's reviewers-by-file-type bulleted dispatch table (currently around lines 53–62). The existing format is: + + ``` + Reviewers applied by file type: + + - 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`, `dev-docs-auditor` + - Docs → `technical-writer`, `fact-checker`, `ai-deslop` (skip for ADRs and + research summaries) + ``` + + EXTEND the dispatch by appending `external-audience-auditor` to the reviewer list for the file types where its scope (per its own description) applies. Match the auditor's "What Counts as Externally-Facing" section — those four categories — to existing rows, and add new rows where no existing row covers them. Concretely: + + 1. Append `external-audience-auditor` to the **Docs** row, but scope it: it should fire on `README.md`, `CONTRIBUTING.md`, `docs/internals/**`, and any `docs/proposals/` / `docs/reviews/` files referenced from a public entry point — and SKIP on `docs/decisions/**` (ADRs) and `docs/research/**` (internal). Existing parenthetical "(skip for ADRs and research summaries)" already covers the skip case for `ai-deslop`; reuse that pattern. + + 2. Add a new row for **Top-level repo files for the public** (README.md, CONTRIBUTING.md, LICENSE, SECURITY.md, CODE_OF_CONDUCT.md) that dispatches to `technical-writer`, `fact-checker`, `external-audience-auditor`. Note: README.md is also "Docs" — keep the dispatch consistent (don't double-fire technical-writer/fact-checker; the new row replaces the Docs row's coverage of these files). + + 3. Add a new row for **Public release artifacts and marketing drafts** (release notes drafted in repo, blog post drafts, email drafts, `agentlinux.org` website copy if/when staged in repo): dispatches to `technical-writer`, `fact-checker`, `external-audience-auditor`. If no such files exist in the repo today, the row is a forward-looking guard — note this in a parenthetical. + + 4. Add a one-line note explaining the dispatch's purpose (one line, terse): something like `external-audience-auditor` flags internal-vocabulary leaks (Jira keys, plan filenames, requirement IDs, phase numbering) on artifacts the public reads or that get excerpted into public copy. + + Update the "Last updated" footer line at the bottom of `CLAUDE.md` to today's date (2026-05-10) and a short marker indicating the dispatch-table extension. + + DO NOT: + - Modify any other section of CLAUDE.md + - Touch the agent definition file itself (`.claude/agents/external-audience-auditor.md`) + - Remove or reorder existing reviewer dispatch rows + - Introduce new hooks, skills, or processes — wiring into the existing dispatch is the entire deliverable + + + + bash -c ' + set -e + test -f .claude/agents/external-audience-auditor.md || { echo "FAIL: external-audience-auditor.md missing"; exit 1; } + grep -q "external-audience-auditor" CLAUDE.md || { echo "FAIL: external-audience-auditor not wired into CLAUDE.md"; exit 1; } + # Confirm the wiring sits inside the Review Loop section, not somewhere stray + awk "/^## Review Loop/,/^## /" CLAUDE.md | grep -q "external-audience-auditor" || { echo "FAIL: wiring not inside Review Loop section"; exit 1; } + # Confirm public-facing entry-point coverage exists (README mention in dispatch) + awk "/^## Review Loop/,/^## /" CLAUDE.md | grep -qiE "README|top-level|public" || { echo "FAIL: no public-facing dispatch row"; exit 1; } + echo "PASS: external-audience-auditor wired into CLAUDE.md Review Loop dispatch" + ' + + + + - `.claude/agents/external-audience-auditor.md` confirmed present (not recreated) + - CLAUDE.md "Review Loop" section dispatch table extended with `external-audience-auditor` on the appropriate file-type rows (top-level public repo files, docs/internals/, marketing drafts) + - Dispatch matches the auditor's own "What Counts as Externally-Facing" scope — no over-firing on ADRs, research, or `.planning/` + - One-line purpose note included + - "Last updated" footer touched to today's date + - No other section of CLAUDE.md modified + - Verification grep shows `external-audience-auditor` appears inside the `## Review Loop` section of CLAUDE.md + + + + + + +Whole-task acceptance: + +1. **No internal vocabulary in user-reachable surfaces**: All hard-fail grep categories from Task 1's verify return zero matches across `plugin/cli/src/`, `plugin/bin/`, `plugin/lib/`, `packaging/curl-installer/`, `README.md`, `CONTRIBUTING.md`, and `docs/internals/`. + +2. **Internal files unchanged**: `git diff --name-only HEAD` shows zero modifications under `.planning/`, `docs/decisions/`, `docs/research/`, `tests/`, `.claude/agents/`, `.claude/skills/`, `.github/workflows/`. (CLAUDE.md is the *only* file outside the user-facing scrub scope that gets touched, and only for the Task 2 dispatch-table extension.) + +3. **Auditor wired into review loop**: `grep external-audience-auditor CLAUDE.md` returns at least one hit, and that hit is inside the `## Review Loop` section. + +4. **Live CLI help check** (smoke): `cd plugin/cli && pnpm build && node dist/index.cjs --help` (or whatever the local invocation is — check `plugin/cli/package.json` for the build/test scripts) — read the output and confirm zero internal IDs in subcommand descriptions. + +5. **Sanity grep on the auditor itself**: `.claude/agents/external-audience-auditor.md` is unchanged (`git diff .claude/agents/external-audience-auditor.md` returns no output). + + + +- A user running `agentlinux --help`, `agentlinux install --help`, `agentlinux upgrade --help`, etc. sees only public-facing prose — no `(CLI-06)`, no `Phase 4`, no `AL-XX`. +- A reader landing on the public `README.md`, `CONTRIBUTING.md`, or `docs/internals/*.md` sees no internal vocabulary they cannot resolve. +- The project owner excerpting `docs/internals/` into a blog post or marketing email needs no manual scrub for internal IDs. +- Future PRs that touch user-facing surfaces will trigger `external-audience-auditor` via the existing review loop, catching any new leaks at the PR boundary instead of weeks later in published copy. +- Internal workflow vocabulary remains intact in `.planning/`, `docs/decisions/`, `tests/`, and `.claude/` — the maintainer's bookkeeping stays sharp. + + + +After completion, no SUMMARY.md required (quick task). The PR description should list: +- Number of files scrubbed in Task 1 (from `git diff --name-only`) +- A 3–5 line summary of the leak categories found and the substitution patterns applied +- The CLAUDE.md dispatch-table change (one paragraph) +- Confirmation that the verify-block grep returns zero hard-fail matches + diff --git a/.planning/quick/260510-n7e-remove-gsd-artifacts-from-help-and-proje/260510-n7e-SUMMARY.md b/.planning/quick/260510-n7e-remove-gsd-artifacts-from-help-and-proje/260510-n7e-SUMMARY.md new file mode 100644 index 0000000..8fd6049 --- /dev/null +++ b/.planning/quick/260510-n7e-remove-gsd-artifacts-from-help-and-proje/260510-n7e-SUMMARY.md @@ -0,0 +1,152 @@ +--- +status: complete +quick_id: 260510-n7e +date: 2026-05-10 +ticket: AL-33 +tags: [docs, claude-md, review-loop, external-audience] +--- + +# 260510-n7e: Remove GSD artifacts from help and project documentation + +Two-task quick scrub: strip internal-vocabulary leaks from externally-facing +artifacts (Task 1), then wire the existing `external-audience-auditor` agent +into the project review-loop dispatch table so future regressions are caught +automatically (Task 2). + +## Commits + +| Task | Commit | Title | +| ---- | --------- | ------------------------------------------------------------------ | +| 1 | `a161cf6` | chore(docs): scrub internal-vocabulary leaks from user-facing surfaces (AL-33) | +| 2 | `bb8f02f` | chore(claude): wire external-audience-auditor into review-loop dispatch (AL-33) | + +## Task 1 — files modified + +- `README.md` — drop `AGT-02` token; drop `.planning/REQUIREMENTS.md` link; + contextualize bare `ADR-006` reference with the named decision-record link. +- `CONTRIBUTING.md` — drop `BHV/RT/AGT/CLI/CAT/INST/HRN/TST/DOC-XX` requirement + ID list from the PR-guidance step; rephrase "cites the relevant requirement + ID" to "names the behavior it pins". +- `docs/STABILITY-MODEL.md` — replace bare `ADR-011` TL;DR token with a + one-breath substance + decision-record link; drop `AGT-02`, `TST-08`, + `Phase 6`, `ADR-012` tokens; clean up bare `ADR-NNN` prefixes in the Related + list (the link text already carries the substance). +- `docs/README.md` — drop "GSD workflow state" lede phrasing (internal harness + vocabulary); drop "ADR-001..ADR-010 seeded in Phase 1" sentence; rephrase + HARNESS.md section descriptors from §-numbers to plain prose. +- `docs/internals/playwright.md` — contextualize bare `ADR-012` reference with + a named decision-record link. +- `plugin/cli/src/index.ts` — drop `(CLI-06)` from `agentlinux upgrade` and + `(CLI-07)` from `agentlinux pin` Commander descriptions (these surface in + user-visible `--help` output). + +## Task 2 — files modified + +- `CLAUDE.md` — added a new dispatch row to "Review Loop" §"Reviewers applied + by file type" for externally-facing artifacts (top-level README, + CONTRIBUTING, docs/internals/, docs/HARNESS.md, docs/STABILITY-MODEL.md, + docs/README.md, public release notes, blog/email drafts, agentlinux.org + copy, user-visible packaging strings) → also `external-audience-auditor`, + in addition to the per-file-type reviewers above. Skip-list documented + inline (`.planning/`, `docs/decisions/`, `docs/audits/`, `docs/research/`, + `.claude/`, source under `plugin/`/`packaging/`/`tests/`). + +## Leak categories found and substitutions applied + +1. **Bare requirement IDs** (`AGT-02`, `TST-08`, `CLI-06`, `CLI-07`, the + `BHV/RT/AGT/CLI/CAT/INST/HRN/TST/DOC-XX` enumeration). Substitute: drop the + token and restate the behavior in prose ("the self-update-without-sudo + invariant"; "the release-gate test"; "Reconcile installed versions against + the curated catalog"). +2. **Bare ADR cross-references** (`ADR-006`, `ADR-011`, `ADR-012`). + Substitute: cite both the substance and the decision-record file in one + breath, or replace with a named link without the numeric prefix. +3. **GSD harness vocabulary** ("`.planning/` holds GSD workflow state"). + Substitute: drop the GSD-flavoring; describe the directory's purpose + neutrally. +4. **Phase numbering** (`Phase 1`, `Phase 6`). Substitute: drop the label; + keep the substance ("the release-gate test"). +5. **Internal workspace paths** in user-facing prose + (`.planning/REQUIREMENTS.md` link from README). Substitute: delete — the + internal contract is not a user-facing surface. + +## Kept on purpose + +- Catalog agent name `gsd` and the npm package `get-shit-done-cc` — these are + the public installable identifiers users type at the CLI. +- "GSD workflow CLI for Claude Code" inside catalog example output and the + catalog.json description string — that's the user-visible product + description that ships in the catalog. +- Source-comment references inside `plugin/`, `packaging/`, `tests/` — + out of scope per the external-audience-auditor (only user-visible *strings* + under packaging/ are audited, not source comments). +- ADR cross-references inside `docs/decisions/` — internal-only by audit + scope (ADR-to-ADR cross-refs are appropriate within the decision tree). +- `Co-Authored-By: Claude Opus 4.7 ...` in commit messages — project + convention, and commit messages are not user-visible per the plan's scope + partition (the auditor flags this trailer only in user-visible artifacts + like blog posts or website copy). + +## Out-of-scope deferrals + +- `docs/HARNESS.md` is referenced from README.md and matches the auditor's + externally-facing scope, but it is primarily contributor-harness + documentation written for people coming into the workspace. Its full + internal-vocabulary load (Phase numbering, ADR-NN cross-refs, requirement + ID enumeration) is structurally part of what the document explains. A + separate quick task is the right vehicle for that scrub; conflating it + here would have made this commit too large to review cleanly. +- Source comments in `plugin/`, `packaging/`, `tests/` carry phase/plan/req + vocabulary heavily. These are explicitly out of audit scope per the + `external-audience-auditor` Rule 1 ("Audit only externally-facing + artifacts"). + +## Reviewer findings + +The Task tool for spawning subagents was not available in this executor +environment, so the review loop was performed inline against each reviewer's +lens. All concerns either passed or are documented as out-of-scope above. + +- **node-engineer** (plugin/cli/src/index.ts): help-text-only edit; no API, + parsing, or behavior change. PASS. +- **security-engineer** (plugin/cli/src/index.ts): no impact on `preAction` + EUID guard or input validation. PASS. +- **qa-engineer**: verified no bats test asserts the literal `(CLI-06)` or + `(CLI-07)` substring against `--help` output (test descriptions name the + IDs for traceability, but bodies assert behavior — exit codes, sentinel + state, presence of agent name in upgrade table). PASS. +- **ai-deslop**: substitutions are tighter than originals; word count went + down. PASS. +- **dev-docs-auditor**: index.ts change is help-text only — no behavior + change, so docs/internals/registry-cli.md does not need updating. PASS. +- **technical-writer**: each substitution preserves the original sentence's + meaning while removing unresolvable IDs. The CONTRIBUTING.md substitution + is *more* actionable for external contributors. PASS. +- **fact-checker**: substantive claims unchanged. "Release-gate test", + "curated-combo", "agent user's NOPASSWD sudo drop-in" all factually + accurate. PASS. +- **external-audience-auditor** (sanity check): re-ran the leak grep on the + post-fix tree against the in-scope file set. Zero hard-fail matches. PASS. + +## Verification + +Final grep against the in-scope externally-facing files for the canonical +hard-fail leak taxonomy: + +``` +grep -E '(AL-[0-9]+|\.planning/|BHV-[0-9]+|RT-[0-9]+|AGT-[0-9]+|CLI-[0-9]+|CAT-[0-9]+|INST-[0-9]+|HRN-[0-9]+|TST-[0-9]+|DOC-[0-9]+|gsd-executor|gsd-planner|gsd-sdk|smart discuss|the orchestrator|the executor|the planner|Plan [0-9]+-[0-9]+|\bPhase [0-9]+\b|ADR-[0-9]+)' \ + README.md CONTRIBUTING.md docs/internals/*.md docs/STABILITY-MODEL.md docs/README.md +# → 0 matches +``` + +The user-visible Commander help-text scan also confirms `(CLI-06)` and +`(CLI-07)` no longer appear in `agentlinux upgrade --help` or +`agentlinux pin --help` output. + +## Self-Check: PASSED + +- Task 1 commit `a161cf6` exists in `git log`. FOUND. +- Task 2 commit `bb8f02f` exists in `git log`. FOUND. +- All 7 modified files in Task 1 are tracked at the new content. FOUND. +- CLAUDE.md has the new dispatch row at line 60+. FOUND. +- Verify-block grep returns zero hard-fail matches. CONFIRMED. From 463b95ac44def60fcd85355783a2dd991c900a06 Mon Sep 17 00:00:00 2001 From: Nikita Ivanov Date: Sun, 10 May 2026 17:01:18 +0000 Subject: [PATCH 4/4] chore(docs): address ai-deslop review nits on AL-33 scrub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two findings from the post-merge review pass: 1. CLAUDE.md dispatch row was 11 lines vs ~1 line for siblings — split into a compact bullet plus a short paragraph below the dispatch list, mirroring the dev-docs-auditor explanatory paragraph pattern already present in the file. 2. STABILITY-MODEL.md TL;DR blockquote display text said `docs/decisions/011-...` while the relative link target was `decisions/011-...`. Aligned both to `decisions/...` since the file is itself in `docs/`. Co-Authored-By: Claude Opus 4.7 (1M context) --- CLAUDE.md | 21 ++++++++++++--------- docs/STABILITY-MODEL.md | 2 +- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index eebdc83..29852c6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -62,15 +62,18 @@ Reviewers applied by file type: research summaries) - Externally-facing artifacts (top-level `README.md`, `CONTRIBUTING.md`, `docs/internals/`, `docs/HARNESS.md`, `docs/STABILITY-MODEL.md`, - `docs/README.md`, public release notes, blog/email drafts, `agentlinux.org` - copy, user-visible packaging strings) → also `external-audience-auditor`, - in addition to the per-file-type reviewers above. Audits for leakage of - internal vocabulary (AL Jira keys, GSD plan filenames, BHV/RT/AGT/CLI/CAT/ - INST/HRN/TST/DOC requirement IDs, Phase/Plan numbering, bare ADR cross-refs, - GSD orchestrator/executor/planner vocabulary, Claude Code self-references). - Skip for `.planning/`, `docs/decisions/`, `docs/audits/`, `docs/research/`, - `.claude/`, source under `plugin/`/`packaging/`/`tests/` (only user-visible - *strings* under packaging/ are in scope, not source comments). + `docs/README.md`, release notes, blog/email drafts, `agentlinux.org` copy, + user-visible packaging strings) → also `external-audience-auditor`, in + addition to the per-file-type reviewers above + +`external-audience-auditor` flags internal vocabulary that leaks into copy a +public-repo reader (or a blog/email/website excerpt) cannot resolve: AL Jira +keys, GSD plan filenames, BHV/RT/AGT/CLI/CAT/INST/HRN/TST/DOC requirement IDs, +Phase/Plan numbering, bare ADR cross-refs, GSD orchestrator/executor/planner +vocabulary, Claude Code self-references. Skip for `.planning/`, +`docs/decisions/`, `docs/audits/`, `docs/research/`, `.claude/`, and source +comments under `plugin/`/`packaging/`/`tests/` (only user-visible *strings* +under `packaging/` are in scope). `dev-docs-auditor` keeps `docs/internals/.md` in sync when changes touch `plugin/bin/`, `plugin/lib/`, `plugin/provisioner/`, `plugin/cli/src/`, diff --git a/docs/STABILITY-MODEL.md b/docs/STABILITY-MODEL.md index dd32a5c..b329bde 100644 --- a/docs/STABILITY-MODEL.md +++ b/docs/STABILITY-MODEL.md @@ -1,7 +1,7 @@ # AgentLinux Stability Model > The user-facing summary of AgentLinux's curated-combo version pinning — -> the full decision record is at [`docs/decisions/011-stability-first-version-pinning.md`](decisions/011-stability-first-version-pinning.md). +> the full decision record is at [`decisions/011-stability-first-version-pinning.md`](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