How do I create a new doc?

Table of Contents

For the contract every generated document follows (frontmatter, sections, TODO vocabulary), see document types. For background on the generator itself, see ores.codegen.

1. Question

How do I create a new information-architecture document — task, story, sprint, version, component, recipe, knowledge, skill, product identity, or capture, or memory — without hand-writing the frontmatter?

2. Answer

For all standard document types, use compass add instead of calling calling codegen directly. It supports: story, task, sprint, version, recipe, knowledge, component, capture, memory, investigation, product_identity, skill, diagram, entity_org, field_group, dataset_overview, facet, facet_group. It defaults --parent-dir from context (current sprint for stories/tasks, current version for sprints, doc/llm/skills for skills) so you rarely need to type a path. This recipe remains the authoritative reference for edge cases (explicit --id, non-current parents, cross-sprint predecessors, etc.).

Memories support a one-shot body — no placeholder fill-in step:

compass add memory --slug prefer_x_over_y --title "Prefer X over Y" \
  --description "One-line summary." --memory-subtype feedback \
  --statement "The rule itself." \
  --why "The correction or incident behind it." \
  --how-to-apply "When X applies, do Y."

Codegen field-group models scaffold into the component's modeling directory (the _field_group.org suffix drives loader dispatch):

compass add field_group --component trading --slug instrument_identity \
  --description "Codegen field-group model for instrument_identity." \
  --brief "Common identity fields shared by all instrument types."

Literate template-library docs scaffold into projects/ores.codegen/library/templates/ (the default parent dir for both types). A facet doc holds one template family's literate source and requires --facet-group; a facet_group doc is the namespace page indexing its facets (filename gets a _group.org suffix to avoid colliding with a same-named facet):

compass add facet --slug cpp_domain_type --facet-group cpp \
  --title "C++ domain type templates" --description "…"
compass add facet_group --slug cpp \
  --title "C++ template group" --description "…"

Call compass add <type> with the slug, parent directory, and the document's title and description. The generator fills in a fresh UUID, today's dates, the required frontmatter (including the glossary-linked blurb), a * Status table at the type's default state where applicable, and the skeleton sections — leaving only the content for you to fill in.

