Repository navigation
feat(conventions): one setup lifecycle for where plugins store team conventions and settings #6594
Description
No related issue: this issue proposes the convention; #5906 migrates surfaces to it.
Summary
Define one repository-wide convention, owned by a new docs/conventions/setup-lifecycle/README.md
and recorded in one ADR that replaces ADR 0044, for how every plugin's setup skill stores and
maintains a team's conventions and settings:
- Conventions and settings live outside
.claude/: prose the model reads in
docs/conventions/<plugin>.md, values scripts read in a separatedocs/conventions/<plugin>.yaml,
so every agent and tool can use them. - Only the prose
.mdcan move; its path is set in the pointer. The.yamlstays at its fixed
default path, so scripts and hooks never parse a pointer. - The root
AGENTS.mdhas one managed block holding one short trigger line per plugin that needs
one, naming model-invokable skills. A plugin gets a line only with stumble evidence. Each setup
writes only its own line, after confirmation. - Setup keeps the closed verb set:
checkreports drift and writes nothing;applyconverges the
repository by detected state (init, migrate, or configure). Model-invoked skills tell the user to
run setup when conventions are missing or stale. - Each value records whether the team chose it or inherited a default, and each file records the
plugin version it was written against, so a changed plugin default updates inherited values and
only flags deliberate ones. - Files record current facts, never targets.
- At user level, an agent-neutral file under
~/.config/<plugin>/, with a pointer in each installed
agent's personal instructions file.
The user wants this as the single source of truth for every plugin, not only for the new
developer-experience plugin (#6302), which adopts it first.
Problem
Evidence, pointer-form test (2026-10-07, blind-scored, one throwaway .NET fixture, 3 runs per cell): with only one trigger-and-path line in AGENTS.md and the team conventions in docs/conventions/developer-experience.md, the agent read the conventions file and called the right plugin skill in 6 of 6 runs, without the prompt naming a skill. Scores: S1 10, 10, 9 of 12 and S3 10, 9, 10 of 10, against 11, 11, 10 and 10, 10, 10 when the prompt named the skills, and 9, 9, 9 and 4-6 when the plugin was installed with no pointer (its skills never fired: the model saw about 320 skills, about 30 with descriptions, and these as bare names).
- Plugin config is spread over three location rules and several shapes. Today a setup skill
may write.claude/<name>(ai-slop:plugins/ai-slop/skills/setup/SKILL.md:20-24), a fenced
yaml configblock indocs/conventions/<concern>.mdwith a.claudefallback (testing:
plugins/testing/skills/setup/SKILL.md:20-26; multi-agent:
plugins/multi-agent/skills/setup/SKILL.md:50-55), a.claude/<name>.mdplus a separate
neutral YAML file reached by aconvention_sourcepointer (source-control:
plugins/source-control/skills/setup/SKILL.md:54-58,130-136), or a.claude/standards.yaml
pointer file (review:plugins/review/skills/setup/SKILL.md:34-40, ratified in ADR 0042). Other
agents and tools do not read.claude/(ADR 0044 Context,docs/adr/0044-*.md:12-17). - The documented target has already moved past the docs. The owner comment on Migrate per-skill .claude config files to userConfig, one conventions doc, or the cascade (ADR 0018) #5906 records
that standardscomponents/github-actions-conventions/README.md:131-136(merged 2026-10-04) puts
structured configuration indocs/conventions/<concern>.yamlwith a JSON Schema and prose in
docs/conventions/<concern>.md, superseding ADR 0044. This repository's
docs/conventions/config-cascade/README.md:50-92and ADR 0044 still describe the fenced block,
and the promised ADR ("home plugin customization in docs/conventions/.yaml") is not in
docs/adr/(latest is 0057). - A skill hidden in a large listing does not fire unless an always-loaded line points to it.
In the developer-experience value test (2026-10-07, round 2), the plugin's skills fired in 0 of 12
runs when merely present: the model saw about 320 skills, about 30 with descriptions, and the
plugin's skills appeared as bare names. Told to use them, the same skills scored 10/10 on every
script-cleanup run against 4-6 without. Team conventions inAGENTS.mdproduced most of the
gain in round 1 (+16 of 44). The test's conclusion: setup should write anAGENTS.mdline
routing the work to the skills, "since AGENTS.md is always loaded and the listing is not". - Setup wrote targets as current facts. In the same test, two of three setup runs described
the target contract as current ("every command supports non-interactive flags"), which would
make an agent hang on commands that do not. - No setup skill can tell a team-chosen value from an inherited default. When a plugin
changes a recommended default, a re-run cannot know whether to update the stored value or leave
it, so todayapplycan only fill absent keys and report what it cannot reconcile
(docs/plugin-philosophy.md:617-625). - Cross-agent reach differs by level.
AGENTS.mdcovers repository and folder levels across
most agents, with nested files and nearest-wins precedence. No cross-agent user-level or local
file exists: each agent has its own (~/.claude/CLAUDE.md,~/.codex/AGENTS.md,
~/.copilot/copilot-instructions.md,~/.gemini/GEMINI.md, Cursor user rules). Merge order
across layers is unconfirmed for several agents, so a design should not depend on one layer
overriding another. (Basis: the instruction-layers research run of 2026-10-07; its claims are
single-source content claims about each publisher's own docs, runtime not probed.)
Proposal
Locations and formats
| What | Path | Format | Reader |
|---|---|---|---|
| Team conventions for a plugin's concern | docs/conventions/<plugin>.md by default; relocatable through the pointer line |
Markdown prose | the model, on demand through the pointer |
| Team settings scripts and hooks read | docs/conventions/<plugin>.yaml, fixed |
YAML, validated by a JSON Schema the plugin ships | scripts, hooks, and the model |
| Pointer | one short trigger line per plugin that needs one, inside one managed block in the root AGENTS.md |
Markdown | every agent that reads AGENTS.md |
| User-level conventions and settings | ~/.config/<plugin>/, same .md/.yaml split |
Markdown and YAML | the model through a pointer in each installed agent's personal instructions file; scripts at the fixed path |
- Script-read values go in the
.yaml, prose in the.md, never mixed. A plugin with no
script-read values has no.yaml; a plugin with no prose has no.md. - Only the prose
.mdis relocatable. The.yamlstays at its fixed default path, so no script or
hook resolves a pointer: the hook cost ADR 0044 decision 4 guards (testing's hook has a 150 ms
p95 budget) and the lookup ADR 0042 declined (docs/adr/0042-*.md:43-45,59) both stay at zero. - The same pointer pattern serves a folder (a nested
AGENTS.mdpointing to a folder-scoped
file) and the user level. No cross-agent user file exists (Problem 6), so the user-level file is
agent-neutral under~/.config/<plugin>/, and setup writes a pointer into the personal
instructions file of each agent installed on the machine, after confirmation. - Surfaces that config-cascade keeps as dedicated files stay where they are: per-operator-keyed
surfaces, policy-floor surfaces, and mutable state
(docs/conventions/config-cascade/README.md:209-212), and machine state in
${CLAUDE_PLUGIN_DATA}(docs/plugin-philosophy.md:383-391). Personal scalars stay in
userConfig. The gitignored overlay.claude/<stem>.local.<ext>is unchanged.
Pointer format
One managed block in the root AGENTS.md; one short trigger line per plugin that needs one:
<!-- BEGIN plugin-conventions (managed by plugin setup skills; each line edited through its plugin's setup) -->
- Developer tooling (scripts, CLIs, dev commands): read `docs/conventions/developer-experience.md`; use `/developer-experience:audit-tools` before changing scripts and `/developer-experience:build-cli` when adding a command.
<!-- END plugin-conventions -->- The line leads with the trigger and follows the pointer-writing rules in
/docs-hygiene:write-for-agents(front-load the matching word, say when to follow and what the
reader gets). Its final wording waits on the pointer-form test (Evidence above). - It names only skills the model can invoke.
setupcarriesdisable-model-invocation: true
(docs/conventions/invocation-mode/README.md:99-105), so a pointer cannot route the model to it;
drift checks the model should run go through the<plugin>:checksibling
(docs/plugin-philosophy.md:604-610). - A plugin gets a line only with stumble evidence: each line is a standing instruction under
Instruction economy (docs/plugin-philosophy.md:948-953). Problem 3 is the evidence for the
pattern; each plugin's line names its own. - Each setup writes only its own line inside the block, after showing it and getting a yes.
instruction-placement's rules-index block is the precedent for a managed region
(docs/conventions/config-cascade/README.md:217-224). - This repository's own
AGENTS.md"Conventions that load on demand" table is a working example
of trigger-and-path routing.
Setup actions
Setup keeps the closed verb set check and apply (docs/plugin-philosophy.md:617-633).
| Action | Writes | Does |
|---|---|---|
check |
never | Drift report: config at an old location (such as .claude/, detected through the plugin's retirements.yaml records), a missing or stale pointer line, a pointer to a missing file, options a plugin update added, recommended defaults that changed since the recorded version, values that state a target as a fact. |
apply |
yes, after showing each change | Converges by detected state. No conventions: init (infer current facts from the repository, interview for the rest, write the .md, .yaml and pointer line). Config at an old location: migrate (move it, rewrite the pointer, carry every value and its provenance; a value it cannot carry is reported, never dropped). Existing config: configure (confirm, change or add options, update inherited defaults). |
No argument runs check. apply runs check before and after. A second apply with no changed
inputs writes nothing. apply's conservative-reconcile rules (docs/plugin-philosophy.md:619-625)
still hold.
Model-invoked skills of an adopting plugin tell the user to run /<plugin>:setup when the
conventions they need are missing or stale, since the model cannot invoke setup itself.
Provenance and version recording
The .yaml records the plugin version it was written against and, per value, whether the team
chose it:
written_against: developer-experience@0.3.0
settings:
default_runner:
value: just
source: chosen # set or confirmed by the team
require_dry_run:
value: true
source: default # inherited from the plugin at written_against- When the installed plugin's default for a
defaultvalue differs from the recorded one,
applyupdates it and says so;checklists it. - When it differs for a
chosenvalue, the value is kept andcheckflags it with the old and new
defaults, so the team can decide. - Prose files carry the same
written_againstline (front matter) and mark team-chosen rules
versus plugin-recommended ones (granularity: Open question 1).
Current facts, not targets
Every stored statement describes the repository as it is when written. A goal the team has not
reached goes in a separate, labeled "Not yet" list or a work item, never in the convention text.
check flags universal claims ("every command supports X") it can test and finds false.
Migration rules
- A surface migrates in its owning plugin's own change, as ADR 0044 decision 7 already requires
per surface. - Leaving
.claude/<name>or~/.claude/<name>is declared with aretirements.yamlrecord
(docs/plugin-philosophy.md:635-641), socheckdetects the leftover in every consumer
repository andapplyoffers the gated move. No bespoke detection prose. - During the bounded window, the old file is read while present and every run says so, per the
one sanctioned dual-read (docs/plugin-philosophy.md:629-633; ADR 0018 decision 5). - When both old and new locations exist, the new one wins and the run warns, naming both paths
(the rule ADR 0044 decision 3 already uses).
What it supersedes or amends
| Existing rule | Change |
|---|---|
ADR 0044 decisions 1-2 (docs/adr/0044-*.md:25-41): team layer is a fenced yaml config block in docs/conventions/<concern>.md |
Superseded by one new ADR that replaces ADR 0044: settings live in docs/conventions/<plugin>.yaml, prose in docs/conventions/<plugin>.md. This is the ADR the owner comment on #5906 promised ("home plugin customization in docs/conventions/.yaml"); this issue carries it. |
ADR 0044 decision 4 (:45-48) and config-cascade/README.md:85-89: the pointer is a load hint, "no script reads it", scripts read the fixed path |
Kept: the .yaml stays at its fixed path; only the prose .md moves through the pointer, and only the model reads the pointer. |
ADR 0042 (docs/adr/0042-*.md:43-45,59): the pointer file is not a fleet rule; generalizing it "would add a lookup to every resolution ladder for no measured benefit" |
Kept: no script-facing lookup is added. The model-facing pointer rests on Problem 3's evidence. |
config-cascade/README.md:217-224: a single index/pointer line in the root file binds the convention home |
Amended: one managed block with one short trigger line per plugin that needs one. |
config-cascade/README.md:28-36,50-92: user-global layer at ~/.claude/<name>, team layer location axis |
Location axis rewritten to the .yaml/.md defaults; user-global layer moves to ~/.config/<plugin>/ with a pointer in each installed agent's personal file, ~/.claude/<name> retired through retirements.yaml. The gitignored overlay is unchanged. |
docs/plugin-philosophy.md:617-633: the setup verb set is "deliberately closed at check and apply" |
Kept. apply gains converge-by-detected-state (init, migrate, configure) and provenance-aware default updates. |
docs/plugin-philosophy.md:540-543: setup offers check and apply |
Amended to point at the new owner doc. |
plugins/testing/skills/setup/SKILL.md:15 ("never edits CLAUDE.md or AGENTS.md") and plugins/multi-agent/skills/setup/SKILL.md:107 |
Stand. They describe those plugins' setups. An adopting setup writes only its own line inside the managed block, with confirmation. |
docs/plugin-philosophy.md:948-953 (Instruction economy, evidence-gated additions) |
Applied: a plugin gets a pointer line only with its own stumble evidence. |
config-cascade/README.md:316-319 (Versioning) |
Changing what the team layer is triggers a contract_version bump: minor if .claude/<name> stays a supported fallback (as ADR 0044 judged), major if it is retired. |
docs/conventions/retired-conventions/ |
Reused unchanged for leaving .claude/ and ~/.claude/. |
docs/conventions/plugin-reconfiguration/ |
Unchanged; it owns native userConfig routes, which this convention does not touch. |
Open questions
- Is provenance recorded per value or per section?
- A. Per value in the
.yaml, per section in the.md. - B. Per value everywhere, with inline markers in prose.
- C. Per file only.
- Recommendation: A. Script-read values need exact default tracking; prose rules change as
sections, and per-sentence markers would make the file hard for people to edit. Basis:
judgment. Settles: the schema every plugin's.yamlcarries and the prose front-matter shape.
- A. Per value in the
Settled by the user on 2026-10-07 and stated above as the proposal: user-level location, script
path resolution, pointer count, the setup verb set, and the owner doc.
Rollout
- Owner doc first: write
docs/conventions/setup-lifecycle/README.md, add its convention
registry entry (docs/plugin-philosophy.md:808-813), and record one ADR that replaces ADR 0044
(the ADR Migrate per-skill .claude config files to userConfig, one conventions doc, or the cascade (ADR 0018) #5906 promised) and amends ADR 0018 decision 1. Amend config-cascade (location axis,
user-global layer, pointer count,contract_versionbump with its CHANGELOG) and
plugin-philosophy (applyconverges; setup section points at the owner doc) in the same change. developer-experience(feat(developer-experience): new plugin for a team's developer tooling (Brief confirmed) #6302) adopts first, since it has no existing surface to migrate.- Other plugins adopt in their own changes, each with its retirement record and, if it wants a
pointer line, its own stumble evidence. Migrate per-skill .claude config files to userConfig, one conventions doc, or the cascade (ADR 0018) #5906 carries the migration of the existing.claude/*
surfaces and fenced blocks once the owner doc lands. - A static conformance check (pointer line present, file at its path,
written_againstpresent)
joins the registry row's audit only after two or three plugins have adopted. - Notify the UX and UI lanes when the owner doc lands; docs: add a routing-as-data convention for plugins that route to installed tools #6483's routing data follows the same
location, format and provenance rules.
Related
- Migrate per-skill .claude config files to userConfig, one conventions doc, or the cascade (ADR 0018) #5906: migrate per-skill
.claudeconfig files; its owner comment moves the target to
docs/conventions/<concern>.yaml. This issue defines the convention that migration lands on. - feat(developer-experience): new plugin for a team's developer tooling (Brief confirmed) #6302: new
developer-experienceplugin, first adopter; source of the value-test evidence. - docs: add a routing-as-data convention for plugins that route to installed tools #6483: routing-as-data convention for plugins that route to installed tools; its data files
should use the same location, format and provenance rules. - ADR 0018, ADR 0042, ADR 0044;
docs/conventions/config-cascade/,
docs/conventions/retired-conventions/,docs/conventions/plugin-reconfiguration/.
Activity
github-actions commentedon Oct 7, 2026
Proposed work class: work-class: structural
Basis: automated intake triage; the lanes App applied this class.
Size: Large
Complexity: High
Uncertainty: Knowable
Flags: intent
Blocked by: none
#6594 (comment)
I understood this as a repo-wide setup-lifecycle convention (a
.md/.yamlsplit, a managed AGENTS.md pointer block, check/apply, provenance, current-facts-only). The decision settles the pointer-line question only. Two questions remain open:.yamland per section in the.md. Basis: the issue's own judgment that script-read values need exact default tracking, and per-sentence markers make prose hard to edit.~/.config/<plugin>/, but an earlier owner comment says~/docs/conventions/<plugin>.{yaml,md}. RECOMMENDED:~/.config/<plugin>/, because the body records it as settled on 2026-10-07 and it is agent-neutral. Basis: the issue body.No related duplicates found. The issue is already tracked as a split parent.
Automated triage, applied by the lanes App.
kyle-sexton commentedon Oct 9, 2026
The
developer-experienceplugin (#6302) is the first adopter of the managed block and merges first, so the owner doc can adopt what it ships instead of the other way round. This records the shipped contract and where it differs from the draft here.Shipped marker text (amend this issue's draft to the GENERATED form). From
plugins/developer-experience/skills/setup/scripts/pointer-line.sh:-bullet. A plugin's setup owns exactly one line, the one that starts with its own prefix, and never edits another byte. The path in the line is the only variable part.setupcarriesdisable-model-invocation: true.checkreports a block that opens with the draft<!-- BEGIN plugin-conventionsprefix asdraft-markerfor migration, andapplyrefuses to edit it (exit 3), so no consumer is rewritten silently.Why GENERATED (OD-1 B), with the counter-evidence.
lib/index-regen.sh:58also uses<!-- BEGIN GENERATED: ... -->, for a region regenerated whole, while this block is edited line by line, so "GENERATED" there means "rerendered". B stays because the existingconvention-homeregion is also a line-owned GENERATED region that setup skills write a single line into (docs/conventions/authoring-formats/README.md:144,plugins/architecture/skills/setup/SKILL.md:59-66), as is the rules index atAGENTS.md:77and:100. So the repository already reads GENERATED as "machine-owned", and the draft'sBEGIN plugin-conventions (managed by ...)form would add a second marker grammar.Provenance marker (OD-2) and conventions-file contract (a).
docs/conventions/developer-experience.mdby default, any repo-relative path the user picks; the pointer line carries it. User level:~/.config/developer-experience/developer-experience.md(OD-6, same name at both levels).written_against: developer-experience@<semver>, rewritten only byapplyand only when it writes something.## Not yethas<!-- developer-experience: source=chosen -->orsource=defaulton the line after its heading.defaultis updated byapplywhen the plugin default changes and the team has not edited the body (an editeddefaultbody is reported as a marker to flip, never overwritten); a changed default on achosensection is flagged bycheckand never applied.Tools,Shared helpers,CLI contract,Secrets,Platforms, then an optional## Not yetthat is the only place a target may appear. No sentence elsewhere states a target as current fact.apply.Convention-home reuse (OD-11). The repository already has a setup-written pointer to the consumer's convention home,
<!-- BEGIN GENERATED: convention-home -->, resolved bylib/resolve-convention-home.sh(scripts/cross-plugin-source-registry.txt:128). It holds exactly one line, so the trigger line cannot go there. DX vendors the resolver byte-identical and defaults the conventions file to<home>/developer-experience.mdwhen a home is bound, elsedocs/conventions/developer-experience.md. This issue does not mention that mechanism; the owner doc should unify the two pointer mechanisms.Departure from
docs/conventions/config-cascade/README.md:229-243(OD-3 A). Those rules make whichever ofAGENTS.mdandCLAUDE.mdcarries the marked region canonical, so a repository that keepsCLAUDE.mdcanonical is served identically. DX's setup writesAGENTS.mdonly and never editsCLAUDE.md. WhenCLAUDE.mdexists without an@AGENTS.mdimport,checkreports thatAGENTS.mdmay not load and prints the exact line to add, and the shim is routed to/instruction-placement:migrate. The owner doc decides whether the block may also live in a canonicalCLAUDE.md.The shipped behavior is in #6668; amend the draft marker and these rules in the owner doc to match, or record the retirement and migration if you choose another form.
kyle-sexton commentedon Oct 10, 2026
Input from the owner, recorded during the planning interview for a new CSS skill in
user-interface(/user-interface:write-cssplus/user-interface:setup).Settled
.local.md/.local.yaml, gitignored, the same pattern as Claude Code'ssettings.local.json)docs/conventionsis only the shipped default location. Every repo and project may store its config elsewhere, and plugins and skills must honor the resolved locations every time.Still open, for this issue to decide
Until this lands, the CSS skill follows the shape on main and in
user-experience: YAML for settings, Markdown for prose, one folder resolved through the convention-home pointer.🤖 Generated with Claude Code
kyle-sexton commentedon Oct 11, 2026
Further owner direction from the
user-interfaceCSS skill design session. This is the target default the repo should converge on; the CSS skill ships as its first adopter.Defaults
<plugin>.yamlfor pure config and one<plugin>.mdfor prose per plugin, no per-plugin subfolder unless a plugin genuinely needs one.AGENTS.mdorCLAUDE.md, whichever is used) points to the convention files with context clues.userConfigexposes the user-global keys under flattened names (css.browser_targetbecomescss_browser_target).Cascade (later wins per key, lists combine)
userConfig(user scope, not committed)~/docs/conventions/<plugin>.{yaml,md}, mirroring the repo layout, pointed to from the user-global instruction file (not committed)<home>/<plugin>.{yaml,md},<home>from the convention-home pointer, defaultdocs/conventions(committed)<home>/<plugin>.local.{yaml,md}(gitignored)Shared mechanism
lib/config-cascade.mjs, plus a canonicallib/yaml-subset.mjs), vendored per ADR 0019, so a later change to locations or format lands in one place.Migration requirement
work-itemswritingtracker.jsonat the repo root) move to this pattern.Repo-wide codification (the written standard, an ADR superseding ADR 0044, and migrating each existing plugin) is proposed as this issue's scope rather than the CSS work's.
🤖 Generated with Claude Code
refactor(user-experience): read team config through lib/config-cascad…
kyle-sexton commentedon Oct 24, 2026
Decision recorded. Owner, Backlog HITL session, 2026-10-24. Q98: "Should ADR 0075 be amended so a plugin's setup may add one trigger line to the always-loaded AGENTS.md, but only with evidence that plugin needs it?" Answer: "yes, go w/ recomended". Next: amend ADR 0075, then split the undelivered lifecycle remainder (owner doc + ADR amendment, provenance recording, converge-by-state apply, facts-not-targets check) into lane slices.
kyle-sexton commentedon Oct 26, 2026
This was generated by AI.
Releasing the hold. This issue is a split parent: its work lives in its sub-issues. The hold was kept until admission refused a parent with open sub-issues, and that guard is now on main:
.github/scripts/intake-triage/admit.mjs:438-441("A split issue's work is its sub-issues' (owner Q93)"), so admission waits while any sub-issue is open.refine.mjs:292also declines to split an issue that already has sub-issues.needs-humancomes off. Nothing is re-queued: the parent stays open as the tracker until its sub-issues close.This split was filed by hand, so it has no lanes App split record, and work-unblock's
closeSplitParentwill not close it on its own when the last sub-issue closes. That gap is reported to the coordinator.melodic-automation-lanes commentedon Oct 26, 2026
The triage verdict left this issue at
status: needs-decision:melodic-automation-lanes commentedon Oct 26, 2026
Refinement. A read-only run explored this repository, searched its issues and pull requests, and read the allowed docs to draft what follows. On an issue a listed human filed, it counts as the issue's spec once posted, while unedited; it is still model text, so check it.
Intended outcome: Close this issue as a tracker once its remaining slices (#9809, #9862, #9827) land, since the owner doc and ADR 0075 amendment already shipped in #9811.
Dependencies
Related work
Open questions
RECOMMENDED: Yes. Keep it open only until those sub-issues close, then close it by hand, since there is no lanes split record to close it automatically. Basis: judgment
RECOMMENDED: Yes, option A. The developer-experience adopter already ships per-section markers in prose and per-value source keys. Basis: 6668
RECOMMENDED: Follow what ADR 0075 and docs/conventions/setup-lifecycle/README.md now say, not the issue body. The body and the 2026-10-11 owner comment conflict, and the ADR is the later accepted record. Basis: docs/adr/0075-resolve-plugin-settings-through-one-four-layer-cascade-and-a-bound-convention-home.md:3
Sources read
Automated refinement by the lanes App. Answer with a comment whose first line is
**Decision recorded.**.kyle-sexton commentedon Oct 27, 2026
Decision recorded. The owner answered in the Refinement session (2026-10-25), deciding the open items below on the facts:
Owner ledger rows that govern this issue:
.work/backlog-to-zero/interview-checklist.md:140), also recorded on the issue (feat(conventions): one setup lifecycle for where plugins store team conventions and settings #6594 (comment)):.work/poteto-review/interview-checklist.md:594), accepted "all 15" conventions-vetting fixes, including:.work/issue-triage-owner-sweep-1/interview-checklist.md:63) is deferred ("outside the pipeline focus; issue not touched") and decides nothing.Delivered: #9811 amended ADR 0075 and added
docs/conventions/setup-lifecycle/README.md(sub-issue #9801, closed). Open: #9809, #9827, #9862.The refinement's questions (#6594 (comment)):
Decided: it stays open as the tracker and closes when feat(lib): record written_against and per-key provenance in the shared setup writer #9809, feat(lib): add a current-facts-not-targets check for conventions files #9827 and feat(lib): let the shared setup writer converge by detected state (init, migrate, configure) #9862 close. The split was filed by hand, so no split record closes it on its own (2026-10-26 comment); a tracker whose sub-issues are all closed is closed by the lane (BRIEF rule).
Decided: option A: per key in the
.yaml, per section in the.md. The first adopter already ships per-section markers in prose (plugins/developer-experience/skills/setup/reference/conventions-file.md:37), and feat(lib): record written_against and per-key provenance in the shared setup writer #9809 records per-key provenance.~/.config/<plugin>/or~/docs/conventions/<plugin>.{yaml,md}?Decided: neither. Q549 retired the user-global file layer into
userConfig. ADR 0075 records it: "There is no user-global file layer" (docs/adr/0075-resolve-plugin-settings-through-one-four-layer-cascade-and-a-bound-convention-home.md:50, fix 9 at:128-129), and the owner doc says the same (docs/conventions/setup-lifecycle/README.md:21-22). ADR 0075 is dated 2026-10-18 (:4), newer than the 2026-10-07 body and the 2026-10-11 comment, so Q549 governs both. The owner doc already states this, so no criterion is needed for it.Acceptance criteria:
docs/conventions/setup-lifecycle/README.md(:71,:75,:79) are filled by feat(lib): record written_against and per-key provenance in the shared setup writer #9809, feat(lib): let the shared setup writer converge by detected state (init, migrate, configure) #9862 and feat(lib): add a current-facts-not-targets check for conventions files #9827, and the provenance section states per-key provenance in the.yamland per-section provenance in the.md.