ontoref/reflection/templates/manifest-self-interrogation-prompt.md
Jesús Pérez da083fb9ec
Some checks failed
Nickel Type Check / Nickel Type Checking (push) Has been cancelled
Rust CI / Security Audit (push) Has been cancelled
Rust CI / Check + Test + Lint (nightly) (push) Has been cancelled
Rust CI / Check + Test + Lint (stable) (push) Has been cancelled
.coder/m
2026-03-29 00:19:56 +00:00

9.3 KiB
Raw Permalink Blame History

Manifest Self-Interrogation — Enrichment Prompt

Purpose: Populate capabilities[], requirements[], and critical_deps[] in {project_name}'s .ontology/manifest.ncl. These fields answer the operational self-knowledge questions that ontology Practice nodes don't: what does the project do and why, what does it need to run, and what external dependencies carry blast radius when they break.

Substitutions required before use:

  • {project_name} — kebab-case project identifier
  • {project_dir} — absolute path to project root

Requires: ontoref installed globally (just install-daemon from the ontoref repo).


Bootstrap — source ontoref env vars

Before running any direct nickel export command, source the ontoref env into the current shell:

cd {project_dir}
. $(which ontoref) --env-only
# NICKEL_IMPORT_PATH and ONTOREF_ROOT are now available in this shell session

Context for the agent

You are enriching .ontology/manifest.ncl for project {project_name}. The three new arrays are semantically distinct — do not conflate them:

  • capabilities[] — operational, audience-facing. What the project offers, why it was built, how it works at implementation level. Cross-references ontology node IDs (nodes[]) and the ADRs that formalize design decisions (adrs[]). These are not architectural invariants — they evolve freely.
  • requirements[] — prerequisites to start. Classified by env (Production / Development / Both) and kind (Tool / Service / EnvVar / Infrastructure). Focus on impact (what breaks if absent) and provision (how to satisfy it).
  • critical_deps[] — runtime load-bearing external dependencies. Not "you need this to start" but "if this breaks or disappears, these capabilities degrade in these ways". failure_impact is required. Include feature flags or fallback builds in mitigation.

All entries must pass nickel export cleanly. Do not add entries you cannot substantiate by reading the code.


Phase 1 — Read the project

Before writing anything, understand the project. Read in order:

cd {project_dir}

# Architecture and purpose
cat README.md
cat .claude/CLAUDE.md 2>/dev/null || true

# Existing ontology — understand Practice nodes already declared
nickel export --import-path "$NICKEL_IMPORT_PATH" .ontology/core.ncl \
  | jq '[.nodes[] | {id, name, level, description}]'

# Existing manifest — see what is already declared
nickel export --import-path "$NICKEL_IMPORT_PATH" .ontology/manifest.ncl \
  | jq '{description, capabilities: (.capabilities | length), requirements: (.requirements | length), critical_deps: (.critical_deps | length)}'

# Cargo workspace — understand crate boundaries
cat Cargo.toml 2>/dev/null || true
ls crates/ 2>/dev/null || true

# External dependencies with most weight
cargo metadata --format-version 1 2>/dev/null \
  | jq '[.packages[] | select(.source == null) | {name, dependencies: [.dependencies[] | .name]}]' \
  2>/dev/null | head -60 || true

Identify:

  1. What the project does for each audience (developer, agent, CI, end user)
  2. Which Cargo features are optional vs default
  3. What external services are consumed (databases, message buses, APIs)
  4. What environment variables the project reads at startup
  5. Which dependencies are foundational (the project cannot function if they break their contract)

Phase 2 — Add description field

If .ontology/manifest.ncl has no description field, add it immediately after repo_kind:

  description = "One sentence: what is this project and for whom.",

Confirm with:

nickel export --import-path "$NICKEL_IMPORT_PATH" .ontology/manifest.ncl | jq .description

Phase 3 — Populate capabilities[]

For each major capability the project offers, write one entry. Use the builders:

  capabilities = [
    m.make_capability {
      id        = "kebab-id",
      name      = "Short Name",
      summary   = "One line: what does this capability do?",
      rationale = "Why does this exist? What problem does it solve? What was consciously rejected?",
      how       = "Implementation level: key patterns, entry points, data flows.",
      artifacts = [
        "crates/foo/src/lib.rs",
        "GET /api/endpoint",
        "reflection/modes/foo.ncl",
      ],
      adrs  = [],   # ADR IDs that formalize decisions in this capability
      nodes = [],   # ontology node IDs from core.ncl that this capability manifests
    },
  ],