For task and story, the codegen automatically prepends Task: = / =Story: = to the title you supply (idempotent: passing =--title "Task: Foo" won't double-prefix). Sprints and versions keep the title as-given.

For task / story / sprint, parent :ID:, title and slug are auto-detected from <parent-dir>/<parent-type>.org so you usually don't need to pass them. Run the script from a terminal and it prompts for any missing required field.

2.1. New task

compass add task \
  --slug fix_broken_link \
  --parent-dir doc/agile/versions/v0/sprint_17/audit_tooling \
  --title "Fix broken id-links surfaced by audit" \
  --description "Audit reports two unresolved id-links; fix them." \
  --tags "audit,bug_fix"

Parent story info is auto-detected from doc/agile/versions/v0/sprint_17/audit_tooling/story.org.

2.2. New story

compass add story \
  --slug audit_tooling \
  --parent-dir doc/agile/versions/v0/sprint_17 \
  --title "Audit tooling" \
  --description "Scripts that enforce the information-architecture invariants." \
  --tags "audit,scripts"

2.3. New story continuing from a previous sprint

Add --predecessor-id and --predecessor-title. The script renders #+predecessor: in the frontmatter and a Continued from: line in the body:

compass add story \
  --slug currencies_temporal_continued \
  --parent-dir doc/agile/versions/v0/sprint_17 \
  --title "Currencies temporal (continued)" \
  --description "Pick up where sprint 02 left off." \
  --tags "currencies,temporal,reference_data" \
  --predecessor-id ed5bc735-fb54-4ce0-9a08-6dab88c242d0 \
  --predecessor-title "Currencies temporal and export"

After the script runs, manually update the predecessor story: add #+successor: <new-uuid> to its frontmatter and a Continued in: [[id:<new-uuid>][...]] note in its * Decisions section.

2.4. New sprint

compass add sprint \
  --slug sprint_17 \
  --parent-dir doc/agile/versions/v0 \
  --title "Sprint 17" \
  --description "Sprint 17 — describe its mission in one sentence." \
  --tags "v0"

2.5. New version

compass add version \
  --slug v1 \
  --parent-dir doc/agile/versions \
  --title "Version 1" \
  --description "First production release." \
  --tags "v1"

2.6. New component model

Component overview files are always named component_overview.org. Use --slug component_overview (not the component name):

./projects/ores.compass/compass.sh add component \
  --slug component_overview \
  --parent-dir projects/ores.example/modeling \
  --title "ores.example" \
  --description "One-line summary of what the component does." \
  --tags "example,component"

Output: projects/ores.example/modeling/component_overview.org. See How do I create a component overview? for how to fill in each section.

2.7. New recipe

Use the how_do_i_<thing> slug convention. The output is <parent-dir>/how_do_i_<thing>.org:

./projects/ores.compass/compass.sh add recipe \
  --slug how_do_i_clear_the_cache \
  --parent-dir doc/recipes/cmake \
  --title "How do I clear the cache?" \
  --description "Remove the CMake binary cache to force a clean re-configure." \
  --tags "cmake,build,recipe"

Scaffold with content — the body sections can be supplied as arguments (verbatim org markup; multi-line via $(printf ...) or shell $'...' quoting) so the recipe is born complete instead of with placeholder text:

  • --intro — lead paragraph before * Question;
  • --question — the * Question body;
  • --answer — the * Answer body (include the #+begin_src block);
  • --script — the * Script body;
  • --tested-by — the * Tested by body;
  • --see-also — one * See also bullet (repeatable).

Sections not supplied fall back to the fill-in placeholders.

When the recipe's * Answer involves a shell command, write it in an #+begin_src sh :results verbatim block so the recipe is executable in emacs (C-c C-c) — see How do I list available presets? for an example that also captures a #+RESULTS: snapshot.

2.8. New manual chapter

Use compass add manual. The slug should follow the chapter_<topic> convention — no chapter number in the filename; the manual's reading order comes entirely from where the chapter's #+include sits in user_manual.org, so inserting a chapter between two existing ones never requires renaming or renumbering anything else. --parent-dir defaults to doc/manual/user_guide and can be omitted. Headings inside the chapter start at ** (level 2); they become \section in the PDF. After creating, add a #+include line in user_manual.org and an entry in user_manual_site.org.

./projects/ores.compass/compass.sh add manual \
  --slug chapter_reference_data \
  --title "Reference Data" \
  --description "Reference data management in ORE Studio: currencies, countries, and other slowly-changing financial master data." \
  --tags "manual,reference_data,user_guide"

2.9. New knowledge document

./projects/ores.compass/compass.sh add knowledge \
  --slug build_system_decisions \
  --parent-dir doc/knowledge/architecture \
  --title "Build system decisions" \
  --description "Why we picked Ninja over Make as the default generator." \
  --tags "build,architecture,knowledge"

2.10. New Claude Code skill

Use compass add skill. The slug must be snake_case; it becomes the folder name and the name: field in the skill's markdown frontmatter. --parent-dir defaults to doc/llm/skills and can be omitted:

./projects/ores.compass/compass.sh add skill \
  --slug my_new_skill \
  --title "My New Skill" \
  --description "When and how to use the new skill."

Output: doc/llm/skills/my_new_skill/SKILL.org.

After filling in the skill body, rebuild the shipped bundle so Claude Code picks up the change — see How do I deploy the skills?:

./compass.sh build --direct skills

2.11. New product identity

There is one product identity document per product (product_identity.org under doc/identity/). The codegen scaffolds a fresh one — useful mostly when bootstrapping a new product or migrating an existing identity from scratch.

compass add product_identity \
  --slug product_identity \
  --parent-dir doc/identity \
  --title "ORE Studio product identity" \
  --description "The durable statement of what ORE Studio is and is not." \
  --tags "identity,vision"

2.12. New investigation report

Investigation reports live in the folder of the story that commissioned them, as investigation_<slug>.org, at level s1. Pass that story's folder as --parent-dir; there is no default, because an investigation belongs to a story rather than to a fixed directory.

compass add investigation \
  --slug msvc_c1202_rfl_complexity \
  --parent-dir doc/agile/versions/v0/sprint_18/rfl_complexity_resolution \
  --title "MSVC C1202 and rfl complexity" \
  --description "Root cause analysis of recursive template depth limits in reflect-cpp." \
  --tags "msvc,cpp,reflect_cpp,investigation"

Then add it to the story's * Investigations section. Before you cite it from code, a recipe, a model or a knowledge page, read Document type: investigation: the durable half of what it concludes goes to the page that owns the subject, and those surfaces cite that page.

2.13. New user journey

User journeys live in doc/knowledge/journeys/, one subfolder per logical group of journeys. Pass the group folder as --parent-dir; the group hub is expected to be <group>.org inside it.

compass add user_journey \
  --slug present_myself \
  --parent-dir doc/knowledge/journeys/profile \
  --title "Present myself" \
  --description "A member shows who they are: photo, name, job title and reporting line." \
  --tags "user_journey,security"

This writes doc/knowledge/journeys/profile/journey_present_myself.org. Wire it into the group hub's journey table.

2.14. New capture

Captures live in doc/agile/product_backlog/ across four buckets: inbox/ (untriaged), next/ (upcoming candidate), deferred/ (long-horizon), discarded/ (explicitly rejected).

The preferred way to file a new capture is compass capture, which lands the file in inbox/ automatically:

projects/ores.compass/compass.sh capture --note "Add an uptime screen"

To create directly in a specific bucket via codegen:

compass add capture \
  --slug add_uptime_screen \
  --parent-dir doc/agile/product_backlog/next \
  --title "Add an uptime screen" \
  --description "Surface live service health in the shell UI." \
  --tags "ui,observability"

The bucket name is derived from --parent-dir basename and appears in the generated blurb automatically.

2.15. New memory

Memories live under doc/llm/memory/. Pass --memory-subtype to pick the kind of memory (feedback / user / project / reference — default feedback). The memory filetag is auto-injected so the catalogue is greppable.

compass add memory \
  --slug do_not_re_export_env_vars \
  --parent-dir doc/llm/memory \
  --title "Do not re-export ORES_* env vars in Bash tool calls" \
  --description "The user already exports them; prepending is noise." \
  --memory-subtype feedback

For the LLM-side decision flow (when to write vs push back), see the compass-doc-add-memory skill; for the standalone recipe with body conventions, see How do I create a memory?.

2.16. Creating a set of inter-linked documents

When creating multiple documents that will link to each other (e.g. a knowledge doc and several component overviews that reference it), the correct order is:

  1. Generate all skeleton files first. Each call mints a fresh UUID. Do not pre-assign or guess UUIDs before running the script — they will not match.

    compass add knowledge ...
    compass add component --slug component_overview ...
    compass add component --slug component_overview ...
    
  2. Collect the generated IDs.

    grep "^:ID:" projects/ores.foo/modeling/component_overview.org \
                 doc/knowledge/topic/my_knowledge.org
    
  3. Fill in the content of each file, using the actual IDs in [[id:UUID][label]] links.

The --id flag is for migration only — preserving an existing UUID when reformatting a document that already has one. Never use it to pre-assign an ID to a brand-new document.

3. What the script does

  • Generates a fresh UUID (always uppercase hex) and puts it in :ID:. Every :ID: property and [[id:UUID]] link in the documentation graph must use uppercase hex — see Lock down uppercase UUID invariant.
  • Sets #+created and #+updated to today.
  • Adds --parent-slug as a filetag, so the parent-tag invariant holds.
  • Auto-detects parent :ID: and #+title: from <parent-dir>/<parent-type>.org for task/story/sprint.
  • Renders the type's Mustache template from projects/ores.codegen/library/templates/.
  • Writes the file (path varies by type — see the table in projects/ores.codegen/docs/doc_generator.md).
  • Refuses to overwrite an existing file unless --force is passed.

4. Tested by

Manual smoke tests during initial development. No automated test yet — ores.codegen does not currently exercise the doc generator in CI.

5. See also

Emacs 29.3 (Org mode 9.6.15)