docs(philosophy): lock setup-lifecycle convention#990
Conversation
Resolve the four setup-lifecycle design threads and encode the outcome in the "Setup is explicit and repeatable" section of PLUGIN-PHILOSOPHY.md. - Verb set is closed at check/apply. apply is state-assessing (reconcile and report), which subsumes forward schema evolution; no standalone remove/reset/migrate verb joins the mandatory contract. The clean-break stance extends to setup config: reconcile-and-report stands in for a migration verb, never silent key translation. Genuine teardown stays an optional apply-scoped `apply remove` bounded to tracked project config (never pluginConfigs), deferred with a second-adopter owner-doc trigger; config-vs-data distinguishes teardown from ordinary apply surface. - Setup is one plugin-level skill, not a per-skill action: setup granularity follows install granularity, one discoverable entry point, one place disable-model-invocation is set, aggregating per-skill readiness. - Reconcile with the native Setup/SessionStart hook idioms the same section sanctions: the skill is the interactive consumer-config face no native hook exposes; the hooks are the complementary unattended faces. native- first is honored. Fleet audit (fresh-context) found zero nonconformers among 38 setup skills; the sharpened wording adds no requirement any existing skill violates, so this is a doc-only change. The two pre-existing missing-setup gaps (education, repo-hygiene) predate these decisions and are tracked in #988. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 2m 4s —— View job Review:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1a55b0b47b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ation Address review findings on #990. The codex reviewer surfaced a real contradiction: the absolute "clean-break stance (no migration tooling) extends to setup config" wording conflicts with the shipped standards- contract binding (review + planning setup), whose normative "Setup and migration" section defines a guided, directional, user-confirmed version upgrade that runs under apply (no separate verb, no silent writes). Reconcile: clean-break rules out silent backward-compat shims and dual-read windows, not a guided version-gated migration a plugin's own config contract defines and runs under apply. A plugin either carries such a guided upgrade (the versioned standards index) or takes topic-docs' clean-break move-by-hand path — neither uses a separate migrate verb, neither writes silently. Also fold reviewer clarity nits: de-hyphenate the compound adjective; note the teardown-owner-doc trigger rides the same fleet-audit enforcement as every convention-registry row; reword the native-idiom "requirement is satisfied in the interactive dimension" to avoid reading as partial satisfaction. markdownlint clean. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 2m 53s —— View job Review:
|
…opic is fully landed (#1004) ## Summary `docs/topics/lint-static-analysis-gaps/PLAN.md` is a contract-tier topic doc per `docs/conventions/topic-docs/README.md`: committed on the task branch only, pruned before merge once the topic's outcome lands (§"Contract-slice lifecycle"). It was added by PR #829 and never pruned. Epic #830 and all 6 sub-issues (#831-#836) plus the related setup-lifecycle epic (#837) are now merged and closed, so the topic's outcome has fully landed — pruning now, mirroring the same fix already applied to #836's leaked plan doc in PR #966. Content preserved for the record (from commit `4a289ab389`, PR #829): <details> <summary>Epic Brief (pruned)</summary> # Lint / static-analysis gaps ## Brief ### TLDR Close the fleet's lint/static-analysis gaps with one epic in this repo (typos hook plugin, Go coverage in both lanes, lychee-offline + pyright batch additions, .NET runtime guard, hook-observability convention, bespoke-guard routing), plus two epics owned elsewhere (setup-lifecycle convention here as its own design effort; standards adoption sweep + ecosystem-declaration in `melodic-software/standards`). ### Goal Local lanes catch what CI gates, so agents fix findings at edit time instead of burning commit–push–CI round-trips. Every addition follows the plugin philosophy: consumer-config-driven, zero shipped opinions, runtime detection over assumptions, advisory hooks that auto-fix silently and surface only residual unfixables. Epic sub-items (discuss-first honored — file only on explicit request; epic + sub-issues shape): 1. **typos hook plugin** — per-file autofix (`typos -w`), consumer `_typos.toml` ancestor walk-up, false-positive remediation via consumer allowlist entries (`extend-words` / `extend-identifiers` / `extend-ignore-re`), advisory residual-only context, hook-precision + hook-telemetry conventions. 2. **Go coverage, both lanes** — new `go` batch ecosystem default (golangci-lint v2, format, `go mod tidy`; govulncheck optional) and a Go format hook plugin. Formatter selection (gofmt / goimports / gofumpt / `golangci-lint fmt`) is an implementation-time field survey per the pick-for-the-problem discipline; criteria: official/authoritative, maintained, feature-fit. golangci-lint is batch-only by design (package-scope analysis, per its FAQ). 3. **lychee-offline** added to `cross-cutting.yaml` (on-disk link/anchor integrity; gating in CI, no network). 4. **pyright** added to `python.yaml` check-cmd (CI gates it; local batch was ruff-only). 5. **.NET batch guard** — `dotnet` ecosystem entry detects analyzer/`.editorconfig` configuration presence at runtime each run; skips with a visible notice when absent. No assumptions about consumer state; .NET stays batch-lane only. 6. **Hook-observability fleet convention** — every fleet hook emits `statusMessage` (during run), `systemMessage` (failure/notable action), and the hook-telemetry OTel envelope. Grounded in current official hooks docs at authoring time (no native user-visible hook UI exists as of 2026-07-21; OTel events + author-emitted messages are the sanctioned surfaces). Optional sub-item: upstream feature request for a native verbose-hooks UI toggle. 7. **Bespoke CI guards** (comment-hygiene, exec-bit, machine-specific-paths, reference-integrity) — sub-issue routed to `ci-workflows`/`standards`: local lane must invoke the same owned source (pointer-not-copy), which needs a small distribution decision those repos own. ### Constraints - Plugin philosophy governs: repo/user/machine/org-agnostic, two-lane convention posture, native-first, cross-platform (Windows/macOS/Linux), setup contract, graceful degradation. - Lane rule (locked): fast (<~2s), per-file, auto-fixing, consumer-config-discovering tool = hook plugin; slow / repo-wide / package-scope tool = toolchain batch entry; both when both fit. - Hooks auto-fix silently, never block, surface only residual unfixables (markdown-format pattern); hook-precision convention bounds false-positive noise. - New plugins conform to the setup-lifecycle convention once that epic lands. ### Acceptance criteria - Each epic sub-item lands as its own planned change with the normal pipeline (explore/research → plan → implement → review). - typos + Go hook plugins pass the plugin contract gate and fleet conformance audit. - Batch additions (go, lychee-offline, pyright, dotnet guard) are rung-4 defaults only — consumer `.claude/ecosystems/*.yaml` override ladder unchanged. - Hook-observability convention documented as an owner doc (convention registry row) and adopted by every fleet hook; conformance audited. - CI/local parity: gaps identified 2026-07-21 (Go toolchain, lychee-offline, pyright) have local coverage. ### Captured assumptions - No work-machine tool-install restriction (winget/brew acceptable). User to correct if wrong. - Single Go repo today (`ci-runner`); Go hook plugin justified by completeness preference (user choice) despite one consumer. ### Out of scope - Standards distribution-model redesign — model is settled (ADR-0001, accepted 2026-07-10); dissatisfaction, if it persists after reading the ADR rationale, is an ADR-supersede discussion in `standards`. - Consumer-config adoption gaps (ruff/pyright targets, dotnet-analysis to itinerary-planner / medley, TS/JS component admission, medley lychee) — standards epic below. - Setup-lifecycle convention design — own epic below. ### Deferred questions - YAML lint/format plugin — arbiter: USER-RESERVED. Trigger: a CI YAML gate lands in the fleet, or Biome ships YAML support (unshipped as of the 2026 roadmap). Facts: yamllint validate-only; yamlfmt autofixes but imposes defaults without consumer config. - gitleaks per-edit hook — arbiter: USER-RESERVED. Trigger: a local leaked-secret incident. Facts: `dir` mode (detect/protect deprecated v8.19), entropy false-positive noise, no autofix. - `dotnet format whitespace --folder` fast path — arbiter: USER-RESERVED. Whitespace-only today (bypasses MSBuild/restore; the only sub-2s path — full/style/analyzer modes pay project-load, ~1.3s minimum single file). Links: <https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-format>, <dotnet/format#757>. Trigger: an MSBuild-free style/analyzer path appears upstream. - Upstream feature request for native verbose-hooks UI — arbiter: /planning:plan (optional sub-item of the observability convention). ### Related epics (owned elsewhere) - **Setup-lifecycle convention** (this repo, own design session) — DONE (#837, PR #990). - **Standards adoption sweep + ecosystem-declaration enhancement** (`melodic-software/standards`) — still open, separate repo (`standards#230`). ## Plan (Empty — `/planning:plan` fills this per epic sub-item.) </details> ## Verification - [x] `git rm -r` only — no other changes; no build/test impact. - [x] Content fully preserved in git history (commit `4a289ab389`) and in this PR body. ## Related No linked issue — epic #830 is already closed (manually, since all 6 sub-issues plus the related setup-lifecycle epic #837 were done); this is a follow-up hygiene fix, not new epic work. Related PRs: #829 (added the brief), #966 (same fix applied to #836's leaked plan doc), #990 (#837, the last related item to land before this cleanup). --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Summary
Own design session for the setup-lifecycle convention (epic #830). Resolves the four threads in #837's body and encodes the outcome in the "Setup is explicit and repeatable" section of
docs/PLUGIN-PHILOSOPHY.md. Doc-only change (+45/−3 lines); no skill edits — see Verification.The four threads (locked)
1. Verb set —
remove/reset/migratevs state-assessingapply. The mandatory contract stays closed atcheckandapply.applyis state-assessing: it reads current state and converges — naming the existing idempotent-and-preserve-unrelated requirement as a verb contract, not a new bar. That subsumes the forward direction of "migrate": anapplymeeting prior-shape config fills absent keys at defaults, preserves unrecognized keys, and reports (never silently rewrites) values it cannot reconcile, so an obsolete/renamed key surfaces on re-run instead of sitting silently inert. It does not translate renamed/removed keys — the fleet's clean-break stance (no shims, no migration tooling) extends to setup config; reconcile-and-report replaces amigrateverb.reset= teardown +apply. Genuine teardown is an optional apply-scoped operation (apply remove), bounded to the plugin's own tracked project config — neverpluginConfigs(reconfigure/clear stays/plugin configure) — deferred with a second-adopter → owner-doc trigger.2. Per-skill setup action vs plugin setup skill. Setup is one plugin-level
setupskill, never a per-skill action. Primary rationale: setup granularity follows install granularity — a plugin installs and configures as a unit, and there is no native per-skill install anchor. One discoverable entry (/<plugin>:setup), one placedisable-model-invocationis set for configuration, one owner of a config surface that is routinely shared across skills; the setup skill aggregates per-skill readiness rather than fragmenting.3. Philosophy-doc update. Encoded in
PLUGIN-PHILOSOPHY.md— not a newdocs/conventions/setup-lifecycle/owner doc. Re-derived reasoning (not incumbency): the convention registry hosts inter-plugin coordination concerns whose rules are self-contained enough for one separate owner doc; the setup contract is an intra-plugin uniform contract — like Naming and Cross-platform, which also live in the philosophy doc and carry no registry row — and its rules are distributed across and dependent on three neighboring sections (Configuration ownership = what setup may write; Prerequisites = what it declares; Two-lane = the discover-via-setup lane), so extraction would duplicate or fragment them. Honest limitation (not resolved here, out of #837's scope): the registry's inclusion criterion is fuzzy at the edges (permission-rule-hygiene, skill-layout are per-plugin contracts that did get rows — distinguished by a separate enforcement mechanism needing its own home; setup's conformance rides the general fleet audit). The conclusion holds regardless.4. Fleet conformance. A fresh-context fleet audit found zero nonconformers among the 38 setup skills (all have
disable-model-invocation: true+ acheckaction; 35 offerapply; the 3 check-only — bug-report, dometrain, miro — are the sanctioned userConfig-only carve-out). Where teardown-like operations exist they are already apply-scoped arguments (songwriting: apply remove;machine-health: apply disable=/deprecate=/demote=/approve=), never separate lifecycle verbs — direct support for thread 1. The sharpened wording adds no requirement any existing skill violates, so this is doc-only. The lint-gap plugins (typos-format,go-format) already ship conforming check/apply setups. The only debt is two pre-existing missing-setup gaps (educationuserConfig-only;repo-hygienesingle kill-switch) that predate #837's decisions and are a distinct concern → tracked in #988.Fix
docs/PLUGIN-PHILOSOPHY.md"Setup is explicit and repeatable": adds the plugin-level decision, the closed verb set with the state-assessing/reconcile-and-reportapplyand the optional bounded teardown, and a paragraph reconciling the setup skill with the nativeSetup/SessionStarthook idioms the same section sanctions (complementary faces, native-first honored).Verification
applyoverwrites blind — config-writing setups carry read-first/reconcile/preserve language; the thin formatter setups are check-centric (verify tool presence, report "already configured" on rerun, write no user-owned config). Zero conformance debt confirmed.markdownlint-cli2 docs/PLUGIN-PHILOSOPHY.md→ 0 errors. No new links added. Emphasis/heading/list style conform (MD013 disabled repo-wide).Locked design threads (memory-tier artifact, pasted for the durable record)
Empirical grounding (verified 2026-07-22, live fleet)
setupskill; 18 do not (all 18 are zero-config/zero-prereq knowledge/methodology plugins — contract-exempt).name: setup+disable-model-invocation: true. 35 offer check+apply; 3 are check-only (bug-report, dometrain, miro) — all userConfig-only, the sanctioned carve-out.songwriting: apply scaffold|remove,machine-health: apply disable=|deprecate=|demote=|approve=.SetuporSessionStarthook event exists anywhere in the fleet today.Source: fresh-context fleet audit (independent subagent) + direct grep verification.
Thread resolutions
Thread 1 (verbs). Contract stays two verbs, check + apply.
applystate-assessing/reconciling;resetdecomposes to teardown + apply;migraterejected — clean-break (topic-docs "Adoption") generalized to setup config, a deliberately-named generalization. Teardown = optional apply-scopedapply remove, off the mandatory contract (rare, destructive, hand-reversible), with a second-adopter → owner-doc trigger.Thread 2 (plugin-level). Re-derived from install-granularity (a plugin installs/configures as a unit; no native per-skill install anchor), single discoverable entry, shared cross-skill config surface, verb-per-skill naming grammar. The setup skill aggregates per-skill readiness.
Thread 3 (philosophy-doc). Kept in PLUGIN-PHILOSOPHY.md, not a new owner doc: setup is an intra-plugin uniform contract (like Naming/Cross-platform, also non-registry) whose rules are distributed across three neighboring sections; extraction would fragment them. Registry inclusion criterion is genuinely fuzzy at the edges (acknowledged, not redrawn here — out of scope).
Thread 4 (conformance). Zero nonconformers among 38; sharpened wording adds no requirement any existing skill violates → doc-only. Lint-gap plugins (typos-format, go-format) already conform. Two pre-existing missing-setup gaps (education, repo-hygiene) predate these decisions → tracked in #988.
Adversarial stress-test ledger (fresh-context; verdict: safe with specific fixes, no thread reopened)
apply removeis teardown-ish (ONE); machine-healthapply disable=…is domain-data mutation, not teardown. Second-adopter trigger NOT yet met. Config-vs-data distinction folded into the doc.applyoverwrites blind (config-writers reconcile/preserve; formatter setups are check-centric).apply removevs pluginConfigs): teardown bounded to tracked project config, never pluginConfigs. Folded into the doc.Independent review (fresh-context, rationale withheld; verdict: ready with specific fixes)
Folded: #1 scope
disable-model-invocationto setup (not plugin-wide absolute); #2 split the dense verb paragraph and move thepluginConfigswrite-boundary/carve-out ahead of the teardown rule that leans on it; #3 disambiguate "noremoveverb" vsapply removeat first mention; plus cheap in-section wins #4 (migrate-token collision), #6 (config-vs-data criterion stated before the example), #7 (trim mid-sentence bold). markdownlint: 0 errors.Related
education+repo-hygiene(pre-existing missing-setup gaps, not closed here).Closes #837.