Guidelines¶
Source of truth for code, UI, and process conventions in Aletheia. Anything written here is authoritative — code that violates these guidelines should be flagged in review and fixed.
This folder is for code authors and Claude. End-user / operator documentation lives in docs/. Roadmap and planning live in roadmap/. Cross-repo API and infra contracts live in contracts/.
Why a separate top-level folder¶
- Single audience per file (Claude + developers writing code), single tone.
- Mechanical scoping for hooks, audits, and PR-time checks (
guidelines/**). - Drift is visible: a missing file for a recurring UI or backend primitive is an obvious gap.
- Symmetric with the existing top-level concept folders (
roadmap/,contracts/,docs/).
Layout¶
guidelines/
README.md # this file — index + status of every guideline
ui/ # per-component visual rules
search-sort-filter.md
lists.md
forms.md
detail-pages.md
dropdowns.md
badges.md
design-tokens.md
ux/ # system-wide interaction patterns (cross-component)
page-states.md
feedback-and-confirmation.md
navigation.md
microcopy.md
backend/ # Django patterns
views.md
models.md
migrations.md
forms.md
admin.md
security/ # auth, isolation, PII
multi-tenant-isolation.md
auth-and-permissions.md
pii-and-logging.md
celery/ # background jobs and beat schedule
task-conventions.md
integrations/ # external connectors (Doctolib, Pennylane, Logosw, INPI)
overview.md
doctolib.md
pennylane.md
logosw.md
inpi.md
imports/ # AbstractImporter / ImportRow patterns
abstract-importer.md
testing/
pytest-patterns.md
asserting-on-translated-strings.md
i18n/
translation-rules.md
development-workflow/
overview.md
ui/ vs ux/. ui/ is per-component visual rules (badges, lists, forms, dropdowns). ux/ is cross-component interaction patterns (empty/loading/error states, navigation, microcopy, feedback channels). When in doubt: if it's about one component's appearance, it's ui/; if it's a pattern that applies across many components, it's ux/.
Granularity rule. Every topic gets a folder, even if it currently holds a single file. Topics naturally grow (i18n splits into translation rules + model strings + JS strings; dev-workflow splits into git + environments + deploys), and folder-per-topic costs almost nothing today while making future splits painless. Audit globs stay uniform: guidelines/*/....
Naming. Folders and files are kebab-case. File names describe content, not topic (translation-rules.md, not i18n.md inside i18n/). No UPPER_CASE, no dates in filenames.
File format¶
Every guideline file should open with the same frontmatter so the status table stays accurate without manual bookkeeping:
# {Title}
> **Status:** Implemented | Draft | Placeholder
> **Last reviewed:** YYYY-MM-DD
> **Owner:** (optional)
## Scope
One paragraph: what this guideline covers and when it kicks in.
## Rules
The actual rules — copy-pasteable snippets preferred over prose.
## Known deviations
Where the codebase doesn't yet follow the rule, with a pointer to the roadmap item that closes the gap.
Status¶
Statuses: - Implemented — content is current and authoritative. - Draft — content exists but hasn't been reviewed against current code. - Placeholder — file exists to mark the gap; content to be written from an audit + skeleton/reference-page extraction.
| Path | Status | Last reviewed | Notes |
|---|---|---|---|
i18n/translation-rules.md |
Implemented | 2026-04-18 | Consolidated to French source everywhere (Option B). Documents nl-be rationale, _(f"…") antipattern, percent-format convention, module constants pattern. Two backlog sweeps filed (model strings, template/view drift) |
development-workflow/overview.md |
Draft | 2026-04-14 | Migrated from docs/DEVELOPMENT_WORKFLOW.md — verify deploy section still matches Makefile + deploy.sh |
ui/search-sort-filter.md |
Implemented | 2026-04-18 | Authoritative for list/sort/filter stack; one known deviation (finance module) tracked in roadmap/backlog/finance-filter-unify.md |
ui/lists.md |
Implemented | 2026-04-18 | Mined from skeleton + reference impls (practices, patients, holders); covers file layout, two empty states, action column, density rules; defers sort/filter to search-sort-filter.md |
ui/forms.md |
Implemented | 2026-04-18 | Mined from skeleton + form-enhancements.{css,js} + holder_form (contextual reference); covers Alpine state, edit-mode safeguards, validation/auto-format hooks |
ui/detail-pages.md |
Implemented | 2026-04-18 | Mined from skeleton + entity/practice references; covers heading + actions, two-column card grid, audit footer, layout-table-vs-data-table distinction; substitution cheatsheet for the 15 <h5>-in-card-header audit hits |
ui/dropdowns.md |
Implemented | 2026-04-19 | SearchSelect as the form-picker primitive above ~8 options; explicit queryset .order_by; disabled_choices + "Déjà rattachés" separator; JS load order and FORM_RENDERER dependency; flags 3 deviations (link_practice missing form-enhancements.js, register/finance/websites native-Select FK audit, skeleton lacks SearchSelect example) |
ui/badges.md |
Implemented | 2026-04-18 | 4-state status palette + badge-type family modifier pattern; entity & movement variants; flags 2 internal inconsistencies (naming scheme, hardcoded oklch in module CSS) |
ui/design-tokens.md |
Implemented | 2026-04-18 | Full catalogue mined from static/css/base.css; includes audit cheatsheet for the 2026-04 hardcoded-value findings |
ux/page-states.md |
Placeholder | — | Empty / loading / error / no-permission states across all pages |
ux/feedback-and-confirmation.md |
Implemented | 2026-04-20 | Channel decision tree (toast vs banner vs hx-confirm vs _confirm_delete.html vs modal); canonical extra_tags='toast info' pattern; bulk partial-failure 3-way summary; flags 3 deviations (MESSAGE_TAGS not configured, ad-hoc confirm() in 4 sites, _confirm_delete.html structural drift across 8 templates) |
ux/navigation.md |
Implemented | 2026-05-01 | Layout shell (base.html blocks), sidebar active-state via request.resolver_match, breadcrumbs context shape + section-root helpers, success_url post-create/update → detail, post-delete → list (older modules go to list — drift tracked), Cancel always <a href>, multi-select practice scope (cookie + URL override). Two backlog items + one idea filed |
ux/microcopy.md |
Implemented | 2026-05-01 | Canonical EN→FR verb glossary (synced with scripts/audit_i18n_source.py); 5 hard rules — imperative button verbs, vous + sentence case, blame-free error tone, 2-line empty states, named-target destructive confirmations; flags 1 deviation (5 Êtes-vous sûr confirm-delete templates — folds into existing ux-confirm-delete-template-convergence sweep) |
backend/views.md |
Placeholder | — | Document SortableFilterableListMixin, HtmxResponseMixin, CBV conventions |
backend/models.md |
Placeholder | — | Document TimeStampedModel, AuditModel, SoftDeleteModel usage |
backend/migrations.md |
Placeholder | — | When to write a data migration, naming conventions |
backend/database-schemas.md |
Implemented | 2026-05-08 | Schema-location rule (managed → public; unmanaged mirrors + raw landing tables → nomos/pennylane/raw); search_path mechanism, idempotent _move_if_in migration template, drift detection, anti-patterns; flags 4 deviations (5 misnamed *_namespace_tables.py files, qualified-vs-bare references in convention_dentaire_import.py, runtime DDL duplication, no automated drift audit) |
backend/forms.md |
Placeholder | — | Django form / ModelForm conventions, complements ui/forms.md |
backend/admin.md |
Placeholder | — | When to register, list_display / list_filter / inline conventions |
security/multi-tenant-isolation.md |
Placeholder | — | High blast radius — practice scoping rules, queryset filtering |
security/auth-and-permissions.md |
Placeholder | — | Custom User, login, permission decorators / mixins |
security/pii-and-logging.md |
Placeholder | — | What never to log, Sentry scrubbing, PII categories |
celery/task-conventions.md |
Placeholder | — | Task naming, idempotency, retry, beat schedule, failure surfacing |
integrations/overview.md |
Placeholder | — | Shared connector patterns (auth, retry, pagination, persistence) |
integrations/doctolib.md |
Placeholder | — | Doctolib API, daily 3 AM sync, appointment reconciliation |
integrations/pennylane.md |
Placeholder | — | Pennylane Redshift + REST v2, dual-backend abstraction |
integrations/logosw.md |
Placeholder | — | File-based ingestion via apps/collection/ + apps/imports/ |
integrations/inpi.md |
Placeholder | — | INPI RNE via apps/annuaire/, code→label mappings |
imports/abstract-importer.md |
Placeholder | — | Document AbstractImporter lifecycle, ImportRow tracking, bulk mode |
testing/pytest-patterns.md |
Placeholder | — | Fixture conventions, integration vs unit boundary |
testing/asserting-on-translated-strings.md |
Implemented | 2026-04-23 | Never hardcode _()/get_*_display() output in assertions; use Pattern A (stable code) or Pattern B (delegate to object's display helper). Surfaced by the 2026-04 coverage audit when 2 tests silently failed after the French-source sweep |
Roadmap for this folder¶
Linear bring-up (one-time, per cluster)¶
A "cluster" is a top-level folder under guidelines/ (ui/, backend/, security/, celery/, etc.). Each cluster follows the same 4-step bring-up. The UI cluster was brought up first in 2026-04 and is referenced below as the worked example; other clusters apply the same recipe with their own scope.
-
Beef up content — turn placeholders into Implemented files by mining the codebase: recent "consistency sweep" or refactor commits in the cluster's area, the cleanest reference implementations, any relevant skeleton/template files, and external references where applicable. Spawn the Placeholder graduation workflow (template below) per primitive. Worked example: UI cluster mined
templates/skeletons/+ reference pages (patients, holders, practices) for the per-component rules. -
Retroactive audit — once a primitive's guideline is Implemented, spawn the Audit pass workflow (template below). The subagent grep-walks the cluster's relevant code paths against the new rules and produces a backlog file. Worked example: UI audit walked
templates/**/*.html+static/css/*+apps/**/*.pyfor the i18n-related rule. Other clusters scope differently — security audits targetapps/*/views.py+apps/*/admin.py; celery audits targetapps/*/tasks.py+config/celery.py; etc. -
Proactive enforcement — Live as of 2026-04-18, layered. The enforcement layers and forcing semantics are cluster-agnostic; only the rules added to the checker grow per-cluster. Two layers consume the same script (
scripts/check_conformance.py— name is historical, the script enforces both UI and i18n rules and is structured to grow with new cluster rules): - Layer A — PostToolUse hook (advisory).
.claude/settings.jsoninvokes the script after every Edit/Write/NotebookEdit. Prints[BLOCK]and[WARN]violations to stdout so Claude sees them in the tool result and self-corrects on the next turn. Never fails (exit 0 always). - Layer B — Git pre-commit hook (forcing).
.githooks/pre-commitruns the script with--strictagainst staged files on everygit commit. Aborts the commit if anyblock-severity violation is found. Install withmake setup-hooks(one-time per clone). Bypass--no-verifyis reserved for genuine emergencies; Claude must not use it without explicit user permission. - Rules + severity:
block(deterministic, safe to fail commits): rules with zero false-positive risk. Currently encoded: rawbg-*/text-bg-*/bg-outline-*on badges;<h5>/<h6>incard-header-neutral;<tr><th>X</th><td>layout-table signature; literaloklch()/#hex/rgb()outsidestatic/css/base.css;_(\s*f"…")antipattern. Future clusters add their own deterministic rules (e.g. security:Model.objects.all()on practice-scoped models; celery: bare-name@taskdecorators).warn(heuristic, kept advisory to avoid false-positive friction): English source string in_()/{% trans %}matching the curated dictionary fromaudit_i18n_source.py. Cluster-specific heuristic checks (e.g. backend: model withoutTimeStampedModel) would also live here.
- Manual check across the tree:
make check-conformance. -
Out of scope (covered by audit scripts / subagents instead): semantic checks that need judgment (e.g. "layout table vs data table?", "is this empty state appropriate?"), full-codebase heuristic sweeps that risk false positives at hook scale (use the dedicated audit scripts in
scripts/for those). -
CLAUDE.md tightening — once a cluster's guidelines reach Implemented status, any rules duplicated in CLAUDE.md become thin pointers into
guidelines/<cluster>/. Worked example: the 2026-04 UI cluster bring-up retired the entire "UI Design System" → "Pending guideline migration" subsection of CLAUDE.md as each UI primitive graduated. Future clusters follow the same pattern: rule duplications in CLAUDE.md get retired into pointers as the corresponding guideline lands.
Status of the bring-up across clusters (as of 2026-04-19):
- ✅ UI cluster: 8/8 primitives Implemented; audit done; enforcement live; CLAUDE.md tightened.
- ✅ i18n cluster: 1/1 primitive Implemented; convergence sweep done; rolling audit tooling kept.
- 🔄 All other clusters (ux/, backend/, security/, celery/, integrations/, imports/, testing/, development-workflow/): placeholders prepped with self-sufficient structure (per "What a good placeholder contains" below); ready to graduate via the Placeholder graduation workflow whenever a trigger fires.
Three reusable workflows¶
Three subagent-runnable workflows cover everything that happens to a guideline after the cluster's Linear bring-up reaches it. Each has its own template later in this section.
| Workflow | Question | Output |
|---|---|---|
| Audit pass | "Does the code follow the rules?" | Audit-derived backlog file → fixes applied → spin-out deferrals → done |
| Challenge pass | "Are the rules the right rules?" | Keep / Change / Add / Drop report → guideline updates or Ideas |
| Placeholder graduation | "Should the placeholder become Implemented?" | Implemented guideline + signals to triage |
Cadence and complementarity:
- Audit (continuous, mechanical) surfaces violations of existing rules. Eventually hook-driven via
make check-conformanceand the pre-commit hook for deterministic rules; subagent-driven for heuristic ones. - Challenge (periodic, judgmental) questions the rules themselves — surfaces missing rules, stale assumptions, primitives that should exist but don't.
- Placeholder graduation (one-time per primitive, often parallel-session) turns a Placeholder into an Implemented guideline. Triggered by enforcement need, recurring questions, drift accumulation, or adjacent work.
Audit alone produces a locally-consistent codebase converging on possibly-suboptimal rules. Challenge alone produces evolving rules nobody adopts. Graduation alone produces guidelines without enforcement. Use all three; the templates below are the recipes.
Audit pass — template¶
Run an audit against one Implemented guideline at a time. The audit surfaces every place the codebase diverges from the rules, files them as a backlog item, and the work to address them follows the standard backlog → done flow (with the spin-out convention for any deferrals — see roadmap/ROADMAP.md "How this works").
Triggers — run an audit when one is true:
- Just graduated — the guideline flipped Placeholder/Draft → Implemented. Verify the codebase against the new rules; surface the gap.
- Hook upgrade — a new rule just landed in scripts/check_conformance.py. The hook will catch future violations; the audit catches the existing ones.
- Periodic — guideline has been Implemented for ≥ 6 months without an audit pass. Drift accumulates silently.
- Code-review signal — reviewers keep catching the same kind of violation in PRs. Time to find them all at once instead of one at a time.
- Incident-driven — a bug or near-miss pointed at a guideline rule that wasn't being followed somewhere. Sweep for similar cases.
Process:
-
Pick one Implemented guideline. Write the trigger in one sentence: "Audit
ui/badges.mdbecause [reason]." Confirm status is Implemented (not Draft or Placeholder — auditing against unstable rules wastes the subagent's work). -
Spawn an audit subagent. Skeleton prompt — substitute
<primitive>with the guideline's relative path (e.g.ui/badges.md):
TASK: Audit the Aletheia codebase for violations of the rules in
guidelines/<primitive>.md. This is a one-shot scan against a single Implemented guideline.Working directory: /Users/baudry/coding/aletheia/aletheia_v2
READ FIRST:
guidelines/<primitive>.md. Note the Hard rules section — those are the audit targets. Skip rules withseverity='warn'or "When to break the rules" exceptions unless explicitly asked.FOR EACH HARD RULE: - Construct a precise grep / multi-pattern search (cover variants — e.g. for
bg-*badges, also searchtext-bg-*andbg-outline-*; for_(...)strings, also checkgettext_lazy(...)and{% trans %}). - Run the search across the relevant scope (templates, apps//.py, static/css/, etc. — match the rule's scope from the guideline). - List file:line for each violation. Cap at top 10-15 per rule with a count summary if the total is high. - Per rule, include a one-line "fix hint" pointing at the canonical pattern in the guideline.LESSONS FROM PRIOR AUDITS (encode these into your search patterns): - Subagent grep patterns drift toward false positives — for any rule that surfaced overstated counts in past audits (e.g.
<table>in detail pages flagged data tables as layout tables), validate the layout-table-vs-data-table distinction by spot-checking the candidates' structure (single-<th>per<tr>= layout; multi-<th>in<thead>= data). - Subagent grep patterns also miss variants — always run multi-pattern searches, not single-pattern. - Check for canonical references in the codebase before classifying findings as violations — a file may already use the right pattern and serve as the model for the others (e.g. GLTrialBalanceImportView was the canonical i18n reference all along). - Subagent reports describe intent, not facts — verify any "fixed/unfixed" claim independently when consuming this report.OUTPUT: a single Markdown report with one section per hard rule. Each section: rule recap (one line), violation count (audit + actual / verified if you re-counted), top 10-15 file:line examples, one-line fix hint, concentration map (which 3-5 apps/folders have the most violations).
Cap at 500-600 words. Don't write any files (the consuming session will turn this report into a backlog file). Don't propose architecture changes. Just the audit report.
- Triage the report into a backlog file. Take the subagent's report and create
roadmap/backlog/<primitive>-audit-YYYY-MM.mdwith: - Status table at the top — finding | audit count | actual count | status (PENDING initially) | commit (filled when applied).
- Findings sections — one per rule, with the file:line lists and fix hints.
- Approach — phases or per-app PRs to address the work.
-
Definition of done — checkbox list including "0 / 0 violations on
make check-conformancere-run." -
Pick up the backlog and address. Apply fixes per the chosen approach (often per-app PRs).
-
Verification re-run. After the fixes land, re-spawn the same audit subagent with the same prompt. The verification surfaces:
- Confirms 0 remaining violations (the success signal).
-
Catches missed-variant violations the first audit's pattern didn't cover (e.g.
bg-outline-secondaryslipped past the originalbg-*pattern). Fix any of these inline; they don't justify another full audit cycle. -
Handle deferrals via spin-out (per
roadmap/ROADMAP.md"Done means zero follow action — handle deferrals with spin-out"). Each explicit "decided not to act" item becomes its own ≤30-line backlog file with deviation + rationale + revisit trigger + cross-ref to the parent audit. -
Close the audit file. Move to
roadmap/done/. Update ROADMAP.md (remove from Backlog, add to Recently Completed). Optionally: encode any new deterministic rules inscripts/check_conformance.pyso the same drift doesn't return.
What NOT to audit: - Placeholders or Drafts. Audit needs stable rules; auditing against rules that may change wastes work. - Heuristic-only guidelines (e.g. UX microcopy tone). Audit those informally; they don't fit the deterministic-grep model. - Anything with no measurable hard rules (purely descriptive guidelines). Re-frame the guideline before auditing.
Output convention:
- Backlog file: roadmap/backlog/<primitive>-audit-YYYY-MM.md (e.g. ui-design-system-mechanical-fixes-2026-04.md).
- Spun-out deferrals: roadmap/backlog/<area>-<thing>.md (no -audit- infix; they're standalone backlog items).
- Done file: same name, moved to roadmap/done/.
Reference example (the convention's mature form): the 2026-04 UI design-system audit (roadmap/done/ui-design-system-mechanical-fixes-2026-04.md) — surfaced 67 violations across 4 rules, all addressed via Phases A+B+C, with 2 single-occurrence deviations spun out as ui-tokenise-avatar-size.md and ui-tokenise-progress-bar-size.md. The verification re-run caught one missed-variant (bg-outline-secondary) the original audit's pattern missed.
Challenge pass — template¶
Run a challenge against one primitive at a time. Cap at 1-2 challenges per quarter, only against primitives showing a real signal (see triggers below). Resist the urge to re-litigate everything.
Triggers — run a challenge when one is true:
- Recurring deviations in audit output for the same primitive (3+ deferred items in a row → the rule is missing, not the code is wrong).
- User pain surfaces in real flows (e.g. "I had to fix the dropdown sorting on every form" → ui/dropdowns.md needs a challenge).
- External drift — a new reference design system landed (Material You, Geist, Primer) and our equivalent primitive feels old.
- Time-based — primitive is Implemented but hasn't been reviewed in >12 months.
Process:
-
Pick one primitive. Write the trigger in one sentence: "Challenge
ui/forms.mdbecause [reason]." If you can't fill that sentence, don't run the challenge. -
Spawn a challenge subagent. Skeleton prompt:
Read
guidelines/<primitive>.md. Then: - Survey 5 real implementations in the codebase that should follow it. Note where the rule fits, where it doesn't, where the implementation diverged anyway. - Compare to 1-2 external references (name them: e.g. GitHub Primer forms, Vercel Geist forms). - Identify 3 things the current rule does not address but should. - Identify 1-2 rules that look outdated or rarely useful and propose retiring or rewording them. - Output: a single Markdown report under 500 words, structured as "Keep / Change / Add / Drop." Don't write to any guideline file — just propose. -
Triage the report. For each Keep/Change/Add/Drop:
- Quick wins (clear consensus, low risk) → edit the guideline directly, bump
Last reviewed, note the change in commit message. - Bigger changes (need design discussion) → file as
roadmap/ideas/guideline-<primitive>-challenge.md. Promote to backlog only after discussion. -
Rejected → note inline in the guideline as a "Considered and rejected" anchor (so the next challenge doesn't re-propose it).
-
Bump status if material. A challenge that significantly rewrites a guideline resets its status to Draft until re-reviewed against current code. A challenge that confirms-with-tweaks keeps it Implemented but updates
Last reviewed. -
Close the loop. Add a one-liner to the bottom of the challenged guideline: "Last challenged: YYYY-MM-DD — see
roadmap/ideas/...(orcommit <sha>) for outcome."
Output convention:
- Challenge reports go to roadmap/ideas/guideline-<primitive>-challenge-YYYY-MM.md if bigger than a quick edit.
- Audit reports go to roadmap/backlog/<primitive>-audit-YYYY-MM.md (the convention used 2026-04).
What NOT to challenge: - Placeholders. If the guideline isn't Implemented yet, you're writing it, not challenging it. - Rules that came from a recent incident or post-mortem. Those have their reason in the commit message; respect it. - Anything you'd reword purely for style. Challenges need to surface a real gap, not a rewrite for taste.
Placeholder graduation — template¶
The flip side of "challenge an Implemented guideline" is "graduate a Placeholder to Implemented." Same shape: a bounded one-primitive task, ideally runnable in a parallel session without re-deriving context. If a placeholder is too thin to support that, the placeholder itself needs to be beefed up first (see "What a good placeholder contains" below).
Triggers — graduate a placeholder when one is true:
- Enforcement need — a new rule wants to land in scripts/check_conformance.py (or another forcing layer), but its source guideline is still a placeholder. The rule needs the doc to back it up.
- Recurring questions — "how do we do X?" comes up in 2+ recent PRs/conversations and the placeholder is the natural home.
- Drift accumulation — make check-conformance or a periodic audit surfaces violations that have nowhere to point ("see guidelines/ui/X.md" → placeholder).
- Adjacent work — you're touching the same primitive for product reasons; document it while context is loaded.
Process:
-
Pick one placeholder from the status table above. Confirm it's truly a Placeholder (not Draft) and read its current content — if it has fewer than the items in "What a good placeholder contains" below, beef it up before spawning a session.
-
Spawn a graduation session in a fresh
claudeCLI terminal. Skeleton prompt — substitute<primitive>with the placeholder's relative path (e.g.ui/dropdowns.md). The session does graduation and signal triage in one shot: cheap inline fixes are applied; backlog/idea items are filed with aStatus: Provisionalmarker that you confirm or delete afterwards.
TASK: Flesh out
guidelines/<primitive>.mdfrom Placeholder to Implemented. A developer or Claude reading the result should be able to apply the rules without grepping the codebase. ALSO triage and provisionally file every signal you find while doing the work — see PROCESS step 5 below.READ FIRST (in this order — establishes the conventions you must respect): 1.
CLAUDE.md— project conventions (Makefile-only commands;LANGUAGE_CODE='nl-be'is intentional; commit message styleArea: action). 2.guidelines/README.md— index, status table, layout rules. Update the status table at the end when you're done. 3.guidelines/<primitive>.md— the placeholder. Its "Reference structural sibling" tells you which Implemented guideline to mirror in shape; its "Sources to mine" lists the codebase entry points; its "Out of scope" tells you what to defer to other guidelines. 4. The structural sibling named in the placeholder (e.g.guidelines/ui/forms.mdfor component-style guidelines). 5.guidelines/i18n/translation-rules.md— French source for all_()and{% trans %}strings. 6.roadmap/ROADMAP.md"How this works" — for the spin-out and Provisional conventions you'll apply in PROCESS step 5.PROCESS: 1. Read the codebase sources listed in the placeholder's "Sources to mine" section. 2. Write
guidelines/<primitive>.mdmatching the structural sibling's shape (Status banner → Sources of truth → Scope → Hard rules → Required structure → conventions → Anti-patterns → Known deviations → When to break the rules). Aim for 200-280 lines. 3. Updateguidelines/README.mdstatus table: flip the row to Implemented + today's date + a one-line summary. 4. Runmake check-conformanceto confirm zero violations on your edits. 5. Triage signals found while reading the codebase. For each signal, classify and act in the same session: - Inline fix — mechanical, deterministic, ≤5 lines of code change, zero design judgment. Apply the fix. Runpython3 scripts/check_conformance.py <file>to verify the fix doesn't introduce new violations. Mention each inline fix in the graduation commit message. - Backlog — real work to schedule (audit, refactor, multi-file change). File atroadmap/backlog/<area>-<thing>-YYYY-MM.md(or just<area>-<thing>.mdfor items without a dated context) using the standard backlog template (Area / Effort / Depends on header, Problem, Approach). Prepend the file with the Provisional marker (template below). - Idea — design choice, "useful someday" item, or anything without a clear trigger. File atroadmap/ideas/<area>-<thing>.mdusing the lightweight ideas format (no metadata required). Prepend with the Provisional marker. - Report-only — edge case you're unsure about. Don't file. List in REPORT BACK; the human will decide.Provisional marker to prepend to every filed backlog/idea item:
The user will confirm (delete the marker lines), edit, or> **Status:** Provisional — surfaced by the YYYY-MM-DD graduation of `guidelines/<primitive>`. Confirm or delete. > **Filed by:** graduation session (single-shot triage; user override expected).git rmeach filed item later.Be conservative — only file if the signal is truly worth tracking. Don't pad. If in doubt, prefer Report-only. 6. Commit everything together (graduated guideline + status table + any inline fixes + provisional backlog/idea files). The pre-commit hook (
--strict) will block on[BLOCK]-severity violations — fix them, never--no-verify.CONSTRAINTS: - Hook is live: edits to
templates/**,static/css/*,apps/**/*.pytriggerscripts/check_conformance.pyadvisory output. - All Django commands viamaketargets; never rawdocker compose execorpython manage.py. - Code identifiers stay English; only_()-wrapped display strings are French.REPORT BACK: - Line count of the graduated guideline. - Commit hash. - The 3-5 hard rules you encoded. - Signals handled — list of inline fixes applied (file:line + one-line description), backlog files filed (path + one-line description + classification rationale), idea files filed (same), and any report-only signals (unsure cases for the user).
- Confirm provisional artifacts. Walk through each
roadmap/backlog/...androadmap/ideas/...file the session filed. For each: - Accept as-is → delete the
Status: ProvisionalandFiled by:lines. Commit. - Edit then accept → tweak content, delete the marker lines. Commit.
- Reject →
git rmthe file. Commit. - Promote to in-progress → standard backlog → in-progress flow.
Provisional items left unconfirmed remain visible (the marker is conspicuous) and will surface in the next backlog review. They don't block anything.
- Optional follow-up: encode in the hook. If the new guideline has rules amenable to deterministic regex enforcement (no false-positive risk), add them to
scripts/check_conformance.pywithseverity='block'. If they're heuristic, add asseverity='warn'. Update the README's "Proactive enforcement" section accordingly.
What a good placeholder contains (so the graduation prompt is self-sufficient — no per-primitive customisation needed):
- Status banner with Status: Placeholder and empty Last reviewed.
- Reference structural sibling — which Implemented guideline (e.g. guidelines/ui/forms.md) to mirror in shape and depth.
- Scope paragraph — what the guideline will cover.
- Out of scope subsection — what NOT to cover, with explicit cross-refs to the guidelines that own those concerns. Prevents duplication.
- Sources to mine — concrete file paths (with line ranges where useful), reference implementations, recent commits that surface the patterns.
- Starter hard rules to investigate — bullet list of suspected rules the author should validate against the codebase. The graduating session may keep, refine, or drop each.
- Decision points to settle — explicit "the author needs to choose between A and B" items. Surfaces design judgments that shouldn't be made silently.
guidelines/ui/dropdowns.md is the canonical example of a self-sufficient placeholder. Use it as a template when filing new ones.
What NOT to graduate this way: - Files that are already Draft — those need a verification pass against current code, not a from-scratch write. Edit directly. - Placeholders whose scope isn't yet decided — beef up the placeholder (Reference sibling + Out-of-scope) before graduating. - Anything that would duplicate an Implemented guideline — split or merge first.
Output convention: - Graduation lands as one commit per primitive (occasionally split if the work also needs a hook-rule addition or a separate audit run).
Update this README's status table whenever a file's status changes — it is the only manually-maintained index.