Make project MCP workflows self-synchronizing
This commit is contained in:
parent
a30f021a52
commit
73165c9f51
17 changed files with 1124 additions and 56 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue