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

186 lines
12 KiB
Markdown

# DocForge 0.11 contract
## Authority boundary
DocForge is bound to one explicit project root. Canonical project files own documentation facts.
Indexes, query results, context packs, changesets, previews, and renders are derived artifacts.
The generic core validates and retrieves canonical nodes. A project-bound proposal service writes
only isolated changesets. Canonical application, project builds, Git mutation, deployment, and
publication remain external integration actions. Passive revision detection may read the current Git
commit when Git is available; it cannot change repository state.
DFG-9 made manual canonical integration the permanent DocForge 0.x policy. The library, CLI, and
MCP server do not apply changesets to canonical files. Reconsidering that boundary requires a new
approved contract and measured cross-project evidence; it is not an unimplemented 0.x feature. See
`APPLICATION_DECISION.md`.
## Versioned contracts
- Project descriptor schema: `schemas/project.schema.json`, version 1.
- Node schema: `schemas/node.schema.json`, version 1.
- Edge schema: `schemas/edge.schema.json`, version 1.
- Result envelope: `schemas/result.schema.json`, version 1.
- Changeset schema: `schemas/changeset.schema.json`, version 1.
- Index schema: version 1, disposable and reproducible.
- Core, CLI, and MCP server: version 0.11.0.
Schema files describe the generic interchange contract. Runtime validation remains responsible for
path confinement, source hashing, relationship resolution, dependency cycles, project limits, stale
state, and adapter-specific rules that JSON Schema cannot prove by itself.
## Generic node storage
Markdown nodes begin with a TOML metadata block delimited by `+++`. The remaining Markdown is the
node content. TOML sources contain one or more `[[nodes]]` tables and store content in a `content`
field. Every node has a stable project-wide ID.
The generic authority vocabulary is `authoritative`, `approved_plan`, `derived`, `proposal`, and
`historical`. Projects define statuses and allowed relationship names in their descriptor. The core
gives special acyclic validation to `depends_on`; adapters may add stricter rules.
## Result identity
Successful operations identify the project, adapter, current revision when available, and canonical
source hash. Errors use a stable code, direct message, and structured details. Query operations fail
if canonical source no longer matches the derived index.
## Isolated proposal model
Create, update, move, and delete are ordered node operations inside an isolated changeset. Every
operation names its expected base hash. A move preserves the stable node ID. A delete must resolve
every incident relationship. Proposal validation and storage are atomic. Canonical application
remains external, and prose is never auto-merged.
The MCP process binds to one configured writer identity at startup. The project descriptor grants
that writer explicit families and operation types. A changeset records its creator, project root
fingerprint, base revision, canonical source hash, and ordered operations. Every append requires the
current changeset hash, so simultaneous writers cannot silently lose an operation.
Changesets from the same canonical base may coexist only when their touched node and source sets do
not overlap. Exact overlaps return structured conflicts naming the other changesets, nodes, and
sources. A stale canonical base, stale node hash, stale changeset hash, unauthorized family, unsafe
path, invalid graph, dependency cycle, unresolved delete relationship, or configured limit fails
before the proposal file changes.
## Declared rendering and previews
Render configuration is optional. A configured project declares one template root, one isolated
preview root, and one or more stable view IDs. Each view names a built-in renderer, template,
derived output file, title, and optional family filter. Paths are resolved under the project root
and may not overlap canonical content, authority files, changesets, templates, or previews.
The initial `generic_html` renderer uses pinned CommonMark parsing with raw HTML disabled. Templates
are UTF-8 files with a fixed token vocabulary; they cannot name commands, modules, or executable
renderers. Render identity covers the canonical source hash, optional changeset hash, selected node
and edge identities, view configuration, template hash, renderer contract, and exact parser version.
An explicit CLI render atomically replaces one declared derived output. MCP can render a validated
changeset only to its isolated preview path. Status recomputes expected output without writing and
reports `current`, `stale`, `missing`, `unsafe`, or `oversized`. Input changes detected before atomic
replacement fail without replacing the prior output.
Normal MCP access does not expose canonical application, declared project-output rendering,
arbitrary renderer execution, arbitrary file writes, shell commands, Git mutation, build commands,
deployment, or publication.
## Project-bound graph visualization
The fixed `docforge_visualize` MCP tool starts one persistent read-only graph browser for the
server's already-configured project. It accepts only an optional stable node ID, an optional lexical
query, and a bounded traversal depth. It does not accept a project root, database path, SQL,
template path, bind address, command, or renderer.
The runner validates the complete canonical projection and derived index before it starts. It then
pins the browser to that exact validated SQLite file identity and project metadata so normal UI
queries do not rebuild a large adapter graph. Replacement or alteration of the index file makes the
browser fail closed; the user must invoke the tool again. The browser identifies itself as a
validated snapshot rather than claiming that canonical files are continuously monitored.
The HTTP listener binds to `127.0.0.1` on an operating-system-selected port. A cryptographically
random token is part of every accepted URL path. Only `GET` and `HEAD` are supported. Responses use
no-store caching, a restrictive content-security policy, frame denial, MIME sniffing protection,
and no-referrer policy. The built-in template uses only same-origin JSON endpoints for graph
overview, bounded search, exact descriptor-category filtering, exact node content, bounded
incoming-and-outgoing neighborhoods. Descriptor filtering accepts only
family, authority, status, or tag plus one exact value. There is no write endpoint, arbitrary query
endpoint, static filesystem handler, external asset, or project-selection control.
The `graph-browser@8` template provides mouse-wheel zoom centered on the pointer, left-button drag
pan, explicit zoom-in and zoom-out buttons, a reset-view button, and a live zoom percentage. A
four-pixel drag threshold defers pointer capture and preserves node activation for ordinary clicks.
Loading another root node fits the viewport to the returned neighborhood, including a useful
minimum scale for a single-node result. The current root begins selected, and activating another
graph node moves the visible selection ring to it. Space centers the viewport on the selected node
without changing zoom. Reset restores the fitted neighborhood view. Empty-canvas guidance is hidden
whenever a neighborhood is rendered. The page is fixed to the browser viewport. Search and exact
filter results fill the left panel, neighborhood traversal fills the right panel, and only the
center SVG canvas pans or zooms.
Left-clicking or pressing Enter on a graph node opens a compact descriptor card containing the
validated metadata and content previously shown in the details panel. Its family, authority,
status, and tag pills are buttons that replace the left result list with exact matching nodes.
Right-clicking or pressing Shift+Enter opens the complete inspector. Inspection does not replace
the current neighborhood or reset the viewport. Both dialogs support Escape, explicit close
controls, and backdrop dismissal. Loading the inspected node as the new root requires the separate
Explore neighborhood action. Both side panels support pointer and keyboard resizing. The unblurred
full inspector supports native resizing and constrained title-bar dragging.
The header exposes a Nodes/Flow segmented selector. Nodes displays the complete bounded
neighborhood. Flow displays an upstream lineage ending at the current root. Calls, dispatches,
launches, activations, and writes retain their declared source-to-target direction. Reads, imports,
and dependencies reverse for lineage presentation because the declared target feeds the source.
Structural, evidence, and context relations remain available in Nodes but are excluded from Flow.
This is a presentation transform over the validated bounded snapshot; it does not add or change
project relationships.
Both views color edges by relationship semantics and retain direction with visible SVG endpoint
symbols. Line patterns provide a non-color cue. A static canvas key shows the exact symbol, color,
label, and visible count for each displayed relation, including a deterministic fallback for
project-defined relations. Nodes and Flow use the same map.
The browser derives node presentation roles only from the returned bounded graph. The current root
is the focus. In Nodes, nodes reachable through outgoing edges are shown as outgoing paths; the
remaining visible nodes are incoming or lateral context. In Flow, lineage predecessors are shown as
upstream nodes. These roles receive distinct palettes and navigation sections. An undirected
shortest-hop calculation places Nodes on distance rings; Flow uses left-to-right distance layers
with the destination on the right. Each role palette darkens progressively by distance, capped at
fifty percent.
Each invocation creates or reuses one persistent local worker for the validated snapshot. The worker
is detached from the short-lived MCP transport and has no browser inactivity or owner-process
expiry. A repeated invocation reuses its unguessable URL when the validated snapshot is unchanged.
If the index has changed, DocForge replaces the worker only after a fresh complete index check.
`docforge_stop_visualization` is the only normal shutdown path. It stops the current project's
verified worker and removes its private registry record. The worker also ends if the operating
system terminates it. Project-specific integrations receive the same tools because the parent
validates and serializes only the supplied `ProjectService` and `ProjectIndex` snapshot; the worker
does not discover projects or load canonical sources.
## Project adapter boundary
An adapter supplies one deterministically ordered `AdapterProjection` containing core nodes and
edges plus ordered adapter metadata. The core validates root identity, graph integrity, stable
ordering, and metadata-key uniqueness before exposing the projection through the standard derived
index. The loader is called again during an operation so identity or source changes fail closed.
Adapters own stricter project semantics such as authority precedence, phase rules, context
selection, query ordering, and render-model composition. They may not weaken root confinement,
canonical authority, graph validation, hashing, stale-state checks, or derived-output boundaries.
Shadow adapters are explicit local integrations and are not loaded by the normal generic MCP
process. A project integration may explicitly construct a read-only MCP server from one validated
`ProjectService` and an optional project-owned context provider. That server exposes only the fixed
read tool surface. The core does not discover adapters, choose projects or sessions, or import
project policy.
A proposal-enabled adapter declares confined canonical source, changeset, template, preview, and
render paths plus fixed writer permissions. It must supply a proposal validator. The core continues
to enforce optimistic hashes, writer permissions, graph integrity, limits, atomic changeset storage,
conflict detection, and preview confinement. The adapter validator enforces source-format and
project semantics that the generic core cannot infer. Generic projects retain the built-in Markdown
and TOML source-layout validator.
An explicit integration may construct the full fixed MCP surface for a configured adapter project
and one startup-bound writer. This does not add adapter discovery or canonical application. An
adapter without proposal settings or validation remains read-only.