Vault conventions¶
This file is the single source of truth for how this vault is structured. Every other file — CLAUDE.md, README.md, the two skills — points here instead of restating these rules. When a rule changes, change it here and nowhere else.
For what the product is — actors, domain vocabulary, entities — read CLAUDE.md instead. That is the business layer; this is the structural layer.
The vault is shared via GitHub, so every path must be relative. Never write a machine-specific absolute path into a note.
1. One feature, one folder¶
Everything about a feature lives together:
01_Features/<domain>/<slug>/<slug>.md ← feature hub: all metadata
01_Features/<domain>/<slug>/<slug>_srs.md ← requirement note
01_Features/<domain>/<slug>/<slug>_ac.md ← acceptance criteria
01_Features/<domain>/<slug>/<slug>_tc.md ← test case register
01_Features/<domain>/<slug>/screens/*.png ← every image: app screenshots and Figma exports
01_Features/<domain>/<domain>.md ← domain hub, when the domain has 2+ features
- A feature that belongs to no domain drops the
<domain>/level:01_Features/login/login.md. - Domains in use:
accident,lawyer,voucher,workshop— the four subjects that have both a Web App and a Web Portal feature. Everything else is standalone. - A folder is a feature if it contains
<name>_srs.md. A domain folder contains only feature folders. Scripts and skills use this to tell the two apart. _ac.mdand_tc.mdare optional (see §5);<slug>.mdand<slug>_srs.mdalways exist.- One
screens/folder, nofigma/. Where an image came from is not worth a second folder.
2. Slug and platform prefix¶
- Slug — lowercase, identical to the feature folder name. This is what you pass to
/gen-acand/gen-tc. - A slug under a shared domain carries
wa_(Web App, the driver) orwp_(Web Portal, the Client Admin). The prefix is not cosmetic — it identifies the actor and the permission model. SeeCLAUDE.mdfor who those actors are. - Never register a bare domain name as a slug.
workshopalone is ambiguous between the driver feature and the admin feature, and that ambiguity is what once made the graph unreadable.
3. Feature metadata¶
There is no registry file. The feature hub is the source of truth for its own metadata:
---
type: feature
code: WS # ID prefix — AC-WS-01, BR-WS-01, TC-WS-001
domain: workshop # omitted for a standalone feature
platform: Web App # Web App | Web Portal | Android | SaaS Admin
actor: Driver # Driver | Client Admin | MCS Admin
entity: # links, not plain text — see §4
- "[Workshop](<entities/e_workshop.md>)"
- "[Voucher](<entities/e_voucher.md>)"
jira: [RC-120] # story tickets only, never the epic
status: Draft
srs: "[wa_workshop_srs](<../01_Features/workshop/wa_workshop/wa_workshop_srs.md>)"
ac: "[wa_workshop_ac](<../01_Features/workshop/wa_workshop/wa_workshop_ac.md>)" # omit if the feature has no AC
tc: "[wa_workshop_tc](<../01_Features/workshop/wa_workshop/wa_workshop_tc.md>)" # omit if the feature has no TC
related: [] # see §6 — normally empty
---
- Code — 2–6 uppercase letters, unique across the whole vault. Used only in IDs:
AC-<CODE>-NN,BR-<CODE>-NN,TC-<CODE>-NNN. - A code already used in any ID must never change — it would break traceability across hundreds of IDs. Reserved codes for features that have no folder yet are listed in
features.md. [features.base](<./features.base>)renders all of this as a live table (views: All features, Impact by entity, Test coverage). It is generated from the hubs — never edit a feature's data there.- SRS / AC / TC notes carry a lighter header:
type,feature(a link back to the hub),code,jira,status. TC registers addtc_total,tc_automated,tc_pending.
4. Entities, and finding impact across features¶
The domain tree groups features by subject area. It does not show impact: the Voucher record is touched by four features spread across two domains, so a voucher change puts all four at risk while the domain hubs show them as two unrelated trees.
Entity notes are the second, orthogonal axis. One note per record type in 00_Project_Info/entities/:
e_company · e_user · e_vehicle · e_accident · e_workshop · e_expert · e_lawyer · e_voucher · e_ad · e_pricing
Every feature hub links to the entities it owns. That single link is the whole mechanism:
To answer "what else does this change put at risk?" — open the entity note and read its Backlinks. Every feature that touches those records is listed there, automatically, including features in other domains.
Rules for the entity value:
- Declare only the entity the feature takes as its subject — the records it reads or writes as its actual job. Use
entity: []when there is none (pure-UI features). - Do not declare an entity a feature merely branches on. Almost every screen behaves differently for a logged-in vs. guest user; if that counted, every feature would list
Userand the axis would carry no information.homepagelistsAd(it renders banners), notUser(it only checks session state). - One entity is normal; two happens when a feature genuinely owns both (
registrationcreates aUserand registers aVehicle). More than two usually means the feature is too broad — check whether it should be split. - The
e_prefix is required. An entity note calledVoucher.mdwould collide with thevoucherdomain hub — Obsidian resolves link targets case-insensitively — and every impact edge would silently point at the wrong note. Link with a display alias:"[Voucher](<entities/e_voucher.md>)".
Both skills do this — /gen-ac at step 3b, /gen-tc at step 4b — and both report what they checked. When a hub has an empty entity they say so rather than guessing, because an empty value silently shrinks every future impact search.
5. Traceability¶
Jira ticket ──▶ AC-<CODE>-NN / BR-<CODE>-NN ──▶ TC-<CODE>-NNN
(the why) (the what — definition of done) (the how to verify)
AC are optional — write them when the ticket is ambiguous, high-risk, or needs stakeholder sign-off. For a small clear ticket go straight to TCs and set the AC column to —. Coverage rule: every business rule and every Critical/High AC needs ≥1 TC.
6. Linking discipline¶
Obsidian builds its graph from links alone, including links written in frontmatter. The rules exist so the graph stays a set of readable feature clusters instead of a hairball:
| Direction | How | Who maintains it |
|---|---|---|
| Feature hub → its SRS / AC / TC | frontmatter srs: / ac: / tc: |
the skills, automatically |
| SRS / AC / TC → its feature hub | frontmatter feature: |
the skills, automatically |
| Feature hub → entity | frontmatter entity: |
the one human decision, once per feature |
| Feature ↔ feature | nothing — they meet at the shared entity note | automatic |
| Domain hub → its features | a body table of wiki-links | on feature creation |
Feature hub → feature hub (related:) |
only for a real dependency that shares no entity | rare, by hand, with the reason written in the body |
| Inside AC / TC prose | the other feature's code in backticks (WS, AA) — never a wiki-link |
— |
- An AC or TC note never links sideways. It links up to its hub and nowhere else. Cross-feature impact belongs in the analysis, cited by code.
- Codes beat wiki-links in prose: short, stable, searchable with
Cmd+Shift+F, and they survive a file moving.
Never link to a folder¶
[01_Features/accident/wa_my_accident/](<../01_Features/accident/wa_my_accident/.md>) — with a trailing slash — does not resolve. Obsidian links point at notes, not folders, so this renders as a dead grey node. Always link the note. Verify the target file exists before writing the link, or run python scripts/check_links.py, which checks every wiki-link, embed and backtick path in the vault and exits non-zero if any is unresolved.
7. Templates¶
04_Templates/ holds the output formats. Read them from the vault at generation time — never hardcode a copy into a skill.
| File | Used by |
|---|---|
feature_hub_template.md |
creating a feature |
srs_template.md |
creating a feature |
ac_template.md |
/gen-ac |
testcases_template.md |
/gen-tc |
bug_template.md |
manual bug reports |
8. Writing¶
- All note content in English — body text, table cells, headers, and Type / Priority / Status values. The vault is shared on GitHub. German product terms stay German where the UI uses them; gloss them on first use. A verbatim stakeholder quote may stay in its original language only if an English gloss follows it in parentheses — the quote is evidence, the gloss is the content.
- Test cases stay high-level: one scenario, 3–5 steps, no click-by-click. The Cucumber automation layer writes the detailed steps.
- Never fabricate UI you have not seen in a screenshot, and never invent a business rule — flag the assumption instead.
- Never modify
.obsidian/config as part of a content task.
9. Generated folders — do not edit¶
docs/ is a symlink tree built by scripts/build-docs-tree.sh for MkDocs; site/ is the built HTML. Both are gitignored and excluded from Obsidian's index via userIgnoreFilters in .obsidian/app.json — without that exclusion every note appears twice in the graph.