# ✂ docujoint template — adapt this to your system; delete this line when it is yours.
# Your Format Definition — a profile on top of OKF v0.1, interpreted by docujoint.
#
# Everything you don't constrain stays at OKF's tolerant default, so this file
# can stay small for a long time. Tighten it as your format grows: add types,
# blocks, schemes, and checks — the engine enforces what you declare.

format:
  name: my-docs
  version: "0.1"
  okf_version: "0.1"

vault:
  reserved_files: [index.md, log.md]
  links:
    forbid:
      - { rule: wikilink, severity: error, code: wikilink }
    broken_internal: warn
  index: { generated: true }        # dj index --write maintains index.md

# External-reference URI schemes: evidence tokens your docs may cite.
# Syntax is always checked; with `dj lint --inventory` they are also
# reconciled against a scan of what actually exists.
schemes:
  repo: { pattern: "repo://[\\w.-]+/\\S+" }
  test: { pattern: "test://[\\w.-]+/\\S+" }

shared:
  empty_markers: ["—", "-", ""]
  stub_marker: "_To be documented._"
  # what this format's own values MEAN, in this format's own words. The engine
  # ships no vocabulary — an undeclared value still renders, it just carries a
  # palette colour rather than a meaning.
  colors:
    done: success
    answered: success
    blocked: error
    stalled: warning
    open: warning
    todo: muted
    deferred: muted
    wontfix: muted
  enums:
    q_status: [open, answered, deferred, wontfix]

markdown:
  comments: [html, obsidian]        # stripped before ANY parsing

blocks:
  # A task table with DERIVED state: fill Done (what proves it) and Blocked
  # (what stands in the way); the state is computed, never stored — so it can
  # never contradict the prose.
  tasks:
    heading: Tasks
    identity: uuid
    columns:
      - { name: ID, id_grammar: "t<n>", unique: error, sequential: warn }
      - { name: Task, required: true }
      - { name: Done, refs: [repo, test] }
      - { name: Blocked }
    forbid_columns:
      - { name: Status, severity: error, code: task-status-column }
    derive:
      state:
        - { when: "done && !blocked", then: done }
        - { when: "done && blocked", then: stalled }
        - { when: "!done && blocked", then: blocked }
        - { else: todo }
    # Row checks are expressions over the same context (uncomment to enforce):
    # checks:
    #   - { code: task-unproven, severity: warn,
    #       when: "done && !has_refs",
    #       message: "marked done but cites no evidence" }
    display:
      intro: prose
      columns:
        - { col: ID, style: mono, state: marker }
        - { col: Task, style: md }
        - { col: Done, style: md }
        - { col: Blocked, style: md }

  open-questions:
    heading: Open questions
    identity: uuid
    columns:
      - { name: Q, id_grammar: "q<n>", unique: error }
      - { name: Question, required: true }
      - { name: About, optional: true,
          ref: { block: tasks, column: ID, dangling: error, code: q-about-dangling } }
      - { name: Status, enum: shared.q_status, unknown: error, code: q-status }
      - { name: Resolution }
    display:
      intro: prose
      columns:
        - { col: Q, style: mono }
        - { col: Question, style: md }
        - { col: About, style: mono }
        - { col: Status, style: chip }
        - { col: Resolution, style: md }

  # A report's declared calculations — the SAME select/from/where/metric your
  # dashboard.yaml indicators use, so a scheduled report and a live dashboard
  # can never disagree about a number. Locally `dj report` reads them; on
  # cloud docujoint an armed schedule computes them at every run's commit.
  indicators:
    heading: Indicators
    columns:
      - { name: ID, id_grammar: "i<n>", unique: error }
      - { name: Indicator, required: true }
      - { name: Select }
      - { name: From }
      - { name: Where }
      - { name: Metric }
    display:
      intro: prose
      columns:
        - { col: ID, style: mono }
        - { col: Indicator, style: md }
        - { col: Select, style: mono }
        - { col: From, style: mono }
        - { col: Where, style: mono }
        - { col: Metric, style: mono }

types:
  # A thing worth describing — start here; add types as your docs specialize.
  concept:
    frontmatter:
      required: { title: string, description: string }
      optional: { tags: "string[]", timestamp: date }
    sections:
      duplicates: error
    blocks: [open-questions]

  # A standing report: quantitative rows the engine computes (Indicators),
  # prose around them, and — on cloud docujoint — a frontmatter `schedule:`
  # envelope (every/day/at, token_cap, delivery) that runs it on a clock.
  # Locally the schedule is inert and the document lints like any other.
  report:
    frontmatter:
      required: { title: string, description: string, uuid: string }
      optional: { tags: "string[]", timestamp: date, schedule: map }
    sections:
      duplicates: error
    blocks: [indicators, open-questions]

  # A process document with explicit steps and a task table.
  guide:
    frontmatter:
      required: { title: string, description: string }
      optional: { tags: "string[]", timestamp: date }
    sections:
      expect: [Overview, Steps]
      duplicates: error
    blocks: [tasks, open-questions]
