Conversation
Proposes the org repository namespace as a decided standard: naming
grammar (dash prefix = type, dot suffix = variant), a normative type
registry, an ecosystem-name exemption for published packages and forks,
a teaching-events convention (workshop-/course-/conference-{name}-{yyyy})
for the largest unnamed family (~55 repos), and a migration + archival
policy (new repos comply; opportunistic renames; concluded events
archived). Records the taxonomy developed in the team manual and the
boundary rules for project-*/status-*/workspace-*.
Related proposals: QuantEcon/meta#333 and QuantEcon/meta#334 proceed as
first instances of the rename policy.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This pull request introduces QEP-3, a new draft QuantEcon Enhancement Proposal that standardizes repository naming grammar, defines a type-prefix registry, and documents exemptions plus a migration/archival policy; it also registers the new QEP in the repository’s README index.
Changes:
- Add draft QEP document: Repository Naming and Types (QEP-3).
- Update the README index to include QEP-3 with
Type: standard,Status: Draft,Version: –.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| README.md | Adds QEP-3 to the QEP index table. |
| qeps/qep-0003-repository-naming-and-types.md | New draft QEP defining repo naming grammar, type registry, exemptions, and rollout policy. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Two amendments earned by applying the draft to a live placement decision
(where the translation program's command bench should live):
- The project-{name} registry row said flatly "no production code",
contradicting the boundary rule below that allows a minimal command
bench; a reader consulting only the table gets the wrong answer. The
row now points at the boundary rules.
- The bench boundary rule now names the graduation triggers (shared
across initiatives, or grown beyond minimal to serve routine fleet
operations) and records that for a long-running program the
bench-in-project arrangement can be durable, not merely transitional
- locality of decisions, bench and clones under one root is a
feature, not a smell.
Context: QuantEcon/project-translation applied the rule 2026-07-14 and
kept its bench in-project after weighing a workspace-translations split.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Field report from applying the draft. The translation program used QEP-3 this week to settle a live placement question — where its cross-repo command bench should live (QuantEcon/project-translation, decision register 2026-07-14). The goal-vs-fleet boundary rule decided it cleanly, and the exercise surfaced two text gaps now amended in 8150620: the For the record — two pre-existing editions don't parse under the §1 grammar. Not an objection to the draft: §5's migration policy (no bulk renames; opportunistic renames riding on active maintenance) is exactly how these resolve once the QEP is accepted. Documenting them here so they're known instances when the meta#333/meta#334 rename batch picks them up:
One sequencing note for whoever handles them: both editions are the Phase 0 sync-automation targets (action-translation#74). A rename is nearly free before that wiring lands and fiddly after (Pages URLs under github.io don't redirect; |
Field test: a live placement decision run against this draft (+ a proposal to restructure the automation types)I ran a real placement decision against the draft as a test case — the kind of question the Motivation section says should stop being re-litigated. Two findings: the standard resolved the placement decision cleanly (validation, no text change needed), and pulling on one loose thread ( The test caseThe reporting/measurement program (QuantEcon/meta#332 — the status/analytics/activity planes, plus the benchmarking programme QuantEcon/meta#335 on the build side) needs a family-level coordination home: the plane taxonomy, the shared reference architecture, the cross-plane result/environment schema, and cross-plane research notes. Two research PRs recently landed in Finding 1 — the boundary rules decided it without interpretationThe goal-vs-fleet rule in §2 answers directly: the reporting family is heterogeneous ( Two smaller items from the same test are repo-README material rather than QEP material, noted for completeness: (a) the Finding 2 — the automation types need restructuring:
|
| Contents | Registered type it matches |
|---|---|
action.yml (reusable Action) |
action-* |
six scheduled workflows (weekly-report, monthly-report, news-weekly, news-watch, …) |
workflow-* (scheduled automation that acts) |
reports/ directory of generated outputs |
closest to status-*'s data role, though narrative documents rather than a latest.json contract |
The obvious fix was to rename it into workflow-* — but examining the incumbent shows it has the same disease. workflow-* has exactly one member (workflow-backups), and it names the mechanism rather than the role: every repository in the org has .github/workflows/, so "contains workflows" distinguishes nothing, and it pollutes org search. (Anecdotal but telling: in one working session both names were misremembered — report-activity for reports-activity, workflow-backup for workflow-backups. Prefixes that carry no role signal are hard to recall even for their creator.)
Proposal: replace workflow-* with a two-family automation taxonomy, named for the actor and its effect.
reporter-*— observes and narrates. Read-only automation that reads org/web state and writes reports, digests, or dashboard-adjacent narrative. Members and pipeline:reporter-activity(rename ofreports-activity), a futurereporter-news(the news-watch function), and the weekly read-only routines piloted in Org maintenance automation: weekly Claude Code routines (read-only reporting first) meta#331.task-*— executes. Automation with write access to org resources, executing recurring org chores (the registry wording matters: "executes recurring org chores with write access" — atask-*repo is the machinery that does a chore, not a task tracker; work tracking stays in GitHub Projects per this QEP's architecture). Members and pipeline:task-backups(rename ofworkflow-backups, writes to S3), the annual event-archival sweep from Rollout §3 (archives repos).
Design rationale, in registry terms:
- Name the actor and its effect, not the mechanism or the trigger. Mechanism (
workflow-) and trigger (scheduled-,cron-) are implementation details visible inside.github/workflows/; trigger-naming also fails structurally, since both families are typically scheduled and either may be event-driven. Effect — observes vs acts — is the durable, governance-relevant property. - The split is the read/write permission boundary.
reporter-*repos need read scopes plus issue/PR comment;task-*repos need write access to org resources. The org's automation estate becomes triage-able for security review directly from the repo list — the same property that made the meta#331 pilots deliberately read-only. - A closed two-way split, not open-ended agent nouns. This parallels the QEP's own
workshop-/course-/conference-overevent-decision: more reader signal at no grammar cost, without opening the door to a per-role noun zoo (archiver-,syncer-, …) of single-member families. - Domain vocabulary is off-limits for type prefixes — the mirror image of §3's ecosystem-name exemption: just as registry names are load-bearing outside the org, mathematical/economic vocabulary is load-bearing inside it. This filter removed the otherwise-attractive agent nouns:
operator-(Bellman/transition/linear operators saturate the lectures),agent-(economic agents; plus the AI-agent overload),actor-(actor-critic methods).task-passes precisely because it carries no domain meaning. - Verbs framing extends cleanly:
project-*decides /workspace-*operates /status-*measures /reporter-*narrates /task-*executes.
Other names considered and rejected on the way, recorded QEP-style so the choices read as decided: routine- (implies cadence; excludes event-driven members), automation-/automate- (verb form is off-pattern; noun form is long and sits confusably next to action-*), bot- (connotes an interactive actor), scheduled-/cron- (name the trigger both families share), job- (echoes Actions' own "jobs"), and registering reports-* as-is (legitimizes a single-member family).
Concretely, if agreed: in §2, remove the workflow-* row and add the reporter-* and task-* rows with the read/write boundary stated; in Rollout, add reports-activity → reporter-activity and workflow-backups → task-backups as rename candidates under the §5 opportunistic policy (both repos are actively maintained, so the rename-rides-on-maintenance condition is satisfied), parallel to the existing continuous_time_mcs call-out; in Alternatives, note that reports- and workflow- are deliberately absent from the registry.
QEP-2 merged in #2 while its status still read **Draft**, so `main` currently holds an in-effect standard that its own record describes as a draft. This PR completes step 5 of QEP-1's decision process, which was skipped at merge time. The flip is applied in the three places [AGENTS.md](https://github.com/QuantEcon/qeps/blob/main/AGENTS.md) keeps in sync: the YAML frontmatter, the in-document header table, and the README index row. CI parity passed before this PR only because all three agreed on the wrong value. **No version bump.** A newly accepted QEP carries no `version` — implicitly v0 until first substantively amended — so the README `Version` column stays at the em dash. QEP-4 will be the thing that moves QEP-2 to v1, when its acceptance PR re-applies the registry hooks it parked per the convention in #9. The decision itself is not reopened here: @jstac approved the label set and the labelling policy on #2, and @mmcky confirmed the merge. Only the bookkeeping is outstanding. ## Changes | Location | Was | Now | |---|---|---| | `qeps/qep-0002-standard-github-labels.md` frontmatter | `status: Draft` | `status: Accepted` | | `qeps/qep-0002-standard-github-labels.md` header table | Draft | Accepted | | `README.md` index row | Draft | Accepted | Nothing else changes — no normative content is touched, so this is an editorial commit under AGENTS.md's substantive/editorial split. ## Downstream Merging this changes the README row QEP-3 (#7) and QEP-4 (#8) must carry. Both branches are already stale against `main` (they predate QEP-1 v2 and QEP-2's merge, and neither has the QEP-2 row at all), so each will be brought up to date in its own revision round. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…P-2 landed Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Update (2026-08-14). Housekeeping while this PR is under revision:
|
…a example Addresses two Copilot review comments on #7. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
Suggestion from the translation program — a registry entry for published software tools. Today's naming grammar covers lecture content, programs and operations, events, and the support types, but not the family QuantEcon has always had: software packages whose identity is their ecosystem name — We hit exactly this on 2026-08-21 naming the git-metrics tool that came out of project-translation#49: a general Python package, published to PyPI, consumed by Proposed addition to §1 (grammar) and the registry, one row and one rule:
Rule: published packages take their ecosystem name unprefixed; Worked example for the anatomy page: |
Field test: a rename proposal the registry can't express — the
|
| What the proposal asserts | What the registry row says |
|---|---|
| topic + scope, no date | audit-{yyyy-mm}-{topic} |
| durable home, re-run each period in place | frozen once published |
| the cross-period series is the deliverable | a point-in-time audit is the deliverable |
The justification given is the graduation rule restated: the same checks re-run on a cadence, writing versioned data, rendered as a Pages site. That is the status-{domain} anatomy in §2 — collector + versioned data + Pages site — not "dated point-in-time audit, frozen once published". The repo is a hybrid, in the same way reports-activity was in the automation-types finding above:
| Contents | Registered type it matches |
|---|---|
lectures/data/*history*.csv and the charts page, regenerated each pass |
status-{domain} |
| per-pass prose findings, and the four contributed issue bodies | audit-{yyyy-mm}-{topic} |
UPDATE.md — the documented procedure for re-running a pass |
the collector half of status-* |
Two readings are available, and the QEP should pick one rather than leave the next audit to argue it out in its own repo:
- It is a
status-*repo that began life as an audit. The numbers are collected on a cadence, so they graduate; the repo is renamed for the domain it measures, alongsidestatus-lecturesandstatus-translations; the narrative half stays withproject-style-guide, which is already this program's home of record. - It is an
audit-repo and the series is a by-product. Then the date stays —audit-2026-05-style-guide— a new dated repo is minted per pass, and cross-period history is the status plane's job, not the audit's.
I lean to the first. The boundary rule's own test is whether collection is automated on a cadence, and UPDATE.md plus two pinned corpus snapshots means it already is; and the second reading requires copying lectures/data/ forward by hand every pass, which is the manual step the rule exists to prevent.
Concretely, if agreed:
- In §2, widen the "numbers graduate" boundary rule beyond
project-*incubation. It currently opens "A dashboard may incubate as hand-maintained tables inside a project repo", which reads as project-specific and is why this case fell through — the trigger should be any repo accumulating cadence-collected numbers, whatever prefix it started under. - Add one clause to the
audit-row's lifecycle: frozen once published — an audit whose checks are re-run on a cadence, and whose cross-period series is the deliverable, graduates tostatus-{domain}.
On scope: this is not a case for declining audit- registration the way reports- was declined. Single-member supporting families are normal in that table (template- has one member, the benchmark. family one), and the prefix carries real role signal. The finding is about the lifecycle field, not the prefix.
One process note, and some mechanics worth keeping
The rename was about to be decided in the audit repo itself; the QEP is not cited anywhere in the issue, and its "Still open" section defers instead to project-style-guide as the home of record for naming. That repo is the right authority for the program's cadence, but the namespace is this QEP's — a second data point for #14, and an argument that acceptance should include a pointer from the operational homes back to the registry.
Independent of which name wins, the migration mechanics in that issue are accurate and worth not re-deriving: GitHub redirects repository URLs after a rename but github.io Pages URLs are not redirected (16 references in-repo would 404), and the four contributed issue bodies mirrored under contributions/issues/ carry Pages links, so editing them locally is only half the job — the live QuantEcon/action-style-guide issues need re-syncing too.
Field test, part 2: the
|
| Prefix | Meaning | Visibility | Lifecycle |
|---|---|---|---|
compliance-{domain} |
standing record of a domain's conformance with a named standard: rubric + runbook (typically a skill), findings and scores re-measured in place per pass; versioned history seeded from each absorbed audit | public (typically) | standard-scoped — durable while the standard is enforced |
(b) §2 boundary rules — add two.
status-*reports what machines observe;compliance-*records what a rubric adjudicates. Shared anatomy (collector + versioned data + Pages site) does not decide the type; the epistemic mode does. Containment is asymmetric: a compliance ledger may embed machine-collected facts as evidence, but adjudicated numbers never appear on a status dashboard. Litmus tests: a script with no prompt could produce the number →status-; publication requires reviewing findings →compliance-; the repo recommends anything →compliance-(status has no opinions). Both may exist for one domain: the ledger keeps its mechanical evidence inside until that plane has consumers of its own — at which point the evidence (never the judgment) graduates tostatus-{domain}.- The audit is the event; the compliance repo is the ledger. A one-off examination publishes as
audit-{yyyy-mm}-{topic}and freezes. When examinations acquire a cadence, an owner, and a runbook, the standing record is acompliance-*repo assembled from one or more audits; absorbed audit repos are archived — content and Pages stay public and citable — and never renamed. Routine passes post to the ledger directly; dated audit repos remain available as citable freezes of a specific pass.
(c) §2 Supporting — the audit- row's lifecycle becomes: frozen once published; archived once absorbed into a compliance-* ledger.
(d) §5 — the invariant underneath all of this: renames fix names; they never transmute types. A repo that outgrows its type is succeeded by a new repo of the right type and archived — the same shape as "concluded events are archived, not renamed", stated generally.
(e) §1 — grammar note (the reversal test). Choose name tokens so the name reads as natural English when expanded: attributive singulars inside compounds (compliance-lecture-style → "lecture-style compliance", like house style, user guide), standalone plurals for whole-domain tokens (status-translations). This settles singular/plural choices mechanically.
This supersedes the two amendments floated in the field-test comment above (the widened incubation trigger and the audit-row graduation clause): under (b)'s second rule the audit row needs no graduation language at all, and the existing graduation rule gets its correct scope from (b)'s first — evidence graduates, judgment doesn't.
Applied to the test case
audit.2026-05.style-guide keeps its grandfathered dotted name for life. QuantEcon/compliance-lecture-style is assembled from main plus the in-flight branch — which, tellingly, already has the ledger's anatomy: lectures/data/history.csv seeded with the 2026-05 rows, rule_reach_history.csv carrying the 2026-08 pass, snapshot.json pinning the corpus, a deterministic tools/qestyle_*.py checker suite (the embedded evidence layer, and the eventual status- graduation candidate), and per-lecture reviews (the adjudication layer). The audit repo then archives with its Pages site and all posted issue links intact — zero breakage, versus 17 dead Pages links (10 inside live action-style-guide issue bodies) under any rename. The repo's own ROADMAP §2.3 had leaned exactly this way in May ("Option β … cleaner conceptually; the disposable repo really is a snapshot"); the registry now has the type it was missing. Decision recorded in QuantEcon/audit.2026-05.style-guide#2; execution tracked in QuantEcon/audit.2026-05.style-guide#7.
Two tidy consequences for earlier findings: reports- stays on its way out (nothing here revives it — the ledger is an assessment plane, not a "reports" family), and the hypothesized sibling lands cleanly as compliance-lecture-accessibility.
Generated by Claude Code
Folds the amendments queued on the discussion PR into one coherent text:
- Replace workflow-* with the effect-named reporter-*/task-* pair; the
boundary is read vs write access, not trigger or mechanism
- Add compliance-{domain} (assesses): the standing conformance ledger,
with the status/compliance epistemic boundary rule and the
audit-is-the-event rule; audit-* lifecycle gains the absorption clause
- Remove workspace-* (zero members; both field-tested placements
resolved into project-*); the bench allowance folds into the
project-* boundary rule, re-registrable by amendment (Rollout 6)
- 3: published packages take their ecosystem name unprefixed, stated as
a forward rule; register tool-* for internal unpublished tooling
- 5: renames fix names, never transmute types (succession + archive);
rename proposals are adjudicated against the published record
- 1: add the reversal test for name tokens; fix the machine-parse claim
in Alternatives (candidate type, validated against the registry)
- Rollout: automation renames, the compliance-lecture-style succession,
non-parsing translated editions ride the meta#333/334 batch, event
sweep noted as a task-* candidate; tool-* leaves the future-families
list; verbs line updated (decides/measures/narrates/executes/assesses)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LrLuqmKVPh2zDyz8JSyyPD
|
Amended draft landed (5922608). Everything queued in this thread is now in the text, reconciled into one registry: the Also fixed while in there: the machine-parse claim in Alternatives (split on first dash gives a candidate type, validated against the registry — The PR body is updated to describe the amended draft, with the four deltas listed as the points where input is most useful. The four Copilot threads (all addressed in 67ea43a or overtaken when QEP-2 merged) are resolved. Remaining before decision: @mmcky to announce the fresh comment window and deadline. Generated by Claude Code |
|
|
Field note — We nominated Worked without special pleading. The One wording observation. The lifecycle column reads "archive when the pilot ends". This instance has no pilot: it is a standing CI target that should live exactly as long as the tool it tests. The row may want "archive when the tooling it targets is retired", or an explicit acknowledgement that Not one of the four points flagged as most wanting input, so treat it accordingly — raising it only because it surfaced from an actual naming decision rather than a reading. Generated by Claude Code |
The consolidated revision removed the workspace-* type on the grounds that the family had zero members. It has one: QuantEcon/workspace-lectures, private and standing since January 2025 (named `lectures` until July 2026), carrying the manifest, runner and clone root for the lecture family and serving several concurrent initiatives at once. That is the same condition the project-* boundary rule names as the evidence for registering a fleet-bench type, so the removal was self-undermining; and folding the incumbent into project-* would have run into §5, which forbids renaming a repo into a different type and would have demanded that a live bench be succeeded and archived instead. Restores the registry row, the goal-vs-fleet boundary rule and the workspace-ready test, and rewrites the Alternatives entry to record the removal proposal and why it was reversed. The prefix name itself is left open for a future amendment: workspace- names the place rather than the actor's effect, unlike the other five operational types. Discussion in #7. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
That is the same condition the retained What changed in the text
Left open deliberately. The prefix name. A second member is proposed: QuantEcon/meta#381 — The team manual's repository-conventions page already documents Generated by Claude Code |
…ered The restored Alternatives entry left the prefix name open. It is now decided: workspace- stays, and the asymmetry with the effect-named machine types is recorded as deliberate — machines have no location, a fleet bench is the one operational repo humans work in. Adds the rejected-names record the entry was missing, in the same shape as the reporter-/task- entry: maintenance-, ops-, fleet-, bench-, estate-, the agent nouns, the verb forms and the place synonyms, each with its objection. The workshop-/workspace- proximity is recorded as a knowingly accepted cost. Discussion in #7. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two loose ends found reviewing the draft ahead of the comment window. The test-* row read "archive when the pilot ends", which does not describe test-cli — a standing CI target that should live as long as the tool it tests. The row now spans both pilot-scoped doubles and standing targets, as the 2026-08-27 field note on the discussion thread proposed. Rollout item 3 said the event archival sweep was "proposed and tracked in meta" without a reference, and no such issue exists. It now points at the open inventory in QuantEcon/meta#267 and states the difference this QEP makes to it: that issue archives on two years of inactivity, while the QEP makes the event's conclusion the trigger. Discussion in #7. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Draft complete for review — three commits since the consolidated revision, closing everything queued in this thread.
fa0e6b7 — cbc82f0 — the two loose ends. The Consistency pass over the current text: six operational types stated and six rows present, 19 prefixes each defined exactly once, no surviving reference to the removed type or to a Rollout §6 fleet-bench amendment. The PR body is in sync. Sequencing note for anyone reading the Remaining before the decision: @mmcky's read-through, then the comment window and deadline. Generated by Claude Code |
Simplify the Summary and Motivation, compress the boundary rules and Alternatives entries to their core distinctions, drop drafting-history narration, and convert Rollout into an Adoption section of obligations. The detailed execution items now live on their trackers: QuantEcon/meta#382 (continuous_time_mcs rename), QuantEcon/meta#383 (automation renames), and a scope note on QuantEcon/meta#267 (event-concluded archival trigger). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
76fe865 is a document-wide tightening pass to match the QEP-1/QEP-2 house style: simpler Summary and single-paragraph Motivation, boundary rules and Alternatives compressed to their core distinctions, drafting-history narration removed, and Rollout converted to an Adoption section of obligations (per the QEP-2 convention). The execution detail that came out now lives on trackers: QuantEcon/meta#382 (continuous_time_mcs rename), QuantEcon/meta#383 (automation renames), and a scope note on QuantEcon/meta#267 (event-concluded archival trigger). No normative rule changed — final read-through to follow before this moves out of Draft. |
|
@mmcky to review
|
Makes the org's repository namespace a decided standard — exactly parallel to QEP-2 for the label namespace. Prompted by a live placement question (where should the translation-progress dashboard live?) and a survey of the full org: of ~245 non-archived repositories only ~40% follow a documented convention, and the largest family (teaching events, ~55 repos) has no convention at all.
Full text:
qep-0003-repository-naming-and-types.mdWhat it decides
status-translations); a dot suffix encodes a variant of the same content (.notebooks,.zh-cn,.public). Dots are reserved for variants; new members of the dotted legacy families (audit.,benchmark.,project.) use dash forms. Name tokens pass the reversal test (compliance-lecture-style→ "lecture-style compliance").lecture-,book-,quantecon-book-); six operational types, five of them named for the actor's effect:project-*decides ·workspace-*operates ·status-*measures ·reporter-*narrates ·task-*executes ·compliance-*assesses, with boundary rules (numbers vs narrative; read vs write automation; observed facts vs adjudicated findings; the audit is the event, the compliance repo is the ledger); supporting types (test-,template-,tool-,contractor-,audit-,benchmark-).workshop-{name}-{yyyy},course-{name}-{yyyy},conference-{name}-{yyyy}; frozen and archived after the event.QuantEcon.py,GameTheory.jl,textstrata); forks keep the upstream name (mystmd); deployed sites are named by domain (atlas.quantecon.org).tool-*covers internal, unpublished tooling.reports-activity→reporter-activity;workflow-backups→task-backups;compliance-lecture-stylesucceedsaudit.2026-05.style-guide; an annual event-archival sweep (itself atask-*candidate).Review status
The draft was field-tested against live placement and rename decisions during the first comment window; the findings are folded into the amended text (5922608, landing note). Input is most useful on the four points that changed:
reporter-*/task-*(read vs write) replacingworkflow-*workspace-*retained — removal was landed in 5922608 on the ground that the family had zero members, then reversed in f4dcbfc whenworkspace-lecturesturned out to be one; the goal-vs-fleet boundary rule is back, and the prefix name is settled in fa0e6b7 (kept, with the names considered recorded and the place-vs-effect asymmetry stated as deliberate)compliance-{domain}as a fifth operational type, distinct fromstatus-*tool-*rowUnchallenged in the first window and unchanged since: the event three-way split, dash normalization of the dotted families, the reserved-names list (§4), and the archival sweep.
Comment window / decision deadline: to be announced.
The team manual's repository-conventions page remains the operational how-to — anatomies, worked examples, decision guide — and will cite QEP-3 as the naming authority on acceptance.
🤖 Generated with Claude Code