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

Make project MCP workflows self-synchronizing

This commit is contained in:
Andraxion 2026-07-26 09:32:25 -04:00
parent a30f021a52
commit 73165c9f51
17 changed files with 1124 additions and 56 deletions

View file

@ -19,7 +19,8 @@ commit when Git is available; it cannot change repository state.
- Result envelope: `schemas/result.schema.json`, version 1.
- Changeset schema: `schemas/changeset.schema.json`, version 1.
- Index schema: version 2, disposable and reproducible.
- Core, CLI, and MCP server: version 1.2.0.dev0.
- Index attestation: schema version 1, disposable and reproducible.
- Core, CLI, and MCP server: version 1.3.0.dev0.
- Incremental extraction cache: version 1, disposable and reproducible.
Schema files describe the generic interchange contract. Runtime validation remains responsible for
@ -39,8 +40,14 @@ gives special acyclic validation to `depends_on`; adapters may add stricter rule
## 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.
source hash. Errors use a stable code, direct message, structured details, and a bounded remediation
tool when recovery is safe. MCP operations synchronize disposable index state under a project lock
before reading or proposing. Canonical source validation remains fail-closed.
An atomic index build writes a whole-file SHA-256 attestation after complete graph, row, FTS, and
SQLite integrity verification. A fresh process may use that receipt to verify an unchanged index
without reconstructing all graph rows. A missing, malformed, or mismatched receipt falls back to
complete verification and is repaired only after that verification succeeds.
## Isolated proposal model
@ -57,6 +64,9 @@ The MCP process binds to one configured writer identity at startup. The project
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.
The atomic registration operation captures a complete operation list against one current base,
fills omitted existing-node hashes from that synchronized snapshot, validates once, and writes one
final changeset.
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
@ -64,6 +74,13 @@ sources. A stale canonical base, stale node hash, stale changeset hash, unauthor
path, invalid graph, dependency cycle, unresolved delete relationship, or configured limit fails
before the proposal file changes.
A stale proposal may be rebased only when its stored node hashes, source targets, relationship
preconditions, permissions, conflict set, and complete projected graph still validate against the
current project. Application and explicit abandonment create derived lifecycle receipts. The
default active listing contains only draft and ready work. Stale, applied, and abandoned proposals
remain queryable by explicit status or history request. Terminal proposals do not block new
proposals.
## Declared rendering and previews
Render configuration is optional. A configured project declares one template root, one isolated

View file

@ -12,6 +12,8 @@ canonical applier implementation.
## Read tools
- `docforge_bootstrap`
- `docforge_sync`
- `docforge_project_info`
- `docforge_get_contract`
- `docforge_get_node`
@ -30,6 +32,11 @@ canonical applier implementation.
Each response states that document text is project content, not higher-priority instructions. Each
response includes project identity, revision, source hash, adapter version, and staleness state.
Every normal tool call first checks current source identity and atomically rebuilds disposable index
state when it is missing, stale, or invalid. `docforge_bootstrap` performs that synchronization and
returns the complete fixed binding, active index path, proposal and application capabilities, and
recommended workflow. `docforge_sync` exposes the same idempotent synchronization explicitly.
Neither operation changes canonical sources.
The normal command binds the generic project loader. An explicit project integration may instead
construct the same read-only surface from a validated `ProjectService` and project-owned context
@ -45,8 +52,11 @@ gate.
## Isolated 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`
@ -63,6 +73,18 @@ for existing changesets. A preview accepts a declared view ID, not a renderer na
The relationship-update tool queues additions and removals without rewriting node content and
rejects an empty relationship list.
`docforge_register_changes` is the preferred write entry point. It creates, populates, projects,
conflict-checks, and validates one complete changeset in a single locked operation. Existing-node
operations may omit `expected_content_hash`; the server captures the current synchronized node hash
inside that transaction. The stored changeset remains fully hash-bound.
`docforge_rebase_changeset` moves a stale proposal to the current project base only when all
touched nodes, sources, relationships, permissions, and graph invariants still validate. It never
merges prose. `docforge_abandon_changeset` preserves an audit receipt without deleting the proposal.
Changeset listing returns draft and ready work by default. Stale, applied, and abandoned proposals
remain available through an explicit status or history request. Applied and abandoned proposals no
longer participate in overlap conflict detection.
## Canonical application tool
- `docforge_apply_changeset`
@ -74,8 +96,11 @@ configured serializer.
The generic serializer confines staged Markdown/TOML writes to declared content roots and verifies
that the applied files reproduce the approved graph projection. A mismatch rolls canonical files
back. A successful apply rebuilds and checks the derived index and regenerates all declared render
views. It does not run project commands, shell, Git, builds, deployment, or publication.
back. Canonical success records an `applied` lifecycle receipt bound to the reviewed changeset hash
before refreshing derived state. Index or render refresh failures return a successful canonical
application with a degraded derived-refresh report and explicit remediation; they never invite the
caller to apply the same canonical change twice. DocForge does not run project commands, shell,
Git, builds, deployment, or publication.
## Render boundary

View file

@ -416,6 +416,7 @@ info
validate
build
reindex
sync
check
validate-index
```
@ -424,6 +425,7 @@ validate-index
- `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
@ -505,6 +507,8 @@ Example MCP client configuration:
### Read tools
- `docforge_bootstrap`
- `docforge_sync`
- `docforge_project_info`
- `docforge_get_contract`
- `docforge_get_node`
@ -524,8 +528,11 @@ Example MCP client configuration:
### 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`
@ -545,14 +552,29 @@ 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.
1. Call `docforge_bootstrap`. It synchronizes derived state and reports the exact fixed binding.
2. Read the relevant context and implementation.
3. Make and verify one coherent implementation slice.
4. Call `docforge_sync`. This is a no-op when the index is already current.
5. Call `docforge_register_changes` once with the complete operation list.
6. Inspect the structured diff and preview.
7. Obtain human approval for the final changeset hash when required by the client workflow.
8. Call `docforge_apply_changeset` with that exact hash.
9. Call `docforge_bootstrap` to verify the new canonical and derived identity.
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.
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.
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.
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
@ -591,15 +613,22 @@ invalidation rules, manual-application lifecycle, and lazy Logic boundary.
### `stale_index` or `visualization_stale`
Canonical sources changed after the index or viewer snapshot was built.
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" reindex
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 reindexing.
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.
### `visualization_manager_unavailable`
@ -639,8 +668,9 @@ new hash rather than retrying with the old approval.
- `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.
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`