QEP-1 v1: version-defined living standards (amend in place, not supersede)#5
Merged
Conversation
Amend QEP-1 so a QEP gains a `version` the first time it is substantively changed after acceptance, rather than being superseded wholesale for every small change. Living standards (the label policy, a style guide, this process itself) are now amended in place under the same lazy-consensus review. - QEP-1: add the `version` field (implicit v0, git-hash anchor stamped at merge), the substantive-vs-editorial granularity rule, amend-in-place vs supersede, squash-merge-only, the `QEP-N vM:` / `QEP-N:` commit-subject convention, the `standard`/`process`/`informational` content taxonomy for `type`, and git (surfaced on the site) as the change record. QEP-1's own first substantive amendment, so it becomes v1. - template.md: lowercase `type` enum; note that `version` appears on first amendment. - README: add `Type` and `Version` columns; QEP-1 -> process / v1. - AGENTS.md: author-side guidance (substantive vs editorial, version bump, commit subjects, squash-merge) and what CI does. - CI: post-merge `stamp-version.yml` stamps the merged hash into `version: N # <hash>` and syncs the README columns; `qep-checks.yml` enforces version-increment and README<->frontmatter parity. Logic in `.github/scripts/`. Implements the design agreed in #4. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
I fully agree with this. Many thanks @mmcky , very good call. My only complaint is that the "What this does" section reads as Claude mumbo-jumbo that a really clear sequence of rules / steps. Maybe Claude could have another go with the aim of improving clarity --- make it like an algorithm / proof, not a word salad. |
Contributor
Author
|
Thanks @jstac -- sorry this was supposed to be in DRAFT still (not ready for review). But I will tidy up the language, check the new automation code and then will merge based on the principle we want to capture. |
Move the git anchor from the `version: N # <hash>` comment to a sibling `version-hash` frontmatter key. A YAML comment is non-semantic and silently dropped by any parser; a real key is preserved as data and parseQep now throws on a malformed value. `version` stays a plain scalar, so the version pill and the increment check read it untouched. Scope all version parsing/stamping to the frontmatter block: a QEP body may now contain a literal version:/version-hash: YAML example (QEP-1 does), which the old whole-file regex in stamp.mjs/check.mjs would have matched by mistake. Update QEP-1 text, the template, AGENTS.md, and the README to match. Stays at v1 (no bump) since v1 is not yet merged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
QEP-1's own principle is that the change record is git, not in-document. Make the prose practise that: it should read as the current process, with the v0->v1 story left to git history. No normative content changes. - Fold the status/version orthogonality and the Superseded clarification into the Lifecycle paragraph, dropping the redundant standalone paragraph (the Amending section already owns amend-in-place vs supersede). - De-tense the Summary (drop "now at v1 ... introduces"). - Compress the version-hash rationale, dropping the framing relative to the rejected YAML-comment design. - Remove the "(added at v1)" annotations from Alternatives considered. - Fix a stale "git-hash anchor" -> "version-hash" in Rollout. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…gent Address the PR review's must-fixes and cheap hardening. - stamp.mjs (#1): detect a merge commit and diff against the first parent (`git diff --name-only HEAD^1 HEAD`) instead of `git diff-tree -r HEAD`, which prints nothing for a merge and would make stamping silently no-op if a QEP PR is merged as a merge commit rather than squashed. Verified on synthetic merge and squash commits. - check.mjs (#2, #5): a new QEP must start unversioned (v0); a versioned QEP may not drop its version field (once versioned, stays versioned). Distinguishes a brand-new file from a v0 file via a base-existence check. - check.mjs (#3): validate that type/status are known enum values. - check.mjs (#8): tolerate a hand-typed ASCII "-" or empty README Version cell for a v0 QEP (stamp.mjs normalises it to the en dash post-merge), so the cell no longer blocks the PR with a visually identical-looking parity error. - stamp-version.yml (#6b): push explicitly with `git push origin HEAD:main`. - QEP-1 + AGENTS.md (#7): the site uses book-theme today, so make the type/version pills and git-history-dropdown claims contingent on the QuantEcon theme; lead with the always-true README columns. Describe the strengthened PR checks. All eight check.mjs scenarios pass in an isolated synthetic repo; check.mjs passes on the real tree. Stays at v1 (no normative rule changed). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
These are local review notes, not part of the QEP record; gitignore the pr-*-review.md pattern so they can't be re-added. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
Author
|
Addressed the review in 791af8c (and untracked the stray pr-5-review.md working notes):
All eight |
check.mjs guarded the presence of the Type and Version columns but not Status, so a removed/renamed Status header would make the status-parity check silently no-op (expect() early-returns when the column index is -1). Add the matching presence check (Copilot review comment). Verified with a scenario test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
mmcky
added a commit
that referenced
this pull request
Jun 26, 2026
## Problem The **Deploy QEP site** workflow has failed on every push to `main` since the QEP-1 v1 merge (#5) — including the merge commit's own deploy, so the amended QEP-1 (the new `Type`/`Version` columns and pills) **never reached the live site**. The last successful deploy was #1 on 2026-06-16. The failure is unrelated to #5. `myst build --html` serves all pages fine, then fails resolving the favicon. With no favicon configured, MyST falls back to fetching the default from `https://mystmd.org/favicon.ico`. On the runner's Node 24.17.0 that remote fetch dies with `ERR_STREAM_PREMATURE_CLOSE` (a recent `http.Agent` keep-alive change), retries 3× and aborts the build: ``` Failed to fetch http://localhost:3000/favicon.ico after 3 attempts. ##[error]Process completed with exit code 1. ``` ## Fix Vendor QuantEcon's favicon into the repo and reference it locally, so the static build never reaches the network for it: ```yaml site: options: favicon: favicon.png ``` ## Verification Built locally on Node 26 with the change: | Check | Result | |---|---| | `myst build --html` exit code | `0` | | Build errors | none | | Emitted `_build/html/favicon.ico` | byte-identical to the vendored source | | `mystmd.org/favicon` references in output | none | | HTML `<head>` | `<link rel="icon" href="/favicon.ico"/>` | Once merged, the push to `main` re-triggers the deploy, which should now go green and publish the amended QEP-1. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the design discussed and agreed with @jstac in #4.
What this does
Today QEP-1 freezes a QEP the moment it is
Accepted— the only way to change it is to supersede the whole document with a new one. That suits a one-shot decision, but not a living standard (the label policy, a future style guide, this process itself) that evolves in small, frequent steps.This PR lets an accepted QEP be amended in place under the same lazy-consensus review. The first substantive change after acceptance gives the QEP a
version— v1, then v2, and so on — and routine evolution bumps that number instead of spawning a superseding document. A reader always sees one current standard rather than a chain of replacements.What deliberately stays the same:
statusstill answers only was this agreed? No new status word is added — living-ness rides onversioninstead. This sidesteps PEP'sActiveand the MEP clash whereActivemeans the opposite (frozen for voting).Supersededis kept, but only for a genuine wholesale rethink — never routine maintenance.Two supporting changes come along for the ride:
typebecomes a minimal content taxonomy:standard/process/informational.Adopting this is QEP-1's own first substantive amendment, so QEP-1 becomes
v1: the document is a worked example of the mechanism it introduces.How a revision is anchored
Each QEP's
versionis paired with aversion-hashkey in the frontmatter that pins the revision to an exact commit:version-hashis a real key, not a YAML comment, so a standard parser keeps it (a comment would be silently dropped). CI stamps it at merge — a commit cannot contain its own hash — so authors never write it by hand. Tooling that pins a standard readsversionand verifies againstversion-hash.Substantive vs editorial
This is an author/reviewer call — CI does not classify it — and it decides whether the number moves:
version; commitQEP-N vM: ….versionunchanged; commitQEP-N: ….Changes
qeps/qep-0001-purpose-and-process.mdversionfield (implicit v0) and itsversion-hashanchor, the substantive/editorial rule, amend-in-place vs supersede, squash-merge-only,QEP-N vM:commit subjects, thestandard/process/informationaltypetaxonomy, an Automation section, and git-as-history. Setstype: process,version: 1.qeps/template.mdtypeenum; a comment notingversion(and its CI-stampedversion-hash) appears on first amendment, while a new QEP stays unversioned (v0).README.mdTypeandVersioncolumns added to the index; QEP-1 row →process/v1.AGENTS.md.github/scripts/qeps.mjs(frontmatter + README-table parsing),stamp.mjs(post-merge: writeversion-hash, sync README),check.mjs(per-PR checks). All version parsing is scoped to the frontmatter block, so aversion:example in a QEP body is never mistaken for the real field..github/workflows/stamp-version.yml(post-merge: stamp the merged hash, sync README) andqep-checks.yml(per-PR:versionincrements by at most one, README↔frontmatter parity).The model assumes squash-merge only (one amendment = one commit). That is a repository setting CI cannot apply. After this merges, please set in Settings → General → Pull Requests: enable Allow squash merging, and disable Allow merge commits and Allow rebase merging. I left the live repo settings untouched, as agreed.
Validation
check.mjs) passes locally, and both workflow YAMLs parse.version-hashkey — is covered by round-trip checks: first-stamp insertion, re-stamp replacement, idempotence, and confirming aversion:/version-hash:example inside a QEP body is never rewritten.Decision
Per QEP-1, this is decided by lazy consensus at a deadline. Suggested comment window: two weeks (by 2026-07-08) — adjust as you like.