Guidelines:

  • Aim for 26 capabilities. Do not list every feature — group by audience-facing concern.
  • nodes[] must match IDs declared in .ontology/core.ncl. Verify:
    nickel export --import-path "$NICKEL_IMPORT_PATH" .ontology/core.ncl | jq '[.nodes[].id]'
    
  • adrs[] must match IDs in adrs/adr-*.ncl. Verify:
    ls adrs/adr-*.ncl | sed 's|adrs/||;s|-[^-]*\.ncl||'
    
  • how and rationale can be empty strings ("") if there is nothing substantive to say. Do not pad with generic prose.

Phase 4 — Populate requirements[]

For each prerequisite to run the project (prod or dev), write one entry:

  requirements = [
    m.make_requirement {
      id        = "kebab-id",
      name      = "Human Name",
      env       = 'Both,           # 'Production | 'Development | 'Both
      kind      = 'Tool,           # 'Tool | 'Service | 'EnvVar | 'Infrastructure
      version   = "0.x",           # empty string if no constraint
      required  = true,
      impact    = "What breaks or degrades if this is absent.",
      provision = "How to install, set, or provision this.",
    },
  ],

Decision tree for env:

  • Only needed to build/test/lint → 'Development
  • Only needed when the service is deployed → 'Production
  • Needed in both contexts → 'Both

Decision tree for kind:

  • Binary on PATH (nu, nickel, cargo, just) → 'Tool
  • External running service (postgres, redis, nats) → 'Service
  • Environment variable that must be set (DATABASE_URL, API_KEY) → 'EnvVar
  • Filesystem layout, platform, or network topology → 'Infrastructure

What to include:

  • Runtime tools (nushell, nickel, just, docker)
  • Feature-gated services (database, message bus) — mark required = false if optional
  • Required env vars (especially secrets and URLs)
  • Repo layout dependencies (sibling checkouts, path dependencies in Cargo.toml)

What to exclude:

  • Standard Rust toolchain (assumed for all Rust projects)
  • OS-level libraries already declared in Cargo dependencies

Phase 5 — Populate critical_deps[]

List only external dependencies whose failure has a documented blast radius. This is not a full dependency audit — focus on load-bearing external contracts:

  critical_deps = [
    m.make_critical_dep {
      id             = "kebab-id",
      name           = "crate-or-service-name",
      ref            = "crates.io: foo / github.com/org/repo",
      used_for       = "Which capabilities or features depend on this.",
      failure_impact = "What breaks if this dep disappears or breaks its API contract.",
      mitigation     = "Feature flags, fallback builds, or alternative paths. Empty if none.",
    },
  ],

Candidates to consider:

  • HTTP framework (axum, actix-web) — entire API surface goes down
  • Serialization crates with unusual API stability guarantees
  • inventory or other linker-section crates — catalog surfaces go silent
  • Database driver — persistence layer failure
  • Any proc-macro crate the project defines (breakage cascades to all users)
  • External APIs called at runtime without a fallback

Do not include:

  • serde / tokio / tracing — industry-stable, ubiquitous, low blast-radius
  • Dev-only dependencies (test frameworks, criterion, cargo-nextest)
  • Transitive dependencies the project has no direct contract with

Phase 6 — Validate

cd {project_dir}

# Must export without errors
nickel export --import-path "$NICKEL_IMPORT_PATH" .ontology/manifest.ncl

# Confirm counts
nickel export --import-path "$NICKEL_IMPORT_PATH" .ontology/manifest.ncl \
  | jq '{description, capabilities: (.capabilities | length), requirements: (.requirements | length), critical_deps: (.critical_deps | length)}'

# Confirm nodes[] cross-references are valid
nickel export --import-path "$NICKEL_IMPORT_PATH" .ontology/manifest.ncl \
  | jq '[.capabilities[].nodes[]]' > /tmp/cap_nodes.json
nickel export --import-path "$NICKEL_IMPORT_PATH" .ontology/core.ncl \
  | jq '[.nodes[].id]' > /tmp/core_ids.json
# All capability node refs must appear in core_ids — check manually if jq diff not available

# Smoke test describe output
ontoref --actor developer describe requirements
ONTOREF_ACTOR=agent ontoref describe capabilities | from json | get capabilities | length

Checklist

  • description field populated (non-empty)
  • At least 1 capability entry with non-empty summary
  • nodes[] entries verified against .ontology/core.ncl node IDs
  • At least 1 requirement per environment context that applies (Production / Development)
  • All critical_deps have non-empty failure_impact
  • nickel export passes cleanly with no contract errors
  • describe requirements renders without errors
  • ONTOREF_ACTOR=agent ontoref describe capabilities | from json | get capabilities | length > 0