1310 lines
59 KiB
Markdown
1310 lines
59 KiB
Markdown
# DocForge user manual
|
||
|
||
DocForge turns project-owned documentation and source projections into a validated graph that
|
||
people and AI agents can search, inspect, visualize, and change through reviewable proposals.
|
||
Canonical project files remain authoritative. The SQLite graph, previews, rendered manuals, and
|
||
viewer processes are derived and can be rebuilt.
|
||
|
||
This manual describes the DocForge 1.4.0 release candidate. The tagged `v1.0.0` baseline was the
|
||
first stable product release. Version 1.4.0 preserves its project-scoped graph, CLI and MCP query
|
||
surfaces, hash-approved proposal application, generic and project-owned adapters, declared
|
||
rendering, and Nodes/Flow/Web model while adding the maintained incremental, projection, adapter
|
||
SDK, recovery, and release proofs documented below.
|
||
|
||
Later incremental-compiler capabilities are additive. A Release 1 adapter with only
|
||
`load_projection()` remains valid and follows the same complete-rebuild path. No existing project
|
||
descriptor, canonical document, changeset, or adapter must be rewritten. Source-scoped caching and
|
||
lazy logic projections activate only for adapters that explicitly implement the optional
|
||
incremental methods while retaining the full loader as a fallback.
|
||
|
||
## Features
|
||
|
||
- Project-bound Markdown and TOML documentation graphs with stable node IDs.
|
||
- Deterministic validation for metadata, relationships, dependency cycles, paths, and limits.
|
||
- Disposable SQLite indexing with lexical search, filters, backlinks, dependencies, and impact.
|
||
- Bounded context profiles for AI agents, including source paths and content hashes.
|
||
- Isolated, optimistic changesets with create, update, move, delete, validation, diffs, and previews.
|
||
- Relationship-only changeset operations that do not rewrite node content.
|
||
- Hash-bound canonical application through both CLI and an explicitly enabled MCP tool.
|
||
- Opt-in incremental adapter extraction with reverse-dependency invalidation.
|
||
- Lazy function-scoped logic projections that do not densify the primary graph.
|
||
- Declared HTML render views. Arbitrary templates, render commands, and output paths are rejected.
|
||
- Separate versioned manual and portable graph plans, immutable packages, detached built-in
|
||
renderers, and validated receipts.
|
||
- Content-addressed portable Nodes/Flow/Web artifacts with receipt-only status and repair.
|
||
- Independent manual, portable-graph, and live-viewer policy.
|
||
- A loopback-only graph browser with Nodes, semantic Flow, and convergence Web views,
|
||
relationship keys, source inspection, branch-aware node hiding, panel resizing, zooming, and
|
||
managed idle shutdown.
|
||
- A generic Markdown/TOML adapter plus contracts for deterministic project-owned adapters.
|
||
- A public adapter SDK, optional Python/JavaScript/TypeScript/C++ reference integrations, and one
|
||
fixed read-only reference MCP binding.
|
||
|
||
DocForge does not run shell commands from documentation, mutate Git, build an application, deploy,
|
||
publish, choose a project globally, or cross project boundaries.
|
||
|
||
## Mental model
|
||
|
||
One `.docforge/project.toml` binds DocForge to one project root. The descriptor declares canonical
|
||
content roots, authority files, derived paths, proposal writers, relationship types, limits,
|
||
context profiles, and optional render views.
|
||
|
||
Canonical files own facts:
|
||
|
||
```text
|
||
canonical Markdown/TOML or adapter sources
|
||
↓ validate
|
||
disposable SQLite graph
|
||
├── query / compile context
|
||
├── ManualRenderPlanV1 → detached manual renderer → declared manual
|
||
├── GraphViewPlanV1 → detached graph renderer → portable Nodes/Flow/Web artifact
|
||
└── pinned index → managed live Nodes/Flow/Web/Logic viewer
|
||
↓
|
||
people and agents
|
||
↓ propose
|
||
isolated changeset + preview
|
||
↓ exact hash approval
|
||
canonical apply
|
||
↓
|
||
reindexed graph + declared renders
|
||
```
|
||
|
||
An apply operation is deliberately narrower than a general file editor. It accepts one validated
|
||
changeset ID and the exact SHA-256 changeset hash that was reviewed. It rejects stale canonical
|
||
sources, changed proposals, overlapping proposals, unauthorized families or operations, unsafe
|
||
paths, symlink escapes, and projections that do not round-trip through the project loader.
|
||
|
||
The generic adapter can serialize its Markdown and TOML nodes directly. A custom adapter must
|
||
provide its own canonical applier because only that project knows how a graph node maps back to its
|
||
source format.
|
||
|
||
Generic canonical application compare-and-swaps each target against its exact expected identity.
|
||
A concurrent create, update, or delete fails closed, rolls back when the exact displaced state is
|
||
still provable, or preserves recovery evidence without overwriting foreign data. Per-file
|
||
publication is atomic, but an application spanning several canonical files has no process-death
|
||
journal and does not claim crash atomicity across the group.
|
||
|
||
## Setup
|
||
|
||
### Requirements
|
||
|
||
- Python 3.12 or newer.
|
||
- [`uv`](https://docs.astral.sh/uv/) for the development environment.
|
||
- Node.js and npm for browser asset validation and strict Pyright checking.
|
||
|
||
Clone and verify DocForge:
|
||
|
||
```bash
|
||
git clone forgejo@repo.andraxion.net:administrator/DocForge2.git /absolute/path/DocForge2
|
||
cd /absolute/path/DocForge2
|
||
uv sync --group dev
|
||
npm ci
|
||
|
||
npx pyright
|
||
npm run lint:web
|
||
uv run ruff check src tests tools
|
||
uv run ruff format --check src tests tools
|
||
uv run pytest -q
|
||
```
|
||
|
||
Use the executables under `/absolute/path/DocForge/.venv/bin/` when DocForge is not installed into
|
||
the active shell environment.
|
||
|
||
For an installed distribution, choose only the language extras the project needs:
|
||
|
||
```bash
|
||
python -m pip install docforge
|
||
python -m pip install 'docforge[javascript]'
|
||
python -m pip install 'docforge[typescript]'
|
||
python -m pip install 'docforge[cpp]'
|
||
```
|
||
|
||
The base wheel contains the Python reference adapter and no Tree-sitter distribution. JavaScript,
|
||
TypeScript, and C++ require their matching optional extras. `docforge[languages]` installs all
|
||
three optional frontend groups.
|
||
|
||
Verify the four executable surfaces from the exact installed environment:
|
||
|
||
```bash
|
||
python -m docforge.cli --version
|
||
python -m docforge.mcp_server --version
|
||
python -m docforge.reference_mcp --version
|
||
python -m docforge.viewer_manager --version
|
||
```
|
||
|
||
For version 1.4.0 these report `docforge 1.4.0`, `docforge-mcp 1.4.0`,
|
||
`python -m docforge.reference_mcp 1.4.0`, and `docforge-viewer-manager 1.4.0`. Package metadata,
|
||
Python imports, generated generic and adapter configurations, and these commands share the same
|
||
version authority.
|
||
|
||
### Configure a reference source project
|
||
|
||
Reference adapters are a narrow alternative to the generic documentation descriptor. Create
|
||
`.docforge/reference-adapter.toml`:
|
||
|
||
```toml reference-adapter
|
||
schema_version = 1
|
||
project_id = "my-python-project"
|
||
title = "My Python Project"
|
||
language = "python"
|
||
source_roots = ["src"]
|
||
```
|
||
|
||
Start the fixed read-only server:
|
||
|
||
```bash
|
||
python -I -m docforge.reference_mcp \
|
||
--project-root /absolute/path/MyProject \
|
||
--capability-mode read
|
||
```
|
||
|
||
For C++, set `language = "cpp"` and add a project-relative
|
||
`compilation_database = "compile_commands.json"`. The database is inert bounded inventory; the
|
||
reference adapter does not execute its commands or compiler.
|
||
|
||
The reference integrations publish syntax and local static relationships only. They do not claim
|
||
resolved calls, types, inheritance, macro behavior, compiler include semantics, runtime behavior,
|
||
or semantic ownership. See [reference adapters](REFERENCE_ADAPTERS.md) for exact evidence and
|
||
limitations.
|
||
|
||
### Assess and onboard an unconfigured project
|
||
|
||
Run a read-only assessment before writing configuration:
|
||
|
||
```bash
|
||
docforge --project-root /absolute/path/MyProject onboard
|
||
```
|
||
|
||
The result reports detected languages, build evidence, likely documentation, existing
|
||
configuration, and capability status. Detection does not claim that a language frontend exists.
|
||
Limit the assessment with one or more `--language` options when needed.
|
||
|
||
Create, index, and render a generic starter manual explicitly:
|
||
|
||
```bash
|
||
docforge --project-root /absolute/path/MyProject onboard \
|
||
--language rust \
|
||
--scaffold \
|
||
--project-id my-project \
|
||
--title "My Project"
|
||
```
|
||
|
||
Scaffolding refuses to replace existing target files. It leaves source-graph status at
|
||
`adapter_required` until a project integration implements and proves the adapter contract.
|
||
See [Project onboarding](PROJECT_ONBOARDING.md) for the complete language-neutral checklist.
|
||
Use the [Language Adapter Authoring Guide](ADAPTER_AUTHORING_GUIDE.md) when implementing that
|
||
frontend. It covers stable identities, overlapping compiler evidence, deterministic ownership,
|
||
normalization, incremental equivalence, failure recovery, and the required proof matrix.
|
||
|
||
### Configure a generic project
|
||
|
||
Create `/absolute/path/MyProject/.docforge/project.toml`:
|
||
|
||
```toml
|
||
schema_version = 1
|
||
project_id = "my-project"
|
||
title = "My Project"
|
||
adapter = "generic"
|
||
|
||
[sources]
|
||
content_roots = ["Docs/Manual"]
|
||
authority_files = []
|
||
|
||
[derived]
|
||
cache_root = ".docforge/cache"
|
||
index = ".docforge/cache/index.sqlite3"
|
||
|
||
[changesets]
|
||
root = ".docforge/changesets"
|
||
|
||
[[changesets.writers]]
|
||
id = "project-editor"
|
||
families = ["architecture", "system", "operations", "roadmap"]
|
||
operations = ["create", "update", "move", "delete"]
|
||
|
||
[render]
|
||
template_root = "Docs/Templates"
|
||
preview_root = ".docforge/previews"
|
||
|
||
[[render.views]]
|
||
id = "manual"
|
||
renderer = "generic_html"
|
||
template = "manual.html"
|
||
output = "Docs/Rendered/Manual.html"
|
||
title = "My Project Manual"
|
||
families = ["architecture", "system", "operations", "roadmap"]
|
||
|
||
[graph_render]
|
||
output_root = ".docforge/portable-graph"
|
||
|
||
[[graph_render.views]]
|
||
id = "architecture"
|
||
renderer = "portable_graph_html"
|
||
output = "architecture.html"
|
||
title = "Architecture"
|
||
root = "architecture.overview"
|
||
initial_mode = "web"
|
||
depth = 3
|
||
max_nodes = 250
|
||
max_edges = 1000
|
||
max_work = 100000
|
||
families = ["architecture", "system"]
|
||
relations = ["depends_on", "owns", "calls", "reads", "writes", "tested_by", "relates_to"]
|
||
authorities = []
|
||
statuses = ["current", "active", "verified"]
|
||
tags = []
|
||
include_logic = false
|
||
|
||
[graph]
|
||
allowed_relations = ["depends_on", "owns", "calls", "reads", "writes", "tested_by", "relates_to"]
|
||
|
||
[limits]
|
||
max_source_bytes = 500000
|
||
max_nodes = 10000
|
||
max_query_chars = 500
|
||
max_results = 100
|
||
max_traversal_depth = 6
|
||
max_context_tokens = 12000
|
||
max_changesets = 100
|
||
max_changeset_operations = 100
|
||
max_changeset_bytes = 1000000
|
||
|
||
[[profiles]]
|
||
id = "development"
|
||
families = ["architecture", "system", "operations", "roadmap"]
|
||
statuses = ["current", "active", "verified"]
|
||
required_nodes = ["architecture.overview"]
|
||
token_budget = 8000
|
||
dependency_depth = 3
|
||
```
|
||
|
||
Every path is resolved against the explicit project root. Canonical content, derived cache, and
|
||
changeset roots must not overlap.
|
||
|
||
### Add a Markdown node
|
||
|
||
Create `Docs/Manual/architecture-overview.md`:
|
||
|
||
```markdown
|
||
+++
|
||
schema_version = 1
|
||
id = "architecture.overview"
|
||
title = "Architecture overview"
|
||
family = "architecture"
|
||
authority = "authoritative"
|
||
status = "current"
|
||
tags = ["architecture", "ownership"]
|
||
summary = "Defines the top-level systems and ownership boundaries."
|
||
depends_on = ["system.persistence"]
|
||
+++
|
||
|
||
# Architecture overview
|
||
|
||
Describe the project’s systems, authorities, persistence owners, runtime flow, failure behavior,
|
||
tests, and operational entry points.
|
||
```
|
||
|
||
Each Markdown file contains one node. A TOML source may contain multiple `[[nodes]]` records. TOML
|
||
nodes need stable `source_anchor` values when proposals may create or move records within the file.
|
||
Every relationship target must exist.
|
||
|
||
### Build the graph
|
||
|
||
```bash
|
||
PROJECT=/absolute/path/MyProject
|
||
DOCFORGE=/absolute/path/DocForge/.venv/bin/docforge
|
||
|
||
"$DOCFORGE" --project-root "$PROJECT" validate
|
||
"$DOCFORGE" --project-root "$PROJECT" reindex
|
||
"$DOCFORGE" --project-root "$PROJECT" context development
|
||
```
|
||
|
||
`reindex` builds the SQLite graph and immediately checks its identity. Run it after canonical
|
||
documentation or adapter sources change.
|
||
|
||
### Install the viewer manager
|
||
|
||
Install the native per-user supervisor once:
|
||
|
||
```bash
|
||
docforge-viewer-manager install-user-service
|
||
```
|
||
|
||
Linux uses `systemd --user`, macOS uses a LaunchAgent, and Windows uses Task Scheduler. If the
|
||
virtual environment moves, reinstall the service so it points at the current Python interpreter.
|
||
|
||
For a temporary foreground manager:
|
||
|
||
```bash
|
||
docforge-viewer-manager serve
|
||
```
|
||
|
||
Open a project graph without Codex:
|
||
|
||
```bash
|
||
docforge --project-root "$PROJECT" visualize
|
||
docforge --project-root "$PROJECT" visualize --node architecture.overview
|
||
docforge --project-root "$PROJECT" visualize --query persistence
|
||
```
|
||
|
||
The command opens the default browser. Add `--no-open` when a script only needs the returned JSON
|
||
URL. Use `visualization-status` and `visualization-stop` to inspect or stop the project viewer.
|
||
|
||
Status separates the worker lifecycle from snapshot freshness. A worker may remain `running` while
|
||
`snapshot_state` is `stale`; it will not be reused by the next `visualize` call. `freshness.index`
|
||
checks the exact pinned index publication with file identity only. `freshness.source` compares the
|
||
cheap project generation when the project can prove one. Unavailable proof is `unknown`, never
|
||
silently `current`. Status does not load project content, open SQLite, rebuild the index, or renew
|
||
browser activity.
|
||
|
||
The freshness protocol requires viewer manager version 2. After upgrading an already running
|
||
installation, rerun `docforge-viewer-manager install-user-service` or restart the foreground
|
||
manager before requesting status.
|
||
|
||
## Visualization usage
|
||
|
||
- Left-click a node for its compact descriptor.
|
||
- Right-click a node for the full inspector.
|
||
- Use **Open source** to read the node’s project-confined source at its anchor.
|
||
- Use **Explore neighborhood** to make a node the new focus.
|
||
- Use the mouse wheel or viewport buttons to zoom. Drag the canvas to pan. Press Space to center
|
||
the selected node.
|
||
|
||
### Nodes: bounded neighborhood
|
||
|
||
**Nodes** answers: “What is immediately related to this thing?”
|
||
|
||
DocForge starts at the focus and traverses every stored incoming and outgoing relationship up to
|
||
the selected depth and fixed edge limit. The graph preserves the relationships exactly as the
|
||
index stores them. It does not reinterpret direction or exclude contextual relationships.
|
||
|
||
The focus appears at the center. Every other card is categorized by the relationship that explains
|
||
its contribution to the focus: Structure, Behavior, Dependency, Execution, Data, Evidence,
|
||
Context, or Related. This is the broadest view and is useful for inspecting raw adapter output,
|
||
discovering nearby nodes, and choosing a better focus. It can also be the noisiest view because
|
||
containment, documentation, dependencies, calls, imports, and other relationship types may all
|
||
appear together.
|
||
|
||
In Nodes, **Hide node** removes that node and its incident edges from the presentation. It does not
|
||
remove other nodes merely because they become disconnected.
|
||
|
||
### Flow: semantic paths into the focus
|
||
|
||
**Flow** answers: “What origins and prerequisites lead to this thing?”
|
||
|
||
Flow builds bounded semantic paths whose destination is the focus. Structural and execution
|
||
relationships already aimed at the consumer keep their stored direction. Prerequisite-style
|
||
relationships are reversed for presentation so arrows consistently point toward the thing being
|
||
explained:
|
||
|
||
- `defined_in`, `inherits`, and `imports` become definition, base-class, and imported-module
|
||
contributions.
|
||
- `depends_on` and `reads` become dependency and data-source contributions.
|
||
- `tested_by` becomes a test path into the exercised node.
|
||
|
||
For example, a method can appear as:
|
||
|
||
```text
|
||
tests package → test module → test class → test method
|
||
```
|
||
|
||
The displayed reversal is a visualization rule only. It does not mutate the canonical
|
||
relationship or derived index. Context-only relationships such as `documents`, `governs`, and
|
||
`relates_to` are omitted so Flow remains a focused origin-to-destination explanation.
|
||
|
||
### Web: convergence and makeup
|
||
|
||
**Web** answers: “What makes up this thing, and what paths converge on it?”
|
||
|
||
Web starts with the same semantic contributor direction as Flow, then includes contextual
|
||
relationships that Flow intentionally omits. It can show callers, containers, imports,
|
||
dependencies, evidence, documentation context, and other contributors converging on the focus.
|
||
It also presents direct relationships owned by the focus as adjacent contributor branches,
|
||
including supported `calls`, `contains`, `defines`, `dispatches_to`, `implemented_by`, `launches`,
|
||
`writes`, and `activates` relationships.
|
||
|
||
This makes classes and methods useful graph nodes rather than labels attached to a file. A class
|
||
can show its containing module, base class, callers, tests, and methods. A method can show the
|
||
package and class path that contains it alongside imported helpers, dependencies, callers, and
|
||
evidence. Every displayed path is oriented toward the focused node.
|
||
|
||
Adjacent traversal is deliberately bounded. After DocForge includes a direct member or execution
|
||
dependency owned by the focus, it continues toward that branch rather than fanning back out
|
||
through unrelated siblings. Depth and edge limits provide a second guard against an unbounded web.
|
||
|
||
### Logic: possible control paths
|
||
|
||
**Logic** answers: “What decisions and actions can occur inside this function or method?”
|
||
|
||
Logic appears when the focused node owns a function-scoped `LogicProjection`. It loads that
|
||
projection on demand instead of adding statements and conditions to the primary architecture
|
||
graph. The view presents:
|
||
|
||
- **Entry** and **Exit** terminals.
|
||
- **Decision** cards for `if`, `elif`, compound booleans, loop conditions, `match` cases, and
|
||
assertions.
|
||
- **Action** cards for executable statement blocks and calls.
|
||
- **Control** cards for loops, `break`, and `continue`.
|
||
- **Convergence** cards where alternate paths rejoin, including decision, case, loop-exit, and
|
||
exception convergence.
|
||
- **Terminal** cards for returns and raised exceptions.
|
||
|
||
Edges use explicit labels and independent colors for `TRUE`, `FALSE`, `NEXT`, `CASE`, `LOOP`,
|
||
`EXCEPTION`, `RETURN`, `RAISE`, `BREAK`, and `CONTINUE`. Long predicates wrap on the card. The full
|
||
expression and source anchor remain available through inspection and source navigation.
|
||
|
||
The built-in analyzers cover Python, JavaScript, and C++. Python uses the standard-library AST.
|
||
JavaScript and C++ use pinned Tree-sitter grammars behind the same language-neutral
|
||
`LogicProjection` contract. Tree-sitter handles concrete syntax; DocForge keeps a thin
|
||
language-specific control-flow profile for constructs such as conditions, loops, cases,
|
||
exceptions, returns, and short-circuit operators. Adding a language therefore requires a grammar
|
||
and a semantic profile, not a new visualization or database design.
|
||
|
||
Logic is static analysis. It shows paths the indexed source permits, not the branch that ran for a
|
||
particular request or the runtime value of a boolean. Dynamic dispatch, reflection, generated
|
||
behavior, and values returned by other processes may require runtime tracing to resolve.
|
||
|
||
### Finding the right node
|
||
|
||
The left panel combines independent filters rather than forcing users to scan the complete node
|
||
list:
|
||
|
||
- **Text** searches indexed titles, summaries, and content.
|
||
- **Family** selects the project-defined family.
|
||
- **Node type** selects callables or an exact indexed kind such as function, method, class, route,
|
||
test, module, or document.
|
||
- **Language** selects an indexed language tag such as Python, JavaScript, or C++.
|
||
- **Capability** selects nodes with source navigation or an available Logic projection.
|
||
|
||
Quick presets select common combinations for Logic-ready nodes, Python callables, tests, routes,
|
||
and documentation. Filters compose, so `JavaScript` plus `Logic available` lists only JavaScript
|
||
functions that can open Logic. Result cards show the readable leaf name, kind, language, path, and
|
||
source anchor. Full identities remain in the tooltip and inspector.
|
||
|
||
Selecting any canvas node highlights its directly connected nodes and the exact edges between
|
||
them. Other nodes and edges remain visible at reduced opacity. This local trace works in Nodes,
|
||
Flow, Web, and Logic without changing the root or querying a different graph.
|
||
|
||
### Reading graph cards
|
||
|
||
The canvas presents nodes as compact semantic cards rather than anonymous circles:
|
||
|
||
- **Focus** identifies the node being explained.
|
||
- **Structure** identifies packages, modules, classes, methods, definitions, and other containment
|
||
paths that establish where the focus exists.
|
||
- **Behavior** identifies base classes, derived classes, and implementation relationships.
|
||
- **Dependency** identifies imported modules and required services or helpers.
|
||
- **Execution** identifies callers, dispatchers, launchers, activators, and focus-owned execution
|
||
branches.
|
||
- **Data** identifies values or resources read and written.
|
||
- **Evidence** identifies tests, verification, governing rules, and documentation.
|
||
- **Context** identifies descriptive relationships that do not imply execution or ownership.
|
||
- **Related** is the deterministic fallback for adapter-specific relationships that do not fit a
|
||
built-in category.
|
||
|
||
The colored rail, category badge, edge style, and relationship label provide separate visual cues.
|
||
Color is not the only signal. Cards also display the node kind, such as `Test class` or
|
||
`Test method`.
|
||
|
||
Canvas cards use the readable leaf name. For example,
|
||
`tests.test_settings.SettingsTests.test_default_settings_load` appears as
|
||
`test_default_settings_load`, while `tests.test_settings` appears as `test_settings`. Long leaf
|
||
names wrap at identifier boundaries instead of being truncated. The complete qualified title and
|
||
stable node ID remain available in the pointer tooltip, compact descriptor, and full inspector, so
|
||
the shorter canvas label never changes identity or loses information.
|
||
|
||
### Hiding nodes and pruning ancestors
|
||
|
||
Hidden nodes are browser presentation state. Hiding never changes canonical files, the derived
|
||
index, or future graph queries. The focus cannot be hidden; focus another node first.
|
||
|
||
- In **Nodes**, hiding removes only the selected node and its incident edges.
|
||
- In **Flow** and **Web**, hiding removes the selected node, then prunes every upstream ancestor
|
||
whose only remaining route to the focus passed through it.
|
||
- In **Logic**, hiding removes the selected control-flow step and inserts an `omitted` bridge
|
||
between its visible predecessors and successors. This preserves the readable path without
|
||
pretending the hidden code disappeared from the indexed source.
|
||
- Descendant nodes between the hidden node and the focus remain visible.
|
||
- Ancestors with another valid path to the focus remain visible through that alternate path.
|
||
- The status line reports how many nodes were hidden or isolated.
|
||
- **Restore hidden** clears the hidden-node set and rebuilds the complete current view.
|
||
|
||
This behavior lets a user cut away a noisy or irrelevant branch without losing the useful
|
||
downstream chain that explains how the remaining nodes reach the focus.
|
||
|
||
Source navigation depends on adapter evidence. Numeric anchors, line-style anchors such as `L120`,
|
||
TOML `node-N` anchors, heading slugs, and searchable text anchors are recognized. If a custom
|
||
adapter supplies only a path or a vague symbol, the source viewer opens the file and falls back to
|
||
the closest match or first line.
|
||
|
||
## CLI usage
|
||
|
||
Every command emits deterministic JSON:
|
||
|
||
```bash
|
||
docforge --project-root /absolute/path/MyProject <command>
|
||
```
|
||
|
||
The sections below group common workflows. The implementation-derived list of all 28 current
|
||
commands, exact invocations, 36 generic MCP tools, arguments, and input-schema hashes is the
|
||
[generated command reference](COMMAND_REFERENCE.md).
|
||
|
||
### Project and index commands
|
||
|
||
```text
|
||
info
|
||
validate
|
||
build
|
||
reindex
|
||
sync
|
||
check
|
||
validate-index
|
||
```
|
||
|
||
- `info` reports the project binding and index health.
|
||
- `validate` validates current canonical sources without requiring an index.
|
||
- `build` rebuilds the disposable index.
|
||
- `reindex` rebuilds and checks the index in one operation.
|
||
- `sync` checks the index and rebuilds it only when it is missing, stale, or invalid.
|
||
- `check` and `validate-index` verify that the existing index matches current sources.
|
||
|
||
### Query commands
|
||
|
||
```text
|
||
show NODE_ID
|
||
search QUERY [--limit N]
|
||
filter [--family X] [--authority X] [--status X] [--tag X] [--limit N]
|
||
backlinks NODE_ID [--relation RELATION] [--limit N]
|
||
dependencies NODE_ID [--depth N] [--limit N]
|
||
impact NODE_ID [--depth N] [--limit N]
|
||
context PROFILE [--budget N] [--limit N] [--cursor OPAQUE]
|
||
generation-diff [--limit N] [--cursor OPAQUE]
|
||
```
|
||
|
||
`generation-diff` returns the latest verified primary-graph transition. It is not a history query.
|
||
Current results carry a version-1 page, a `receipt_header` bound to the complete stored receipt by
|
||
`stored_receipt_hash`, and one top-level pagination cursor. Missing, unsafe, stale, corrupt, or
|
||
unprovable disposable evidence is reported as a non-repairing receipt status. The command never
|
||
builds or repairs the index.
|
||
|
||
### Render and proposal commands
|
||
|
||
```text
|
||
render-status [VIEW_ID] [--deep]
|
||
render VIEW_ID
|
||
graph-plan VIEW_ID
|
||
graph-render VIEW_ID
|
||
graph-render-status [VIEW_ID]
|
||
preview CHANGESET_ID VIEW_ID
|
||
apply CHANGESET_ID --changeset-hash SHA256 --applier WRITER_ID
|
||
```
|
||
|
||
`graph-plan` validates and returns one declared `GraphViewPlanV1` without publishing. A portable
|
||
view must select exactly one stable `root` or metadata-only lexical `query`. It may use only Nodes,
|
||
Flow, or Web as `initial_mode`; portable version 1 excludes function-scoped Logic.
|
||
|
||
`graph-render` explicitly publishes the declared static artifact, content-addressed renderer
|
||
evidence, and generation/view manifest. `graph-render-status` verifies only bounded committed
|
||
evidence and never plans or renders. Portable publication is a local CLI action.
|
||
|
||
The CLI apply command supports the generic adapter. It verifies that the configured writer owns the
|
||
changeset, applies the exact reviewed hash, rebuilds the index, checks it, and regenerates every
|
||
declared manual render when manual policy is `auto`. It does not publish portable graphs, commit,
|
||
or push the result.
|
||
|
||
### Viewer commands
|
||
|
||
```text
|
||
visualize [--node NODE_ID | --query QUERY] [--depth N] [--no-open]
|
||
visualization-status
|
||
visualization-stop
|
||
```
|
||
|
||
### Client configuration and doctor
|
||
|
||
Preview one deterministic standalone client fragment:
|
||
|
||
```bash
|
||
docforge configure codex --project /absolute/path/MyProject
|
||
docforge configure claude --project /absolute/path/MyProject
|
||
docforge configure openclaw --project /absolute/path/MyProject
|
||
```
|
||
|
||
Preview is the default. Add `--output /absolute/path/fragment` to create a new private fragment in
|
||
an existing real directory. Publication is create-only. DocForge accepts an identical existing
|
||
private single-link file as unchanged, but it never merges, replaces, broadens permissions, or
|
||
follows a symlink. Descriptor, parent, and target identities are revalidated across the
|
||
publication commit.
|
||
|
||
The generated command uses the exact current Python interpreter with isolated module startup.
|
||
Generation first proves that this interpreter can import `docforge.mcp_server`. The result binds
|
||
the project root, effective policy, arguments, artifact bytes, and all hashes. It copies no ambient
|
||
environment values.
|
||
|
||
Select authority explicitly:
|
||
|
||
```bash
|
||
docforge configure codex \
|
||
--project /absolute/path/MyProject \
|
||
--capability-mode proposal \
|
||
--proposal-writer project-editor
|
||
|
||
docforge configure codex \
|
||
--project /absolute/path/MyProject \
|
||
--capability-mode application \
|
||
--proposal-writer project-editor \
|
||
--canonical-applier project-editor
|
||
```
|
||
|
||
Read mode is the default. Proposal and application modes fail closed unless the descriptor
|
||
declares the named writer, and application requires the same writer/applier identity. Add
|
||
`--no-ast` to preserve the no-AST binding. Generic CLI generation refuses project-owned adapters
|
||
because it cannot safely reconstruct their composition.
|
||
|
||
A custom adapter owner supplies the already constructed project and immutable launcher through the
|
||
Python API:
|
||
|
||
```python
|
||
from docforge.adapter_launcher import AdapterLauncherV1
|
||
from docforge.client_config import generate_adapter_client_configuration
|
||
|
||
launcher = AdapterLauncherV1.for_project(
|
||
project,
|
||
module="my_project_docforge",
|
||
)
|
||
fragment = generate_adapter_client_configuration(
|
||
project,
|
||
launcher,
|
||
"codex",
|
||
capability_mode="read",
|
||
)
|
||
```
|
||
|
||
The top-level module must be installed for the exact isolated Python environment and resolve to a
|
||
regular file inside the project root. The fixed `docforge.reference_mcp` module is the only trusted
|
||
dotted exception. Generation probes resolution without importing the custom module, binds current
|
||
source availability and policy, and emits no arbitrary command, arguments, working directory, or
|
||
environment.
|
||
|
||
Select projection behavior independently:
|
||
|
||
```bash
|
||
docforge configure codex \
|
||
--project /absolute/path/MyProject \
|
||
--manual-render-policy explicit \
|
||
--portable-graph-policy disabled \
|
||
--live-viewer-policy on-demand
|
||
```
|
||
|
||
The generated version-1 configuration result carries an additive version-2 `projection_policy`,
|
||
its hash, projection availability, and the exact descriptor hash. Omitted default selectors are
|
||
validated against that descriptor rather than trusted as self-reported output.
|
||
|
||
Inspect one configured client binding:
|
||
|
||
```bash
|
||
docforge doctor --client codex --project /absolute/path/MyProject
|
||
docforge doctor --client codex \
|
||
--project /absolute/path/MyProject \
|
||
--config /absolute/path/config.toml \
|
||
--server-name my-project-docforge
|
||
```
|
||
|
||
Doctor returns `healthy`, `degraded`, or `unhealthy` with exit codes 0, 1, or 2. Its fixed
|
||
version-1 inventory checks project and descriptor binding, the client driver and entry, executable
|
||
and arguments, project root, effective policy, no-AST state, timeouts, environment-key names,
|
||
tool-filter representation, and stat-only index presence.
|
||
|
||
Doctor is intentionally not a connection test. It never loads canonical sources, opens SQLite,
|
||
starts MCP, executes the configured command, synchronizes, builds, renders, starts a viewer, or
|
||
writes configuration. Claude timeout representation and client filtering that cannot be proved
|
||
locally remain explicit warnings.
|
||
|
||
## Independent projection behavior
|
||
|
||
Manual and portable graph renderers consume immutable, path-free packages. A package binds one
|
||
generation-pinned plan, inert assets, fixed component versions, a built-in renderer identity, and
|
||
an exact artifact inventory. The detached child cannot select nodes, open the project or index,
|
||
choose a publication path, execute project code, or mutate canonical facts.
|
||
|
||
Child startup is fixed to isolated Python, a private module entrypoint, a trusted working
|
||
directory, and a sanitized environment. One request and response use canonical newline-terminated
|
||
JSON. The request, response, receipt, execution time, and disk-spooled stdout are bounded. Actual
|
||
artifact transfer is capped at 20,000,000 bytes even when the descriptor retains a larger
|
||
`max_render_bytes` compatibility value.
|
||
|
||
Manual fragment records are disposable semantic cache entries. On a cold miss, DocForge performs a
|
||
trusted full detached render, extracts candidate page fragments, and compares fragment-assisted
|
||
output byte-for-byte before publishing records. On a warm hit, the worker recomputes each expected
|
||
page fragment before accepting cached bytes. Corrupt, forged, stale, individually oversized, or
|
||
aggregate-oversized records fall back to the full oracle. Fragment reuse is currently a correctness
|
||
and recovery boundary, not a promised speedup.
|
||
|
||
Projection policy version 2 is:
|
||
|
||
```text
|
||
manual: auto | explicit | disabled
|
||
portable_graph: explicit | disabled
|
||
live_viewer: on-demand | disabled
|
||
```
|
||
|
||
For ordinary CLI commands, place the corresponding global flag before the subcommand:
|
||
|
||
```bash
|
||
docforge --project-root "$PROJECT" --manual-render-policy disabled render manual
|
||
docforge --project-root "$PROJECT" --portable-graph-policy disabled graph-plan architecture
|
||
docforge --project-root "$PROJECT" --live-viewer-policy disabled visualize
|
||
```
|
||
|
||
An active operation blocked by policy returns `projection_policy_forbids_operation` before hidden
|
||
work. Manual and portable receipt-only status remain available. Viewer status and explicit stop
|
||
remain available when viewer start is disabled.
|
||
|
||
A non-disabled projection also requires its declared configuration or runtime. Manual `explicit`
|
||
requires manual render configuration. Manual `auto` additionally requires canonical application in
|
||
the current operation or server capability. Portable graph `explicit` requires portable graph
|
||
render configuration, and live viewer `on-demand` requires its runtime. An unavailable selection
|
||
returns `projection_policy_unavailable` before work begins. In particular, ordinary CLI `render`
|
||
operations cannot select manual `auto`; use `explicit`, or let a configured canonical `apply`
|
||
operation own automatic regeneration.
|
||
|
||
## MCP usage
|
||
|
||
Run one MCP server per project with absolute paths:
|
||
|
||
```bash
|
||
docforge-mcp \
|
||
--project-root /absolute/path/MyProject \
|
||
--proposal-writer project-editor
|
||
```
|
||
|
||
Omit `--proposal-writer` when the MCP client should not create or append proposals.
|
||
|
||
For `.docforge/reference-adapter.toml`, use the fixed `docforge.reference_mcp` command shown in
|
||
[setup](#configure-a-reference-source-project). It exposes exactly the 21 read tools and never
|
||
registers proposal or application tools.
|
||
|
||
Select the session's declared surface explicitly when useful:
|
||
|
||
```bash
|
||
docforge-mcp \
|
||
--project-root /absolute/path/MyProject \
|
||
--capability-mode read \
|
||
--manual-render-policy explicit \
|
||
--portable-graph-policy explicit \
|
||
--live-viewer-policy on-demand
|
||
```
|
||
|
||
Supported modes are `read`, `proposal`, `application`, and `operator`. Existing startup defaults
|
||
remain compatible. Capability mode describes the registered surface; bootstrap separately reports
|
||
whether a configured writer or applier actually grants mutation access. Application mode refuses
|
||
startup without a canonical applier. Operator mode is reserved and currently adds no tools.
|
||
|
||
Add `--diagnostics` when profiling a development or benchmark session. Each MCP response then
|
||
includes bounded stage timings and compiler-work counters. The same flag is available on
|
||
`docforge`. Diagnostics are disabled by default, record no project content or paths, and never
|
||
displace a primary MCP result that already needs the configured output budget.
|
||
|
||
To expose canonical application, add a separate explicit startup gate:
|
||
|
||
```bash
|
||
docforge-mcp \
|
||
--project-root /absolute/path/MyProject \
|
||
--proposal-writer project-editor \
|
||
--canonical-applier project-editor
|
||
```
|
||
|
||
Without `--canonical-applier`, `docforge_apply_changeset` is not registered. The flag is an
|
||
identity, not a command. The changeset creator, configured writer, and canonical applier must agree.
|
||
|
||
Call `docforge_bootstrap` first. Its version-1 `session_contract` contains the fixed binding,
|
||
current graph generation, effective policy, actual capabilities, render policies, prohibitions,
|
||
and a recommended first operation. The result also carries the independently composed version-2
|
||
`projection_policy` and hash. Workflow guidance does not recommend registration or application
|
||
when those startup capabilities are unavailable.
|
||
|
||
Example MCP client configuration:
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"my-project-docforge": {
|
||
"command": "/absolute/path/DocForge/.venv/bin/docforge-mcp",
|
||
"args": [
|
||
"--project-root",
|
||
"/absolute/path/MyProject",
|
||
"--proposal-writer",
|
||
"project-editor",
|
||
"--canonical-applier",
|
||
"project-editor"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### Read tools
|
||
|
||
- `docforge_bootstrap`
|
||
- `docforge_sync`
|
||
- `docforge_project_info`
|
||
- `docforge_get_contract`
|
||
- `docforge_get_node`
|
||
- `docforge_get_logic`
|
||
- `docforge_search`
|
||
- `docforge_filter_nodes`
|
||
- `docforge_backlinks`
|
||
- `docforge_dependencies`
|
||
- `docforge_impact`
|
||
- `docforge_get_context`
|
||
- `docforge_get_task_context`
|
||
- `docforge_validate_project`
|
||
- `docforge_render_status`
|
||
- `docforge_graph_plan`
|
||
- `docforge_graph_render_status`
|
||
- `docforge_visualize`
|
||
- `docforge_visualization_status`
|
||
- `docforge_stop_visualization`
|
||
- `docforge_get_generation_diff`
|
||
|
||
MCP graph plan and status are read-only. MCP does not expose portable graph publication; use the
|
||
explicit local `graph-render` CLI command.
|
||
|
||
### Proposal tools
|
||
|
||
- `docforge_create_changeset`
|
||
- `docforge_register_changes`
|
||
- `docforge_list_changesets`
|
||
- `docforge_get_changeset`
|
||
- `docforge_rebase_changeset`
|
||
- `docforge_abandon_changeset`
|
||
- `docforge_propose_node_create`
|
||
- `docforge_propose_node_update`
|
||
- `docforge_propose_node_move`
|
||
- `docforge_propose_relationship_update`
|
||
- `docforge_propose_node_delete`
|
||
- `docforge_validate_changeset`
|
||
- `docforge_get_changeset_diff`
|
||
- `docforge_preview_changeset`
|
||
|
||
### Application tool
|
||
|
||
- `docforge_apply_changeset`
|
||
|
||
The application call requires `changeset_id` and `expected_changeset_hash`. Always retrieve and
|
||
inspect the final diff after the last proposal mutation. Apply that exact hash. A proposal mutation
|
||
creates a new hash, so an earlier approval cannot silently apply later content.
|
||
|
||
Use `docforge_get_task_context` when an agent needs one bounded task-shaped intake instead of a
|
||
named profile. Choose `task_kind` from `change`, `implementation`, `failure`, `ownership`, `test`,
|
||
`operation`, or `release`. Supply `focus_node_id` when the stable node is known. Without it,
|
||
DocForge performs a bounded lexical focus search and refuses a tied best match instead of silently
|
||
choosing one.
|
||
|
||
The returned version-1 capsule includes:
|
||
|
||
- The exact project, adapter, source generation, effective policy, request, and retrieval-plan
|
||
hashes.
|
||
- Ordered focus and related evidence with source paths, content hashes, graph paths, and all
|
||
qualifying relationship reasons observed during the bounded traversal.
|
||
- Explicit evidence gaps and omissions, including whether a check completed.
|
||
- Provenance limitations for facts that the current graph does not carry, such as extractor
|
||
identity, observation time, and source provenance for relationships.
|
||
|
||
Project descriptors still own the valid relation vocabulary. The planner recognizes a fixed alias
|
||
map for structure, implementation, dependency, execution, data, evidence, and context. Any other
|
||
valid project relation is returned unchanged as `unclassified`; it is never assigned guessed task
|
||
semantics.
|
||
|
||
A relationship inside `relationship_path` describes the direction traveled from the preceding
|
||
node. A relationship inside `relationship_reasons` describes direction from the evidence item
|
||
itself. This keeps stored source and target identity exact while making each evidence explanation
|
||
locally readable.
|
||
|
||
Task context never exceeds 1,000 evidence items, 100,000 examined candidate edges, or 10,000 task
|
||
query characters, even when a project configures broader general limits. An edge-work or
|
||
unclassified-relation ceiling appears as an explicit omission rather than an unbounded response.
|
||
|
||
Use `docforge_get_generation_diff` after synchronization or a completed implementation slice to
|
||
inspect the one latest verified primary-graph transition. The version-1 receipt reports exact
|
||
added, removed, and changed node counts plus added and removed edge counts. Retained node details
|
||
identify changed fields and before/after hashes and source paths. Edge details retain the exact raw
|
||
relation triple. The receipt stores no source text, rendered content, Logic identities, or
|
||
historical sequence.
|
||
|
||
The first successful publication is an explicit baseline and does not claim every current node was
|
||
added. A corrupt, foreign, unsafe, or unavailable predecessor produces an unavailable comparison
|
||
rather than fabricated removals. A same-generation reindex preserves the latest meaningful
|
||
transition. Each later real transition atomically replaces the single disposable receipt.
|
||
|
||
Generation-diff reads use only the bounded receipt, stable file identities, and an adapter's cheap
|
||
source-generation proof. They do not open SQLite, load a complete adapter projection, parse source,
|
||
synchronize, build, or repair. Legacy adapters without cheap identity report `unknown`. Missing,
|
||
corrupt, foreign, oversized, or concurrently changed receipts report an explicit receipt state and
|
||
do not trigger hidden recovery.
|
||
|
||
Recommended release-candidate sequence:
|
||
|
||
1. Call `docforge_bootstrap`. It synchronizes derived state and reports the exact fixed binding.
|
||
2. Read only the relevant canonical context, implementation, configuration, tests, and release
|
||
rules.
|
||
3. Record the expected documentation impact in the working plan. Do not create or apply a
|
||
changeset yet.
|
||
4. Implement and run focused checks iteratively. Canonical documentation remains read-only during
|
||
this loop.
|
||
5. Freeze one release candidate after implementation stops changing.
|
||
6. Run the complete project gate, deployment preflight, candidate deployment, live checks, data
|
||
integrity checks, and release-identity checks.
|
||
7. If candidate validation fails, return to implementation. Do not document the failed candidate.
|
||
8. Call `docforge_sync` once after the candidate is green.
|
||
9. Call `docforge_register_changes` once with the complete operation list for every affected
|
||
canonical node.
|
||
10. Inspect the structured diff and every required preview.
|
||
11. Obtain human approval for the final changeset hash when required by the client workflow.
|
||
12. Call `docforge_apply_changeset` with that exact hash.
|
||
13. Run documentation-only validation and render checks.
|
||
14. Call `docforge_bootstrap` to verify the new canonical and derived identity.
|
||
15. Commit, tag, and publish the final revision containing both the verified implementation and
|
||
canonical documentation.
|
||
|
||
This cadence separates documentation intake from documentation publication. It avoids repeatedly
|
||
rewriting the manual around intermediate implementation states. One second documentation write is
|
||
allowed only for a narrow evidence correction that could not exist before deployment. If a late
|
||
check exposes an implementation defect, abandon or rebase the pending proposal and return to the
|
||
implementation loop.
|
||
|
||
The older create-and-append tools remain supported for interactive proposal construction.
|
||
`docforge_register_changes` avoids intermediate empty changesets and caller-managed hash chaining.
|
||
For update, move, and delete operations it captures the synchronized current node hash when
|
||
`expected_content_hash` is omitted.
|
||
|
||
MCP mutations are preflighted against the configured response limit. Small mutations keep their
|
||
full response. Large successful mutations return a compact or minimum version-1 receipt with
|
||
`mutation_committed = true` and the exact current changeset hash. A preflight size failure has
|
||
`mutation_committed = false`; it is safe to correct the request or policy before retrying. A
|
||
committed mutation is never reported as `result_too_large`.
|
||
|
||
Active changeset listing includes draft and ready proposals. Stale work remains available through
|
||
an explicit `status="stale"` query for rebase decisions. Applied and abandoned proposals are
|
||
terminal history, remain available by status or history request, and no longer block new proposals
|
||
against the same canonical base.
|
||
|
||
Context and changeset reads use version-1 continuation receipts when their evidence exceeds one
|
||
page. Follow `pagination.next_cursor` with the same tool and semantic arguments until
|
||
`pagination.has_more` is false. Page size may change between calls. Treat the cursor as opaque.
|
||
It is bound to the project, adapter, source generation, query, exact changeset hash, and collection
|
||
identity. `stale_cursor` means evidence changed between pages; discard prior pages and restart the
|
||
read instead of mixing generations.
|
||
|
||
`docforge_get_context` paginates one ordered evidence stream: selected entries followed by explicit
|
||
omissions. An entry too large for one MCP response is represented by a bounded omission carrying
|
||
its node ID and detail hash, and the cursor advances. `docforge_list_changesets`,
|
||
`docforge_get_changeset`, `docforge_validate_changeset`, and `docforge_get_changeset_diff` accept
|
||
the same optional `limit` and `cursor` fields. Small results keep their familiar fields. Large
|
||
inspection pages may use hash summaries. A large diff may return `result_mode =
|
||
"canonical_json_chunk"`; concatenate the chunks in order and verify `payload_hash` before decoding
|
||
the reconstructed `operations` and `changes` object.
|
||
|
||
`docforge_get_task_context` uses the same opaque continuation discipline over capsule evidence
|
||
followed by capsule omissions. Keep the semantic task arguments unchanged while paging. Page size
|
||
may change. Every page retains the same plan, collection, and capsule hashes. A `stale_cursor`
|
||
means that the generation, policy, plan, or collection changed; discard earlier pages and restart.
|
||
|
||
`docforge_get_generation_diff` paginates only the details retained in the latest bounded receipt.
|
||
Its summary counts and full collection hash still cover permanently truncated details. The cursor
|
||
binds the exact receipt, target generation, retained and full collection hashes, receipt state, and
|
||
effective policy. A replacement receipt returns `stale_cursor`; restart from its first page.
|
||
|
||
Canonical application records its terminal receipt immediately after the project-owned serializer
|
||
verifies the new canonical state. A later index or render refresh failure is reported as degraded
|
||
derived state with remediation, not as permission to apply the same canonical change again.
|
||
Likewise, failure to remove a private transaction artifact after semantic commit returns
|
||
`applied`, closes the proposal, and persists compact `application_recovery` lifecycle metadata
|
||
with `cleanup_required`, retained paths, and remediation. Inspect and remove only files proven to
|
||
be DocForge-owned.
|
||
|
||
Every successful declared render publishes a bounded version-1 receipt below the disposable cache.
|
||
Normal `render-status` compares cheap source-generation, view-configuration, template-file, and
|
||
output-file identities. It does not parse canonical nodes, prepare Markdown, construct HTML, or
|
||
hash the complete output. Missing or corrupt receipts are `unverified`; changed sources, templates,
|
||
or outputs are `stale`. Use `render-status --deep` only when explicitly requesting the
|
||
side-effect-free full-render equivalence oracle.
|
||
|
||
Use `docforge_propose_relationship_update` when the intended change is only an edge addition or
|
||
removal. It uses the same underlying validated update contract, but rejects empty relationship
|
||
lists and makes it explicit that node content will remain unchanged.
|
||
|
||
Custom adapters may expose the application tool only when they supply a project-owned
|
||
`CanonicalApplier`. Core DocForge will not guess how adapter nodes map back to canonical sources.
|
||
|
||
## Incremental adapter compilation
|
||
|
||
Release 1 complete-projection adapters remain supported. Adapters with large source trees can
|
||
implement the optional source-scoped manifest and extraction contract. DocForge then fingerprints
|
||
sources, reuses unchanged facts, reparses changed sources and their reverse dependents, validates a
|
||
complete candidate graph, and publishes the index atomically.
|
||
|
||
DocForge detects this capability structurally. An adapter without both `load_manifest()` and
|
||
`extract_source()` remains on the Release 1 path. Its behavior and query results are unchanged, but
|
||
it does not receive incremental performance until it opts in.
|
||
|
||
Build results report cache hits, reparsed sources, invalidated sources, deleted sources, and total
|
||
sources. A full projection remains the fallback and equivalence oracle.
|
||
|
||
Manual proposals remain separate from compilation. Applying an approved changeset updates
|
||
canonical sources first. Incremental compilation then notices those changed source fingerprints;
|
||
it never treats an unapplied proposal as canonical.
|
||
|
||
Function-scoped `LogicProjection` data is cached alongside its owning source but remains separate
|
||
from the primary Nodes, Flow, and Web graph. The Logic tab and `docforge_get_logic` load one
|
||
function or method on demand without adding every condition and basic block to ordinary graph
|
||
traversal.
|
||
|
||
See [Incremental Adapter Indexing](INCREMENTAL_INDEXING.md) for the complete contract, cache
|
||
invalidation rules, manual-application lifecycle, and lazy Logic boundary.
|
||
|
||
### Preserving an older non-AST adapter
|
||
|
||
Use `--no-ast` on the MCP binding when the project owner wants the existing adapter preserved
|
||
without AST, Tree-sitter, compiler-AST, or function-Logic upgrades:
|
||
|
||
```bash
|
||
docforge-mcp --project-root /absolute/project --no-ast
|
||
```
|
||
|
||
For a project-owned server, pass `no_ast=True` to `create_project_server()` or
|
||
`create_read_only_server()`. Bootstrap and contract responses then expose
|
||
`mode=preserve-no-ast`. The Logic tool is blocked, and DocForge refuses to publish nonempty Logic
|
||
projections.
|
||
|
||
This policy does not disable the Release 1 `load_projection()` path. It also permits incremental
|
||
fingerprinting and caching when those mechanisms do not add AST analysis. The adapter can
|
||
therefore benefit from current synchronization, proposals, application, rendering, and graph tools
|
||
without a source-analysis rewrite.
|
||
|
||
The binding rejects a pre-existing index containing Logic before reads or live visualization. A
|
||
configured canonical application service also refreshes through the same no-AST index policy.
|
||
DocForge does not inspect arbitrary adapter source to prove which parsing library it uses, so
|
||
repository permissions and project instructions remain responsible for adapter implementation
|
||
changes outside this process boundary.
|
||
|
||
## Troubleshooting
|
||
|
||
### `optional_dependency_missing`
|
||
|
||
Install the exact extra named in the error into the same Python environment that starts DocForge:
|
||
|
||
```bash
|
||
python -m pip install 'docforge[javascript]'
|
||
python -m pip install 'docforge[typescript]'
|
||
python -m pip install 'docforge[cpp]'
|
||
```
|
||
|
||
Do not install every frontend merely to suppress the check. A missing optional parser is a closed,
|
||
actionable capability error and does not affect base generic or Python reference operation.
|
||
|
||
### `adapter_launcher_unavailable` or `invalid_adapter_launcher`
|
||
|
||
Use one installed top-level Python module whose resolved regular-file origin is inside the project
|
||
root, or use the fixed `docforge.reference_mcp` binding. Arbitrary dotted modules, packages,
|
||
stdlib modules, missing modules, commands, argument strings, working directories, and environment
|
||
injection are rejected. Test the exact generated fragment rather than editing its command by hand.
|
||
|
||
See [agent integration](AGENT_INTEGRATION.md) and the [security model](SECURITY.md).
|
||
|
||
### `adapter_restart_required`
|
||
|
||
The project-local adapter code, its declared descriptor, or another implementation file changed
|
||
after the project-bound MCP process started. DocForge rejects every further operation before
|
||
synchronization because the live Python objects still represent the prior implementation.
|
||
|
||
Restart the MCP server or start a fresh client session. Do not stage files merely to change the
|
||
adapter's source manifest, and do not attempt in-process module reloading. The error includes
|
||
bounded added, changed, and deleted path evidence to identify the changed implementation boundary.
|
||
|
||
### `stale_index` or `visualization_stale`
|
||
|
||
Normal MCP operations automatically repair a missing, stale, or invalid disposable index under a
|
||
project lock. `docforge_sync` can be called explicitly to inspect whether synchronization was a
|
||
no-op or rebuild. The CLI equivalent is:
|
||
|
||
```bash
|
||
docforge --project-root "$PROJECT" sync
|
||
docforge --project-root "$PROJECT" visualize
|
||
```
|
||
|
||
An existing graph browser intentionally stays pinned to its original index identity. Reopen it
|
||
after synchronization or reindexing.
|
||
|
||
Every complete index build also writes a disposable whole-file SHA-256 attestation. A new MCP
|
||
process verifies the unchanged database against that receipt instead of reconstructing every graph
|
||
row. Missing or mismatched receipts fall back to complete verification and are recreated only after
|
||
the full check succeeds.
|
||
|
||
Milestone 5 maintains exact recovery for four corrupt derived artifacts. Synchronization restores
|
||
a corrupt index attestation after complete verification. Explicit `render` restores a corrupt
|
||
manual receipt to the exact output and receipt semantics. A complete `reindex` recreates a corrupt
|
||
generation-diff baseline against the exact current graph. Explicit `graph-render` recreates a
|
||
corrupt portable-graph manifest and exact artifact. Status operations diagnose these conditions
|
||
without hidden repair.
|
||
|
||
### `visualization_manager_unavailable`
|
||
|
||
The per-user manager is not installed, is stopped, or points to an old virtual environment.
|
||
|
||
```bash
|
||
docforge-viewer-manager install-user-service
|
||
```
|
||
|
||
For diagnosis, run `docforge-viewer-manager serve` in a terminal and retry `docforge visualize`.
|
||
|
||
### The browser did not open
|
||
|
||
The command still returns the loopback URL as JSON. Open that URL manually. Desktop-less sessions
|
||
should use `--no-open`. Confirm a local browser is registered as the default URL handler.
|
||
|
||
### `docforge_apply_changeset` is missing
|
||
|
||
The MCP server was started without `--canonical-applier`, or a custom adapter did not supply a
|
||
canonical applier. Restart the MCP server with the explicit gate after deciding that canonical
|
||
application is appropriate for that project.
|
||
|
||
### `canonical_application_disabled`
|
||
|
||
The CLI/MCP process has no matching configured applier identity. Confirm the ID exists under
|
||
`[[changesets.writers]]`, owns the changeset, and is passed exactly to `--applier` or
|
||
`--canonical-applier`.
|
||
|
||
### `changeset_conflict`
|
||
|
||
The changeset changed after the caller read it. Retrieve the changeset and diff again. Review the
|
||
new hash rather than retrying with the old approval.
|
||
|
||
### `base_conflict`, `content_conflict`, or `proposal_conflict`
|
||
|
||
- `base_conflict`: canonical sources changed after changeset creation.
|
||
- `content_conflict`: a target node no longer has the expected content hash.
|
||
- `proposal_conflict`: another active proposal from the same base touches the same node or source.
|
||
|
||
Do not force apply. Call `docforge_rebase_changeset` with the exact current changeset hash. DocForge
|
||
will rebind it only when every touched fact is unchanged and the proposal still validates. A
|
||
content or relationship conflict remains fail-closed and requires a newly reviewed proposal.
|
||
|
||
### `application_mismatch`
|
||
|
||
The written sources did not reproduce the validated projection. During an ordinary in-process
|
||
failure, DocForge rolls generic canonical files back when their exact publication identities are
|
||
still provable. If another process raced a target, DocForge preserves foreign and displaced data
|
||
and returns `application_recovery_required` rather than overwriting either. For a custom adapter,
|
||
fix its serializer or node-to-source mapping before retrying.
|
||
|
||
### `application_recovery_required` or `cleanup_required`
|
||
|
||
`application_recovery_required` means canonical publication or rollback encountered concurrent or
|
||
unprovable state. Preserve every retained file named in the error. Compare it with the canonical
|
||
target and resolve the project before creating a newly reviewed proposal. Do not retry the old
|
||
approved hash.
|
||
|
||
`cleanup_required` means semantic application already committed. The proposal is closed as
|
||
`applied`, and its lifecycle receipt names private transaction artifacts that could not be removed.
|
||
Inspect those files and remove only confirmed DocForge-owned artifacts. The canonical change must
|
||
not be applied again.
|
||
|
||
Generic application uses mode-0700 transaction directories, but DocForge is not a filesystem
|
||
sandbox. Deliberate arbitrary tampering by another process running as the same operating-system
|
||
user is outside that integrity boundary. A process or host death can also interrupt a multi-file
|
||
application because canonical application has no process-death journal.
|
||
|
||
### `path_escape`, `unsafe_template`, or missing source
|
||
|
||
DocForge rejects absolute paths, parent traversal, symlink escapes, overlapping canonical and
|
||
derived roots, unsafe render outputs, and source files outside the project root. Fix the descriptor
|
||
or adapter projection. Do not weaken confinement to make the error disappear.
|
||
|
||
### Source opens at the wrong place
|
||
|
||
The source path comes from the node. The anchor comes from the generic source or custom adapter.
|
||
Improve the adapter’s `source_anchor` to a line, stable heading, TOML `node-N` anchor, or distinctive
|
||
symbol. DocForge can open the file safely, but it cannot infer a perfect code location from
|
||
ambiguous adapter evidence.
|
||
|
||
### Full inspector content does not fit
|
||
|
||
DocForge 1.4 uses a fixed header and footer with a scrollable inspector body. If an older page is
|
||
still open, stop and reopen the visualization so it loads the current `graph-browser@17` template.
|
||
|
||
### Render output is stale
|
||
|
||
```bash
|
||
docforge --project-root "$PROJECT" render-status
|
||
docforge --project-root "$PROJECT" render VIEW_ID
|
||
```
|
||
|
||
Successful canonical apply regenerates declared manual views only when manual policy is `auto`.
|
||
A manual canonical edit requires reindexing and explicit rendering. Portable graph publication
|
||
always remains a separate explicit CLI action.
|
||
|
||
Portable graph publication has separate status and policy:
|
||
|
||
```bash
|
||
docforge --project-root "$PROJECT" graph-render-status
|
||
docforge --project-root "$PROJECT" graph-render architecture
|
||
```
|
||
|
||
### `projection_policy_forbids_operation`
|
||
|
||
The process was deliberately started with the relevant manual, portable-graph, or live-viewer
|
||
operation disabled. Restart with an allowed selector after confirming that the integration should
|
||
receive that capability. Status and explicit stop operations remain available as described above.
|
||
|
||
### `projection_policy_unavailable`
|
||
|
||
The selected non-disabled projection has no matching project configuration or runtime. Add the
|
||
declared manual or portable graph render configuration, or make the live viewer runtime available,
|
||
before selecting that mode. Manual `auto` also requires an operation or MCP server with canonical
|
||
application enabled. Use manual `explicit` for a standalone CLI render.
|
||
|
||
### Descriptor changed after startup
|
||
|
||
Long-lived CLI/MCP bindings fail closed if `.docforge/project.toml` changes underneath them. Restart
|
||
the process so it binds the new descriptor deliberately.
|
||
|
||
## Development and verification
|
||
|
||
Run the ordinary repository gate:
|
||
|
||
```bash
|
||
make gate
|
||
```
|
||
|
||
Use `make benchmark` for the historical Milestone 0 baseline, `make benchmark-m1` for the
|
||
counter-gated warm-operation benchmark, `make benchmark-m2` for agent workflow gates, and
|
||
`make benchmark-m3-full` for the ten-sample 1,000-node projection, worker, fragment, status,
|
||
equivalence, response-size, and memory gates. `make benchmark-m4-full` runs the 1,002-node adapter
|
||
and recovery benchmark. `make adoption-m4` performs the offline fresh-wheel proof.
|
||
`make command-reference-check` rejects command-reference drift, and `make docs-check` validates
|
||
the maintained documentation graph. `make accessibility` runs the generated manual, portable
|
||
graph, and live viewer axe and keyboard flows.
|
||
|
||
Milestone 5 adds maintained compatibility, migration, concurrency, recovery, comparative-task,
|
||
release-identity, reproducible-artifact, secret-scan, and fresh-clone gates:
|
||
|
||
```bash
|
||
make compatibility-m5
|
||
make migration-m5
|
||
make concurrency-m5
|
||
make recovery-m5
|
||
make task-evidence-m5
|
||
make release-gate
|
||
make fresh-clone-m5
|
||
```
|
||
|
||
`release-gate` aggregates the full quality, browser, compatibility, migration, concurrency,
|
||
recovery, task-evidence, fresh-wheel, version, artifact, secret-scan, and benchmark suite.
|
||
`fresh-clone-m5` anonymously clones the exact published candidate over HTTPS, fetches and verifies
|
||
the frozen annotated `v1.0.0` migration tag, and repeats `release-gate`. Release operators use
|
||
`make release-pretag` before creating `v1.4.0` and `make release-posttag` after the annotated tag
|
||
points to the exact release commit.
|
||
|
||
Project-specific vocabulary, extraction rules, and serialization belong in the project adapter.
|
||
Generic core behavior must remain deterministic, project-bound, and recoverable.
|