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.

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?

Answer

For all standard document types, use compass add instead of calling generate_doc.sh 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 projects/ores.codegen/generate_doc.sh with the type, slug, parent directory, and the document's title and description. The script 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.

New task

projects/ores.codegen/generate_doc.sh \
  --type 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.

New story

projects/ores.codegen/generate_doc.sh \
  --type 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"

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:

projects/ores.codegen/generate_doc.sh \
  --type 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.

New sprint

projects/ores.codegen/generate_doc.sh \
  --type sprint --slug sprint_17 \
  --parent-dir doc/agile/versions/v0 \
  --title "Sprint 17" \
  --description "Sprint 17 — describe its mission in one sentence." \
  --tags "v0"

New version

projects/ores.codegen/generate_doc.sh \
  --type version --slug v1 \
  --parent-dir doc/agile/versions \
  --title "Version 1" \
  --description "First production release." \
  --tags "v1"

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.

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.

New manual chapter

Use compass add manual. The slug should follow the chapter_<N>_<topic> convention. --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_4_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"

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"

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

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.

projects/ores.codegen/generate_doc.sh \
  --type 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"

New investigation report

Investigation reports live in doc/investigations/. They are formal records of technical research or debugging sessions.

projects/ores.codegen/generate_doc.sh \
  --type investigation --slug msvc_c1202_rfl_complexity \
  --parent-dir doc/investigations \
  --title "MSVC C1202 and rfl complexity" \
  --description "Root cause analysis of recursive template depth limits in reflect-cpp." \
  --tags "msvc,cpp,reflect_cpp,investigation"

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:

projects/ores.codegen/generate_doc.sh \
  --type capture --slug add_uptime_screen \
  --parent-dir doc/agile/product_backlog/next \
  --title "Add an uptime screen" \
  --description "Surface live service health in the Qt UI." \
  --tags "ui,observability"

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

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.

projects/ores.codegen/generate_doc.sh \
  --type 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 doc-add-memory skill; for the standalone recipe with body conventions, see How do I create a memory?.

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.

    projects/ores.codegen/generate_doc.sh --type knowledge ...
    projects/ores.codegen/generate_doc.sh --type component --slug component_overview ...
    projects/ores.codegen/generate_doc.sh --type 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.

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.

Tested by

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

See also

Emacs 29.1 (Org mode 9.6.6)