Naming Conventions
Overview
StarSpec uses two distinct id formats depending on context:
| Context | Format | Example |
|---|---|---|
Document frontmatter id | kebab-case (unqualified) | id: add-bookmark |
Document frontmatter domain | kebab-case (unqualified) | domain: bookmark |
Document frontmatter context | {type}/{id} with / — the only frontmatter field that uses a qualified reference | context: [feature/add-bookmark, domain/auth] |
Root document tag id | Same unqualified value as frontmatter | \{% feature id="add-bookmark" %\} |
| Cross-document references in tag attributes | {type}/{id} with / | ref="feature/add-bookmark" |
| In-document child tag ids | kebab-case — no type prefix | id="save-url", name="add-bookmark" |
context is the only frontmatter field that uses the {type}/{id} qualified format. All other frontmatter fields (id, domain, tags) use unqualified values. The separator is always / — never :.
Type prefixes are never used on tag ids. The type is always inferred from the tag itself — {% action name="add-bookmark" %} is already an action, so adding action: would be redundant and is a validation error.
Document frontmatter
Standard frontmatter fields control how documents are routed and grouped in the public site:
| Field | Format | Purpose |
|---|---|---|
type | fixed keyword | Required. Determines the document schema and icon. |
id | kebab-case (unqualified) | Required. The unqualified identifier used in the URL. |
title | free text | Required. Human-readable name used in headings and sidebar. |
domain | kebab-case (unqualified) | Optional. Unqualified domain id (e.g. auth). Documents with the same domain are nested under a domain group in the sidebar. |
status | fixed keyword | Optional. draft (rendered as warning) or ready. |
context | {type}/{id} list — qualified | Optional. List of cross-document references whose {% tldr %} blocks are injected as agent context. This is the only frontmatter field that takes qualified references. Example: [feature/add-bookmark, domain/auth]. |
Root document tag rule
The id attribute on a root document tag must match the frontmatter id field exactly — no type prefix, no path.
type: flowid: add-bookmark ← frontmatter
\{% flow id="add-bookmark" ... %\} ✓ matches frontmatter\{% flow id="flow:add-bookmark" %\} ✗ type-prefixed (validation error)\{% flow id="flow/add-bookmark" %\} ✗ qualified pathIn-document child tag conventions
Identifiers: Tags that use id or name
Every child tag id is a plain kebab-case string — no type prefix. The tag itself provides the type context.
| Tag | Field | Example |
|---|---|---|
\{% requirement %\} | id | id="save-url" |
\{% criterion %\} | id | id="save-url" |
\{% action %\} | name | name="add-bookmark" |
\{% event %\} | name | name="bookmark-added" |
\{% operation %\} | name | name="get-bookmark" |
\{% error %\} | id | id="bookmark-not-found" |
\{% component %\} | id | id="bookmark-service" |
\{% rule %\} | id | id="no-direct-db" |
\{% goal %\} | id | id="ship-v1" |
\{% value %\} | id | id="simplicity" |
\{% principle %\} | id | id="local-first" |
\{% surface %\} | id | id="login-form" |
\{% diagram %\} | id | id="add-bookmark-flow" |
\{% policy %\} | id | id="rate-limit" |
\{% property %\} | name | name="session-id" |
\{% setting %\} | id | id="default-visibility" |
References: Tags that use ref or other pointer attributes
References also use bare kebab-case — no type prefix:
| Tag | Purpose | Example |
|---|---|---|
\{% criterion %\} | References a requirement | requirement="save-url" |
\{% uses %\} | References a component | component="bookmark-service" |
\{% step %\} | References an action or operation | action="add-bookmark" |
\{% path %\} (success) | Emits an event on this branch | emit="bookmark-added" |
\{% path %\} (failure) | Throws an error on this branch | throws="duplicate-url" |
\{% throws %\} | References an error | ref="bookmark-not-found" |
\{% policy %\} | Source trigger and reaction | source="add-bookmark" reaction="bookmark-added" |
\{% includes %\} | References a feature/flow | ref="feature/add-bookmark" |
\{% link %\} | References any document | ref="domain/auth" |
Naming rules by tag type
Actions — imperative verb-noun
Actions represent commands: something requested of the system.
add-bookmarkremove-bookmarklock-accountexpire-sessionUse the imperative form. Match the domain verb used in the blueprint loop.
Events — past-tense noun phrase
Events represent facts: something that already occurred.
bookmark-addedbookmark-removedaccount-lockedsession-expiredThe event name is derivable from its triggering action by converting verb-noun → noun-verb(past): add-bookmark → bookmark-added.
Operations — descriptive (read) or imperative (write)
get-bookmark (read)search-bookmarks (read)create-bookmark (write)Errors — descriptive noun phrase
Errors represent a specific domain failure mode.
bookmark-not-foundduplicate-urlinsufficient-permissionsRequirements — descriptive noun phrase
Use a phrase that names the behaviour, not an ordinal.
save-url ✓response-time ✓ (NFR in manifest)1 ✗ ordinals break on reorderrequirement-1 ✗ redundant wordingAcceptance criteria — mirror their requirement
save-url → save-urlsave-url → save-url-invalid-url (failure path variant)Components — singular noun, kebab-case
bookmark-service ✓bookmark-repository ✓bookmarks ✗ pluralBookmarkService ✗ PascalCaseCoherence across document boundaries
When a feature, its flows, its domain actions, and its blueprint components all represent the same operation, the name must match across all of them:
bookmark ← domain namecontext: [feature/add-bookmark, flow/add-bookmark] ← document id (cross-doc ref in YAML frontmatter context)add-bookmark ← flow serving this featureadd-bookmark ← domain action namebookmark-service ← blueprint component that handles itadd-bookmark-flow ← diagram idSub-document references
When a tag id is referenced from another document (e.g. \{% rule ref="..." %\}), use {type}/{id}#{tag-id}:
manifest/product#response-timefeature/add-bookmark#save-urlCommon violations
| Violation | Example | Fix |
|---|---|---|
| Root tag id type-prefixed | \{% flow id="flow:add-bookmark" %\} | \{% flow id="add-bookmark" %\} — match frontmatter |
Root tag id uses / format | \{% flow id="flow/add-bookmark" %\} | \{% flow id="add-bookmark" %\} — unqualified only |
| Type prefix on child tag id | name="action:add-bookmark" | name="add-bookmark" |
| Type prefix on child tag id | id="req:save-url" | id="save-url" |
| Type prefix on property name | name="prop:session-id" | name="session-id" |
| Ordinal id | id="1" on a requirement | Descriptive name: id="save-url" |
| PascalCase in component id | id="BookmarkService" | id="bookmark-service" |
| Action in past tense | name="bookmark-added" on action | name="bookmark-added" belongs on an event |
| Event in imperative | name="add-bookmark" on event | name="add-bookmark" belongs on an action |
Cross-doc ref using : | context: [feature:add-bookmark] | context: [feature/add-bookmark] |