docs: dedupe the project documents and add a task index - #39
Merged
Merged
Conversation
Cross-file deduplication and size reduction across CLAUDE.md, the README and the private notes. NOT the prose-verbosity trim, which stays deferred until the app is finished. Rule applied throughout: trim status, keep rationale. - CLAUDE.md gains a heading-anchored index grouped by task, so a coder starting a PR can find one rule without reading 2000 lines. Anchored to heading text, never line numbers, which rot. - Eight contradictions resolved against the code rather than guessed. The significant one was public: CLAUDE.md and the README both claimed V-scale, Font and French grades are directly comparable. server/domain/grades.py puts boulder in the 1000-band and rope in the 2000-band and raises CrossDisciplineError, so V5 and 7A compare but 6c+ does not. - README no longer calls dev the default branch (main is), and points at CLAUDE.md instead of restating the testing policy, CI internals and auth internals. Headings de-versioned so anchors stop rotting. - The byte-identical-twin rule's add/add half is marked expired; the "inert until the next promotion" half stands. - REPLAY_GRACE keeps the operative one-line constraint here; the analysis moved to private notes. - The query-cache persistence ban keeps its rule and loses its expired reason. The hazard is that localStorage belongs to the shell, not PR #6 sequencing. It does not constrain the outbox. - Adds two rules that were missing: migrate production BEFORE promoting, and hand the migrate.yml dispatch to Kilian rather than attempting it. - migrate.yml is comments only: drops the revision numbers that went stale at 0003, keeps the ref-vs-environment distinction. No version bump, matching #32. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
kilianmc
added a commit
that referenced
this pull request
Aug 20, 2026
…dropped (#40) Production now holds real accounts, and the v3.0.0 promotion is next. These are the rules and guards for not losing them. - tests/test_migrations_additive.py: fails if a migration's upgrade() would destroy app_user. Two arms — Alembic ops (drop_table/drop_column) and raw SQL in op.execute/sa.text strings (DROP COLUMN, DROP TABLE, DELETE FROM, TRUNCATE, SET NOT NULL). Both scoped to the module-level upgrade(); downgrade() bodies are legitimately destructive and ignored, which 0003 proves as a standing control. Inspects string literals only — dynamically built SQL escapes it, and the docstring says so rather than implying a guarantee. - server/admin.py: create-invite and set-password now print the target host and database and require it typed back, with --yes as the only bypass. devseed had this and admin did not, while admin is the one documented as run against production. set-password confirms before the getpass prompt. - server/db.py: target_host_and_database() is now the single redaction point; devseed delegates to it, so there is one copy of that logic, not two. Host and database only — never user, password, query string or full URL. - CLAUDE.md: minting an invite is a LOCAL command and must never become a workflow step (create-invite prints the plaintext code and Actions logs on this public repo are world-readable); app_user migrations are additive-only; never alembic downgrade against production, and the absent downgrade action in migrate.yml is load-bearing; snapshot the Neon branch before a production upgrade (retention is plan-dependent, read it from the dashboard); a promotion is not complete until the applied revision is read back. - migrate.yml: comment recording why there is no downgrade option. Also restores security checklist item 14 ("2FA still enabled on GitHub, Vercel, Neon and Cloudflare"), which PR #39 deleted along with duplicating item 13's opening line, leaving the list 12 → 13 → 13 → 15. Recovered verbatim from 9d8dca5. Out of this PR's scope, but a silently dropped security item should not wait for a later PR. No version bump; the promotion that follows takes this to 3.0.0. Co-authored-by: Kilian Mateo <13885240+kilianmc@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This branch was successfully deployed
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.
Cross-file deduplication and size reduction over the six documents that describe this project. Not the prose-verbosity trim — that stays deferred until the app is finished, per CLAUDE.md's own "docs deep clean" note. Rule applied throughout: trim status, keep rationale.
Docs only. No behaviour change, no version bump (matching #32).
Size
4218 → 3164 lines across all six documents (−25%). Most of the cut is in the private notes and the plan file (7 of its 8 planned PRs have shipped); CLAUDE.md's body is flat and it grew only by the index, because it is the sink every deduped fact drains into.
The index
New heading-anchored section at the top of CLAUDE.md, grouped by task — adding a migration, touching auth, changing the federated mount, promoting, dependencies, styling. Anchored to heading text, never line numbers; two line numbers already shifted during this work.
Contradictions fixed
Eight, each verified against the code rather than guessed. The one worth calling out was public and wrong in both files:
server/domain/grades.pyputs boulder in the 1000-band and rope in the 2000-band and raisesCrossDisciplineError. SoV5and7Acompare;6c+is French rope and does not.devthe default branch —mainis.server/app/domain/planner/; it isserver/domain/.68ch;_layout.scsssays56ch.Two rules that were missing
migrate.ymldispatch is handed to Kilian, not attempted —gh workflow runagainstproductionis correctly refused, and the connection strings live only in the GitHub environments.Deduplication direction
Shared facts live in CLAUDE.md; the private notes keep one-line pointers, because those load before CLAUDE.md is read and the pointer is what sends a reader to it. Nothing moved from private to public.
REPLAY_GRACEwent the other way: the public file keeps the one-line constraint, the analysis moved private.Review notes
Lightweight review is appropriate — docs, plus a comments-only change to
migrate.yml(its diff touches no non-comment line, so YAML validity is unaffected).Not independently re-read: all 465 changed lines of CLAUDE.md. The consequential and checkable claims were verified against the code; the rest rests on the drafting pass.
🤖 Generated with Claude Code