1
0
Fork 0
Code Issues Pull requests Projects Releases 2 Packages Wiki Activity Actions Pages
DocForge2/docs/USER_MANUAL.md

597 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.
## 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.
- Hash-bound canonical application through both CLI and an explicitly enabled MCP tool.
- Declared HTML render views. Arbitrary templates, render commands, and output paths are rejected.
- 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.
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 / visualize / compile context
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.
## 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/DocForge.git /absolute/path/DocForge
cd /absolute/path/DocForge
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.
### 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]
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 projects 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.
## Visualization usage
- Left-click a node for its compact descriptor.
- Right-click a node for the full inspector.
- Use **Open source** to read the nodes 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.
### 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.
- 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>
```
### Project and index commands
```text
info
validate
build
reindex
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.
- `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]
dependencies NODE_ID [--depth N]
impact NODE_ID [--depth N]
context PROFILE [--budget N]
```
### Render and proposal commands
```text
render-status [VIEW_ID]
render VIEW_ID
preview CHANGESET_ID VIEW_ID
apply CHANGESET_ID --changeset-hash SHA256 --applier WRITER_ID
```
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 render. It does not commit or push the result.
### Viewer commands
```text
visualize [--node NODE_ID | --query QUERY] [--depth N] [--no-open]
visualization-status
visualization-stop
```
## 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.
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.
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_project_info`
- `docforge_get_contract`
- `docforge_get_node`
- `docforge_search`
- `docforge_filter_nodes`
- `docforge_backlinks`
- `docforge_dependencies`
- `docforge_impact`
- `docforge_get_context`
- `docforge_validate_project`
- `docforge_render_status`
- `docforge_visualize`
- `docforge_visualization_status`
- `docforge_stop_visualization`
### Proposal tools
- `docforge_create_changeset`
- `docforge_list_changesets`
- `docforge_get_changeset`
- `docforge_propose_node_create`
- `docforge_propose_node_update`
- `docforge_propose_node_move`
- `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.
Recommended agent sequence:
1. Read the contract and relevant nodes.
2. Create a changeset.
3. Add structured operations using the hash returned by each previous mutation.
4. Validate the changeset.
5. Inspect its structured diff and preview.
6. Obtain human approval for the final changeset hash when required by the client workflow.
7. Call `docforge_apply_changeset` with that exact hash.
8. Report changed canonical files and derived refresh results.
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.
## Troubleshooting
### `stale_index` or `visualization_stale`
Canonical sources changed after the index or viewer snapshot was built.
```bash
docforge --project-root "$PROJECT" reindex
docforge --project-root "$PROJECT" visualize
```
An existing graph browser intentionally stays pinned to its original index identity. Reopen it
after reindexing.
### `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. Rebase the intended changes into a new changeset after inspecting current
canonical content.
### `application_mismatch`
The written sources did not reproduce the validated projection. DocForge rolls the generic
canonical files back. For a custom adapter, fix its serializer or node-to-source mapping before
retrying.
### `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 adapters `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 0.15 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@15` template.
### Render output is stale
```bash
docforge --project-root "$PROJECT" render-status
docforge --project-root "$PROJECT" render VIEW_ID
```
Successful canonical apply regenerates all declared views automatically. A manual canonical edit
requires reindexing and rendering.
### 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 complete release gate from the DocForge repository:
```bash
npx pyright
npm run lint:web
uv run ruff check src tests tools
uv run ruff format --check src tests tools
uv run python -m compileall -q src tests tools
uv run pytest -q
```
Project-specific vocabulary, extraction rules, and serialization belong in the project adapter.
Generic core behavior must remain deterministic, project-bound, and recoverable.