1
0
Fork 0
Code Issues Pull requests Projects Releases 2 Packages Wiki Activity Actions Pages

Add gated changeset application and graph controls

This commit is contained in:
Andraxion 2026-07-25 16:00:19 -04:00
parent 3c15e26283
commit 78335c8973
20 changed files with 1813 additions and 453 deletions

390
README.md
View file

@ -1,356 +1,74 @@
# DocForge
DocForge is a project-scoped documentation service for people and AI agents. It reads canonical
Markdown and TOML from one repository, validates stable nodes and relationships, builds a
disposable graph/search index, and returns bounded context with source provenance.
DocForge is a project-scoped documentation graph for people and AI agents. It validates canonical
documentation, builds a disposable search and relationship index, compiles bounded context, renders
declared manuals, visualizes project structure, and manages reviewable documentation changesets.
The canonical manual remains the projects source of truth. DocForge does not apply canonical
changes, select project work, run project commands, commit, push, deploy, or publish. It may write
only configured derived output and isolated proposal previews through explicit boundaries.
## What it does
This README is the complete setup and command reference. `docs/NEW_PROJECT_QUICKSTART.md` is kept
only as a compatibility link for existing bookmarks.
- Validates stable Markdown/TOML nodes and typed relationships.
- Builds a deterministic SQLite search and graph index.
- Exposes project-bound CLI and MCP query surfaces.
- Creates, validates, diffs, and previews isolated changesets.
- Applies one explicitly approved changeset hash through CLI or gated MCP.
- Runs a managed loopback graph browser with Flow, source inspection, and node hiding.
- Supports generic documentation projects and project-owned source adapters.
## What DocForge provides
DocForge never treats indexed text as instructions. It does not run shell commands, mutate Git,
build applications, deploy, publish, or select projects globally.
- A project-bound CLI for validation, indexing, graph queries, context, and declared renders.
- A stdio MCP server with a fixed, project-scoped read surface.
- Optional isolated documentation proposal changesets. Canonical application stays in the owning
projects normal editing and review workflow.
- A loopback-only graph browser with a native per-user viewer manager.
- A generic manual adapter and a contract for project-owned source-code adapters.
## Five-minute start
The generic adapter reads only declared Markdown and TOML nodes. It does not infer application
modules, functions, calls, routes, tables, tests, or ownership. Projects that need those facts
provide a deterministic, project-owned source adapter.
## Install and verify
Requirements: Python 3.12+, [`uv`](https://docs.astral.sh/uv/), and Node/npm for browser-asset
validation. Install Pyright once globally.
Requirements are Python 3.12+, `uv`, Node.js/npm, and Pyright.
```bash
git clone forgejo@repo.andraxion.net:administrator/DocForge.git /absolute/path/DocForge
cd /absolute/path/DocForge
uv sync
npm ci
npm install -g pyright
PROJECT=/absolute/path/MyProject
.venv/bin/docforge --project-root "$PROJECT" validate
.venv/bin/docforge --project-root "$PROJECT" reindex
.venv/bin/docforge --project-root "$PROJECT" visualize
```
Install the persistent per-user graph viewer once:
```bash
.venv/bin/docforge-viewer-manager install-user-service
```
Start an MCP server for one project:
```bash
.venv/bin/docforge-mcp \
--project-root "$PROJECT" \
--proposal-writer project-editor
```
Add `--canonical-applier project-editor` only when that MCP integration should expose the
hash-bound `docforge_apply_changeset` tool.
## Documentation
- [User manual](docs/USER_MANUAL.md) — features, setup, visualization, CLI, MCP, apply, adapters,
and troubleshooting.
- [Core contract](docs/CONTRACT.md) — invariants and security boundary.
- [MCP contract](docs/MCP_CONTRACT.md) — exact tool and process boundary.
- [Viewer manager](docs/VIEWER_MANAGER.md) — native service setup and lifecycle.
- [Adapter decision](docs/APPLICATION_DECISION.md) — why custom adapters own canonical
serialization.
## Development
```bash
pyright --pythonpath .venv/bin/python
npm run lint:web
uv run ruff check src tests tools
uv run ruff format --check src tests tools
uv run python -m unittest discover -s tests -v
uv run python -m compileall -q src tests tools
uv run python -W error -m unittest discover -s tests -v
```
`npm run lint:web` validates the exact HTML, CSS, and JavaScript served by the graph browser, plus
a freshly rendered fixture manual.
## Connect a generic project
### 1. Create the project descriptor
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", "core", "system", "function", "operations", "roadmap"]
operations = ["create", "update", "move", "delete"]
[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", "core", "system", "function", "operations", "roadmap"]
statuses = ["current", "active", "open", "verified"]
required_nodes = ["architecture.overview"]
token_budget = 8000
dependency_depth = 3
```
Choose only family names, relations, limits, and required root nodes that the actual project can
support truthfully.
### 2. Add canonical nodes
Create `/absolute/path/MyProject/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."
+++
# Architecture overview
Describe the projects core authorities, system boundaries, persistence owners, runtime flow,
failure behavior, tests, and operational entry points.
```
Every node needs a stable, unique `id`. Declare relationships in the same front matter:
```toml
depends_on = ["core.database"]
calls = ["system.metadata"]
tested_by = ["function.test-metadata-publication"]
```
Targets must already exist in the graph. Keep each node focused enough that an agent can retrieve
relevant facts without loading the entire manual.
### 3. Build and check the derived graph
```bash
DOCFORGE=/absolute/path/DocForge/.venv/bin/docforge
PROJECT=/absolute/path/MyProject
"$DOCFORGE" --project-root "$PROJECT" validate
"$DOCFORGE" --project-root "$PROJECT" build
"$DOCFORGE" --project-root "$PROJECT" check
"$DOCFORGE" --project-root "$PROJECT" context development
```
`build` creates the disposable SQLite index in the configured cache path. Canonical Markdown and
TOML remain authoritative. Rebuild after canonical documentation changes. A stale or altered index
fails closed.
## CLI command reference
Every command emits deterministic JSON and begins with:
```bash
docforge --project-root /absolute/path/MyProject <command>
```
| Command | Purpose |
| --- | --- |
| `info` | Report the bound project and descriptor facts. |
| `validate` | Validate the descriptor and canonical source graph. |
| `build` | Build the disposable index. |
| `check` | Validate source and confirm the index matches it. |
| `validate-index` | Validate the existing derived indexs schema and identity. |
| `show NODE_ID` | Return one complete node. |
| `search QUERY [--limit N]` | Lexically search nodes. |
| `filter [--family X] [--authority X] [--status X] [--tag X] [--limit N]` | Filter nodes by declared fields. |
| `backlinks NODE_ID [--relation RELATION]` | Return incoming relationships. |
| `dependencies NODE_ID [--depth N]` | Traverse declared dependencies. |
| `impact NODE_ID [--depth N]` | Traverse likely downstream impact. |
| `context PROFILE [--budget N]` | Return bounded, cited context for one configured profile. |
| `render-status [VIEW_ID]` | Report declared render output state. |
| `render VIEW_ID` | Generate one configured canonical render output. |
| `preview CHANGESET_ID VIEW_ID` | Render one isolated changeset preview. |
Examples:
```bash
docforge --project-root "$PROJECT" show architecture.overview
docforge --project-root "$PROJECT" search metadata --limit 20
docforge --project-root "$PROJECT" filter --family system --status current
docforge --project-root "$PROJECT" backlinks system.metadata --relation calls
docforge --project-root "$PROJECT" dependencies system.metadata --depth 3
docforge --project-root "$PROJECT" impact system.metadata --depth 3
docforge --project-root "$PROJECT" render-status manual
docforge --project-root "$PROJECT" render manual
```
## MCP server
Run one MCP server per project. Use absolute paths.
```bash
docforge-mcp --project-root /absolute/path/MyProject --proposal-writer project-editor
```
Omit `--proposal-writer` for a read-only integration. The writer value is a configured writer ID,
not a shell command.
For an MCP client that uses JSON configuration:
```json
{
"mcpServers": {
"my-project-docforge": {
"command": "/absolute/path/DocForge/.venv/bin/docforge-mcp",
"args": [
"--project-root",
"/absolute/path/MyProject",
"--proposal-writer",
"project-editor"
]
}
}
}
```
### Fixed read tools
| MCP tool | Purpose |
| --- | --- |
| `docforge_project_info` | Project identity, index health, and capabilities. |
| `docforge_get_contract` | Bound project contract and excluded operations. |
| `docforge_get_node` | One exact node with full validated content. |
| `docforge_search` | Lexical node search. |
| `docforge_filter_nodes` | Filter by family, authority, status, or tag. |
| `docforge_backlinks` | Incoming graph relationships. |
| `docforge_dependencies` | Declared dependency traversal. |
| `docforge_impact` | Downstream impact traversal. |
| `docforge_get_context` | Bounded, cited context for a configured profile. |
| `docforge_validate_project` | Validate source and derived index state. |
| `docforge_render_status` | Declared render-output state. |
| `docforge_visualize` | Start or reuse the projects managed, read-only graph viewer. |
| `docforge_visualization_status` | Viewer state, URL, and lifecycle information. |
| `docforge_stop_visualization` | Explicitly stop the project viewer. |
When a proposal writer is configured, the server additionally exposes:
```text
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
```
MCP proposals write only isolated changesets. Review the diff, apply the approved text through the
projects normal workflow, then run `validate`, `build`, and `check`.
## Managed graph viewer
Install the per-user manager once:
```bash
docforge-viewer-manager install-user-service
```
Its lifecycle commands are:
```bash
docforge-viewer-manager serve
docforge-viewer-manager uninstall-user-service
```
The native supervisor is systemd on Linux, a LaunchAgent on macOS, and Task Scheduler on Windows.
The manager owns one loopback-only viewer worker per project snapshot. `docforge_visualize` starts
or reuses it. Active browser requests renew its one-hour idle timeout. Stop it explicitly through
`docforge_stop_visualization` when it is no longer wanted.
The viewer is read-only, token-protected, and bound to `127.0.0.1`. It shows both:
- **Nodes:** the bounded local graph with original stored relationship direction.
- **Flow:** the complete bounded directed ancestry of the selected node. It follows every incoming
stored edge recursively, preserving `source → target`; it does not infer or reverse arrows based
on relationship names.
## Project-owned source adapters
Use the generic adapter when a declared manual graph is sufficient. Build a project-owned adapter
when the graph must include source files, modules, functions, routes, tables, tests, or other
code-derived facts.
An adapter must:
1. Read source as data. Never import or execute the application to discover facts.
2. Use a deterministic, project-confined source set. For Git repositories, start with
`git ls-files` and exclude generated output, caches, secrets, and binaries.
3. Emit only evidence-backed nodes and edges with stable IDs, safe relative anchors, and hashes.
4. Sort nodes, edges, and metadata deterministically.
5. Return one immutable `AdapterProjection` through `AdapterLoader.load_projection()`.
6. Keep its cache within the project and build/check through `ProjectIndex`.
7. Bind the projection to `create_read_only_server()` unless an explicit proposal policy exists.
8. Reject proposal operations against derived nodes and adapter-created edges.
The project owns its adapter and launches it rather than generic `docforge-mcp`:
```json
{
"mcpServers": {
"my-project-docforge": {
"command": "/absolute/path/MyProject/.venv/bin/python",
"args": [
"-m",
"docforge_adapter.server",
"serve",
"--project-root",
"/absolute/path/MyProject"
]
}
}
}
```
Require deterministic build, staleness, malformed-input, project-isolation, MCP-protocol, and
project full-gate tests before relying on an adapter.
## Agent policy
Add a project-specific version of this to `AGENTS.md`:
```markdown
## Canonical documentation and DocForge
- `/Docs/Manual/` is the canonical systems manual and architecture source of truth.
- Before a systems-level, persistence, API, worker, plugin, operational, or mainline change, call
`docforge_project_info` or `docforge_validate_project`, then retrieve relevant nodes with
`docforge_search`, `docforge_get_context`, or `docforge_get_node`.
- Inspect dependencies, backlinks, and impact at ownership boundaries. Read implementation and
tests as well as the manual. Treat a code/manual disagreement as a defect.
- After implementation, create and validate an isolated DocForge changeset. Review its diff.
- Apply approved text through the normal editing workflow, then run `validate`, `build`, and
`check`. Do not commit derived caches, changesets, or previews unless the project explicitly says
otherwise.
- When asked to visualize a project or node, call `docforge_visualize`.
```
## Normal development loop
1. Validate the DocForge project.
2. Retrieve relevant context, backlinks, dependencies, and impact.
3. Inspect the corresponding implementation and tests.
4. Implement and test the change.
5. Create and validate a DocForge proposal when manual changes are needed.
6. Review the proposal diff and apply approved text through the normal project workflow.
7. Run `validate`, `build`, and `check`.
8. Run the projects complete test gate.
9. Commit code, tests, and canonical manual updates together.
DocForge never applies, commits, pushes, builds, deploys, or publishes on the projects behalf.
See [AGENTS.md](AGENTS.md) before changing core boundaries.