ontoref/reflection/templates/manifest-self-interrogation-prompt.md

254 lines
9.3 KiB
Markdown
Raw Normal View History

2026-03-29 00:19:56 +00:00
# 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:
```sh
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:
```sh
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`:
```nickel
description = "One sentence: what is this project and for whom.",
```
Confirm with:
```sh
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:
```nickel
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:
```sh
nickel export --import-path "$NICKEL_IMPORT_PATH" .ontology/core.ncl | jq '[.nodes[].id]'
```
- `adrs[]` must match IDs in `adrs/adr-*.ncl`. Verify:
```sh
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:
```nickel
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:
```nickel
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
```sh
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