diff --git a/ACTIVE_SLICE.md b/ACTIVE_SLICE.md index f992ce6..bdb6724 100644 --- a/ACTIVE_SLICE.md +++ b/ACTIVE_SLICE.md @@ -1,134 +1,57 @@ -# Milestone state +# Active slice ```text -Last completed milestone: 5 — stabilization and first DocForge2 release. -Baseline: annotated v1.4.0 release commit on main, dev, origin/main, and origin/dev. +Last completed milestone: 5 - stabilization and first DocForge2 release. +Release: 2.0.0. Active milestone: none. -Outcome: Compatibility, determinism, recovery, security, performance, and representative task advantage are proven for the first successor release. +Maintenance: DocForge2 version identity and cross-identity proposal acceptance released. Status: Complete. -Release: 1.4.0. ``` -## Authority +## Current state -This contract activated Milestone 5 from the clean, merged, and pushed Milestone 4 closeout. The -roadmap in `/home/andraxion/.openclaw/workspace/DocForgeOutline.md` supplies direction; this file -freezes the executable scope and acceptance criteria. +DocForge2 `2.0.0` is the released product baseline. Current behavior is defined by the contracts +and guides under `docs/`. `SLICE_HISTORY.md` contains DocForge2 milestone summaries only. -The completed release synchronizes `main` and `dev` at the documentation-bearing commit identified -by annotated tag `v1.4.0`. +The release adds an explicit accepted-writer allowlist for project-owned canonical appliers. +Same-identity application remains the default. Contributor processes receive no application tool, +and successful receipts record both the proposal creator and applier. -## Required release evidence +The live documentation set contains current product contracts, current operating guidance, and +current successor milestone evidence. Superseded product plans and policy notes remain available +only through repository history and are not part of normal documentation validation or retrieval. -The release candidate must prove all of the following from maintained, reproducible gates: +## Maintenance proof - 2026-07-31 -1. Legacy one-method adapter compatibility and the frozen package, CLI, MCP, schema, rendering, - descriptor, result-envelope, and no-AST surfaces. -2. Exact complete/incremental primary-graph and Logic equivalence for maintained incremental - adapters. -3. Deterministic adapter, worker, renderer, command-reference, configuration, and publication - output. -4. Detection of concurrent source mutation without publishing or serving a mixed or stale - generation. -5. Atomic, crash-safe derived publication and exact recovery from interrupted publication. -6. Corrupt extraction-cache, index, attestation, receipt, fragment, and projection recovery using - canonical sources as the authority. -7. No stale reads after source or policy change, including generation-pinned retrieval and viewer - behavior. -8. Exact-hash canonical application with project-owned serialization, stale-proposal rejection, - and post-application resynchronization. -9. Closed policy precedence across process capability, descriptor policy, `--no-ast`, projection - policy, worker enforcement, and viewer enforcement. -10. Manual and portable-graph isolation, immutable package verification, bounded detached workers, - rendering-policy enforcement, viewer-policy enforcement, and accessibility. -11. Comparative representative task evidence with fixed questions, answer keys, provenance, - latency, and response-size accounting for both graph-assisted and source-only workflows. -12. A fresh-wheel and fresh-clone release rehearsal, full quality and browser gates, maintained - benchmarks, secret scans, exact version identity, signed-off release notes, and reproducible - release artifacts. +- Replaced the historical application-decision memo with the current canonical-application + contract. +- Removed the predecessor chronology from the live slice history and removed the transition-only + repository closeout page. +- Updated the README and documentation validator to reference only current product documentation. +- Formatting, Python lint, web lint, command-reference validation, and the 33-page documentation + graph passed. +- Focused adapter and changeset verification passed 45 tests plus 2 subtests. -## Deliverables +## Maintenance proof - 2026-08-02 -- A maintained Milestone 5 compatibility matrix and aggregate release gate. -- Reproducible migration, recovery, concurrency, and comparative-task evidence. -- One authoritative package version shared by package metadata, Python, CLI, MCP, viewer manager, - reference MCP, generated configuration, and release documentation. -- A standard project license file, changelog or release notes, release baseline, closeout record, - and machine-readable evidence. -- A clean `main` merge, synchronized `main` and `dev`, annotated `v1.4.0` tag, and Forgejo release - only after the final documentation-bearing commit passes a fresh-clone gate. +- Compared exact released commit `f9a05f868eec6c35e2b74a69467459e6ff2190bf` with exact development + commit `7b21541ab37c35dc9f3d47f631fef0c1884f9525` in isolated locked environments. +- The development repository gate passed formatting, Ruff, web lint, strict Pyright, compilation, + 142 contract tests plus 272 subtests, 381 complete tests plus 422 subtests, three accessibility + flows, dependency, build, documentation, and five smoke benchmark gates. +- Compatibility passed 116 tests plus 263 subtests, concurrency and application passed 31 tests + plus 2 subtests, recovery passed 72 tests plus 62 subtests, offline fresh-wheel adoption passed, + reproducible artifact checks passed, and Git plus directory secret scans found no leaks. +- All six full maintained benchmark tracks passed. Across 66 multi-sample operations, the median + absolute development-versus-release difference was 0.71%; 65 remained within 5%, and the only + larger difference was 0.062 ms on a 1.156 ms viewer-overview operation. +- Reference-adapter graph and Logic evidence and representative-task semantic evidence matched the + release exactly. All six representative tasks retained exact answers. +- Anonymous exact-commit fresh clones of both revisions completed the full release gate offline and + remained clean. The development rehearsal completed in 283.490 seconds versus 282.091 seconds for + the release. -## Fixed boundaries +## Next gate -- Preserve the `docforge` package, `docforge` CLI, `docforge-mcp`, MCP tool names, schema version 1 - surfaces, effective policy version 1, projection policy version 2, and legacy adapter entry point. -- Preserve canonical project sources. Migration may rebuild disposable state but may not rewrite - canonical content merely to satisfy the release. -- Full rebuild remains the recovery and equivalence oracle. -- Derived artifacts must fail closed on malformed, foreign, stale, oversized, or incompatible - state. -- Version `1.4.0` is additive relative to `1.0.0`; breaking a frozen contract requires a separately - justified major-version decision. - -## Exclusions - -- No WorldForge change or benchmark. -- No ScrapeStation change, production binding change, or production migration. -- No legacy-repository mutation. -- No production MCP repointing. -- No remote render service, render farm, third-party renderer ecosystem, graph federation, or - dedicated graph database. -- No arbitrary adapter command execution, compiler execution, remote execution, or expanded - launcher authority. -- No PyPI publication unless it is separately verified as an intended existing release channel. - -## Release sequence - -1. Freeze and implement the compatibility, migration, recovery, concurrency, and task-evidence - gates. -2. Stabilize version identity, packaging, license, security, and release automation. -3. Freeze one clean executable candidate and run the full repository, browser, benchmark, - fresh-wheel, fresh-clone, and secret-scan gates. -4. Close documentation atomically against that candidate and rerun documentation-only validation. -5. Merge and push the final candidate. -6. Rehearse from a fresh anonymous clone at the exact commit. -7. Create and push the annotated `v1.4.0` tag and publish the Forgejo release from the verified - artifacts. - -The completed Milestone 4 contract and exclusions remain preserved in `SLICE_HISTORY.md`. - -## Release-candidate evidence — 2026-07-29 - -The executable implementation is frozen at -`d2bb95fe6190e659cf66ba57c78be53b63b53240`. The proof-bearing candidate base is -`2b98059b44f4d46b4d4cce776f163e893c647c76`; it includes exact legacy-tag verification for the -fresh-clone gate and four maintained aggregate derived-recovery tests. - -The clean executable release gate passed formatting, Python and web lint, strict Pyright, -compilation, lock and dependency checks, builds, generated documentation, three accessibility -flows, fresh-wheel adoption, artifact reproducibility, secret scans, and the full Milestone 0 -through Milestone 4 benchmark sequence. Its exact test evidence was: - -- 142 contract tests plus 272 subtests. -- 371 complete tests plus 419 subtests. -- 116 compatibility tests plus 263 subtests. -- 29 concurrency tests plus 2 subtests. -- 68 recovery tests plus 62 subtests. - -The real migration gate preserves exact canonical and proposal bytes from the annotated `v1.0.0` -lineage while rebuilding the disposable index from schema 1 to schema 3. The real-package task -gate uses the lock-pinned `markdown-it-py 4.2.0` tree and proves exact graph-assisted and -source-only answers for all reviewed tasks. - -The later proof-only recovery commit adds four maintained tests without changing executable -product code. The current recovery aggregate passes 72 tests plus 62 subtests. - -The documentation-bearing candidate `49e1a87c138cdc63fb5abb85fc6eb2cf9f4a9d73` passed the complete -local release gate with 378 tests plus 422 subtests, all three accessibility flows, and every -focused and full gate above. Its final documentation-only descendant is the commit identified by -annotated tag `v1.4.0`; that exact remote commit passes the anonymous fresh-clone rehearsal before -tagging. - -The public Forgejo release publishes the reproducible wheel, source distribution, and -machine-readable release-identity evidence from the tagged commit. `main`, `dev`, `origin/main`, -and `origin/dev` resolve to that same commit. No PyPI publication was performed. +No implementation milestone is active. Any additional product behavior, version identity change, +release, or public integration requires its own bounded contract. diff --git a/CHANGELOG.md b/CHANGELOG.md index db7448c..3cfcc9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ remains in `docs/MILESTONE_*_BASELINE.md` and `docs/MILESTONE_*_CLOSEOUT.md`. ## Unreleased +## 2.0.0 - 2026-08-02 + +- Established `2.0.0` as the unambiguous package, Python, CLI, MCP, viewer-manager, and generated + client identity for DocForge2 without changing descriptor, result, adapter, or index schemas. +- Project-owned MCP servers can explicitly authorize a canonical applier to accept exact-hash + changesets from additional configured proposal writers. The default remains same-identity + application, contributor processes receive no application tool, and application receipts record + both the proposal creator and applier. +- Retained the full DocForge 1.4 compatibility, recovery, migration, benchmark, and reproducible + artifact gates. + ## 1.4.0 - 2026-07-29 Version `1.4.0` is the first additive DocForge2 successor release. Annotated tag `v1.4.0` diff --git a/README.md b/README.md index 88aec39..14d1e90 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,10 @@ DocForge never treats indexed text as instructions. It does not run project buil compilers, Git operations, deployments, or arbitrary renderers, and it does not select projects globally. -DocForge 1.4.0 is the first stable DocForge2 successor release. It contains the complete adapter -platform, stabilization and recovery evidence, representative real-task proof, and reproducible -release artifacts. Annotated tag `v1.4.0` identifies the synchronized release commit. +DocForge 2.0.0 is the current stable DocForge2 release. It gives the successor product an +unambiguous major-version identity, preserves the complete 1.4 adapter and recovery platform, and +adds explicit cross-identity proposal acceptance for project-owned canonical appliers. Annotated +tag `v2.0.0` identifies the synchronized release commit. ## Start here @@ -204,7 +205,7 @@ paths. - [Compatibility contract](docs/COMPATIBILITY.md) - [Adapter authoring guide](docs/ADAPTER_AUTHORING_GUIDE.md) - [Incremental indexing](docs/INCREMENTAL_INDEXING.md) -- [Adapter application decision](docs/APPLICATION_DECISION.md) +- [Canonical application](docs/CANONICAL_APPLICATION.md) - [Legacy and no-AST operation](docs/LEGACY_AND_NO_AST.md) - [Migrating from version 1](docs/MIGRATING_FROM_V1.md) - [Viewer manager](docs/VIEWER_MANAGER.md) @@ -218,7 +219,7 @@ paths. - [Milestone 3 baseline](docs/MILESTONE_3_BASELINE.md) and [closeout](docs/MILESTONE_3_CLOSEOUT.md) - [Milestone 2 baseline](docs/MILESTONE_2_BASELINE.md) and [closeout](docs/MILESTONE_2_CLOSEOUT.md) - [Milestone 1 baseline](docs/MILESTONE_1_BASELINE.md) and [closeout](docs/MILESTONE_1_CLOSEOUT.md) -- [Milestone 0 baseline](docs/MILESTONE_0_BASELINE.md) and [closeout](docs/MILESTONE_0_CLOSEOUT.md) +- [Milestone 0 baseline](docs/MILESTONE_0_BASELINE.md) Historical milestone records preserve the facts and dependency observations of their frozen candidates. Use the current guides and contracts for present behavior. diff --git a/SLICE_HISTORY.md b/SLICE_HISTORY.md index 587668d..e63a397 100644 --- a/SLICE_HISTORY.md +++ b/SLICE_HISTORY.md @@ -1,1027 +1,108 @@ -# Completed slices +# DocForge2 completed milestones -## DocForge2 Milestone 5 stabilization and first release +This file records DocForge2 milestones only. Product behavior is defined by the current contracts +under `docs/`, not by milestone notes. -### Changed +## 2026-08-02 - DocForge 2.0 release -- Centralized version `1.4.0` across package metadata, Python, executable surfaces, generated - clients, and release validation. -- Added MIT licensing, public Forgejo metadata, reproducible artifact checks, a real archived-v1 - migration proof, focused compatibility/concurrency/recovery gates, and representative - graph-assisted versus source-only task evidence. -- Hardened durable derived publication and generic exact-hash canonical application against - measured race windows. -- Added a fresh-clone rehearsal that requires the exact annotated legacy tag. +- Verified the unreleased explicit accepted-writer policy at development commit + `7b21541ab37c35dc9f3d47f631fef0c1884f9525` against released `v1.4.0` commit + `f9a05f868eec6c35e2b74a69467459e6ff2190bf` in isolated locked environments. +- Preserved same-identity application as the default, kept contributor processes without an + application tool, and proved explicit allowlisted application with creator and applier receipts. +- The development repository gate passed 142 contract tests plus 272 subtests, 381 complete tests + plus 422 subtests, three accessibility flows, and all static, build, documentation, and smoke + benchmark checks. +- Compatibility passed 116 tests plus 263 subtests, concurrency and application passed 31 tests + plus 2 subtests, recovery passed 72 tests plus 62 subtests, and adoption, reproducible-artifact, + migration, secret-scan, and anonymous fresh-clone release gates passed. +- All full maintained benchmark tracks passed. The median absolute difference across 66 + multi-sample operations was 0.71%, exact adapter graph and Logic evidence matched, and all six + representative task answers remained exact. +- Released the verified candidate as `2.0.0`, giving DocForge2 an unambiguous distribution and + executable identity while preserving its versioned schemas and compatibility contracts. -### Verification +## 2026-07-31 - live-documentation boundary cleanup -- The documentation-bearing candidate passed 378 tests and 422 subtests, 142 contract tests and - 272 subtests, three accessibility flows, lint, strict types, compilation, dependencies, builds, - adoption, reproducible artifacts, secret scans, and every maintained full benchmark. -- Focused compatibility passed 116 tests plus 263 subtests. Concurrency passed 29 tests plus 2 - subtests. -- Four later proof-only tests brought the recovery gate to 72 tests plus 62 subtests without - changing executable product code. -- Real `v1.0.0` migration preserved canonical, graph, and proposal evidence while rebuilding the - disposable index from schema 1 to schema 3. -- The lock-pinned real-package comparison returned exact answers from both workflows and measured - substantially less inspected source for graph-assisted work. +- Replaced the historical application-decision memo with the current canonical-application + contract. +- Removed predecessor rollout chronology and transition-only repository notes from the live + documentation tree. Repository history remains the archive. +- Updated live documentation references and validation requirements. +- Formatting, lint, command-reference, web, and 33-page documentation checks passed. Focused + adapter and changeset tests passed 45 tests plus 2 subtests. -### Limits +## Milestone 5 - stabilization and first release -- Multi-file canonical application does not claim process-death atomicity. -- Source-only task responses were smaller even where graph-assisted work inspected fewer bytes and - ran faster. -- No WorldForge, ScrapeStation, legacy repository, production binding, self-hosting, or PyPI - publication was changed. +- Released DocForge2 `1.4.0` from synchronized `main` and `dev` branches. +- Centralized version identity across package metadata, Python, CLI, MCP, generated client + configuration, and release evidence. +- Proved compatibility, deterministic output, recovery, concurrency, security, representative + task advantage, reproducible artifacts, fresh-wheel adoption, and fresh-clone installation. +- Hardened derived publication and exact-hash canonical application against measured race windows. +- Published the Forgejo release with reproducible wheel, source distribution, and + machine-readable identity evidence. -### Release +The final documentation-bearing candidate passed 378 tests plus 422 subtests, all maintained +quality and benchmark gates, three accessibility flows, secret scans, artifact reproduction, and +the anonymous fresh-clone rehearsal. -The exact synchronized release commit passes the fresh anonymous clone gate and is identified by -annotated tag `v1.4.0`. Its public Forgejo release carries the reproducible wheel, source -distribution, and machine-readable release-identity evidence. +## Milestone 4 - adapter SDK and product documentation -## DocForge2 Milestone 4 adapter SDK and product documentation +- Added the stable `docforge.adapter_sdk` authoring surface and complete/incremental conformance + helper. +- Added bounded Python, JavaScript, TypeScript, and C++ reference integrations. +- Added a closed reference-adapter descriptor and fixed read-only reference MCP server. +- Added deterministic client configuration generation for custom project adapters. +- Generated CLI and MCP references from live implementation metadata. +- Added onboarding, authority, descriptor, policy, adapter, rendering, security, recovery, and + agent-integration documentation. -### Changed +The candidate passed 347 tests plus 402 subtests, strict typing and lint gates, all maintained +benchmarks, package adoption, and three accessibility flows. -- Added stable `docforge.adapter_sdk` authoring imports and a conformance helper for deterministic - complete and exact complete/incremental primary graph plus Logic equivalence. -- Added bounded Python, JavaScript, TypeScript, and C++ reference integrations with explicit - unsupported-fact reports and optional heavy frontends. -- Added a closed `.docforge/reference-adapter.toml` contract and fixed read-only reference MCP - server. -- Added immutable project-bound launcher declarations and deterministic Codex, Claude, and OpenClaw - configuration generation for custom adapters. -- Generated CLI and MCP references from live implementation metadata and added race-safe - publication plus repository drift checks. -- Added strict documentation-graph and fresh-wheel adoption gates and dedicated onboarding, - authority, descriptor, policy, adapter, legacy/no-AST, rendering, agent-integration, security, - recovery/performance, and v1 migration guides. +## Milestone 3 - independent projections -### Verification - -- The executable candidate passed 347 tests and 402 subtests, 142 contract tests and 268 subtests, - three accessibility flows, lint, strict types, compilation, dependencies, builds, adoption, and - every maintained smoke benchmark. -- The offline base wheel contained no Tree-sitter distribution and ran a real Python reference - build/check and isolated 21-tool MCP retrieval flow. Missing C++ support failed with the exact - `docforge[cpp]` remediation. -- The clean 334-source benchmark produced 1,002 nodes and exact full/incremental graph and Logic - evidence, warm zero Python parsing/extraction, and exact corrupt-cache and corrupt-index - recovery below every latency, memory, and response gate. -- Gitleaks found no findings in the Milestone 4 commit range or candidate tree. - -### Limits - -- The reference integrations publish syntax and local static relationships. They do not claim - compiler-resolved calls, types, inheritance, macros, runtime behavior, or semantic ownership. -- C++ compilation-database commands are inert and never executed. -- C++ manifest include discovery uses Tree-sitter and makes no zero-warm-parser claim. -- No WorldForge, ScrapeStation, legacy repository, production binding, language distribution, - self-hosting, tag, or release was changed. - -### Next gate - -Milestone 5 remains directional. Create a new active-slice contract before stabilization, -versioning, tagging, or publication. - -## DocForge2 Milestone 3 independent projections - -### Changed - -- Added strict version-1 manual plan, graph plan, projection package, and projection receipt - contracts with canonical identities and packaged schemas. -- Kept the legacy manual API and exact alpha bytes as a compatibility wrapper over a pure planner, - immutable package, and independent renderer. -- Added generation-pinned portable graph planning, detached rendering, content-addressed durable - publication, repair, and receipt-only status. -- Added a fixed isolated worker protocol with bounded request, response, artifact, timeout, - environment, and renderer inventory. -- Added semantic manual fragments with independent worker validation, corruption recovery, - full-render equivalence, and bounded cache retention. -- Added version-2 independent manual, portable-graph, and live-viewer policy with descriptor-bound - generated-client evidence while retaining effective policy version 1. -- Corrected live source reads to use the pinned index generation. -- Added static and interactive accessibility gates for the manual, portable graph, and live viewer. +- Separated manual rendering, portable graph rendering, and live visualization policy. +- Added immutable render plans and packages, fixed detached workers, content-addressed publication, + receipts, recovery, and accessibility gates. +- Added semantic manual fragments with deterministic full-render equivalence. +- Pinned live viewer reads to one validated index generation. - Replaced recursive cycle planning with an iterative traversal proven at 10,000 nodes. -### Verification +The complete gate passed 281 tests plus 272 subtests and all maintained scale, response-size, +determinism, no-work, package, and browser checks. -- The complete gate passed 281 tests, 272 subtests, three accessibility flows, dependency checks, - builds, and all milestone smoke benchmarks. -- The maintained projection contract subset passed 142 tests and 236 subtests. -- The clean ten-sample 1,000-node benchmark passed every latency, memory, response-size, no-work, - deterministic-output, and full/incremental equivalence threshold. -- An isolated wheel passed CLI, MCP, detached manual rendering, and malformed worker startup. -- Three adversarial review tracks were reconciled, and Gitleaks found no findings in the six - milestone commits or candidate tree. +## Milestone 2 - project policy and task-shaped context -### Limits +- Added capability-aware bootstrap, effective policy, retrieval plans, bounded context capsules, + transition receipts, deterministic client fragments, and read-only diagnostics. +- Kept normal MCP work project-bound and explicit about enabled read, proposal, application, + rendering, and viewer capabilities. +- Added fixed configuration, policy, response-size, counter, and memory contracts. -- Production fragment reuse is correct and recoverable but is slower than forced full rendering at - the maintained 1,000-page fixture. No speedup is claimed. -- Actual detached artifact transfer is capped at 20,000,000 bytes. -- Portable graph publication is CLI-owned. MCP exposes read-only plan and status tools. -- Remote render services, render farms, third-party renderer ecosystems, storage replacement, - self-hosting, adapter SDK expansion, and production integration changes remain out of scope. -- No tag or release was created. +The complete gate passed 205 tests plus 120 subtests, strict types and lint, package builds, and all +maintained milestone benchmarks. -### Next gate +## Milestone 1 - fast observable core -Milestone 4 remains directional and is not active. Create a new active-slice contract before -starting adapter SDK or product-documentation implementation. +- Removed repeated whole-project parsing from routine warm reads. +- Added versioned generation receipts and generation-pinned SQLite retrieval. +- Kept complete loading and deep validation as recovery and equivalence oracles. +- Added structured work counters proving that retrieval and status calls do not hide builds, + parsing, rendering, or complete-project hashing. -## DocForge2 Milestone 0 successor foundation +The maintained 1,000-node benchmark kept exact retrieval, search, filtering, traversal, context, +render status, and visualization status within their recorded latency and response-size gates. -### Changed +## Milestone 0 - successor foundation -- Preserved the complete advanced DocForge lineage in the public - `administrator/DocForge2` successor. -- Committed the verified no-AST work and merged the original local-only adapter-lifecycle commit - without rewriting either line of history. -- Hardened no-AST enforcement for pre-existing indexes, live visualization, and - canonical-application refresh. -- Added explicit package, CLI, MCP, adapter, schema, changeset, rendering, safety, and no-AST - compatibility guarantees. -- Added repository-native aggregate, contract, build, and benchmark gates. +- Established the public DocForge2 repository and its `main` and `dev` workflow. +- Froze package, CLI, MCP, adapter, schema, changeset, rendering, safety, and no-AST compatibility + contracts. +- Added repository-native aggregate, contract, build, and performance gates. - Recorded cold and warm latency, startup, memory, rendering, response-size, incremental, and pinned-SQLite baselines. -- Configured `origin` for DocForge2 and `legacy` for the intact DocForge v1 repository. -- Kept only `main` and `dev` as successor development branches. Historical legacy branches remain - unchanged in the legacy repository. -### Verification - -- Gitleaks 8.30.1 found no secrets in reachable history or the candidate tree. -- The aggregate gate passed formatting, Python and web lint, strict types, compilation, public - contract and schema checks, 95 tests and 44 subtests, lock and dependency validation, package - builds, and benchmark smoke. -- The 1,000-node maintained baseline completed from a clean tree. -- Every successor ref was compared with its local source before redundant public development - branches were removed. -- Every recorded legacy head and the annotated `v1.0.0` tag remained byte-for-byte unchanged. -- An anonymous HTTPS clone selected `main`, passed `git fsck --full` and the complete aggregate - gate, and remained clean. -- No tag, release, release announcement, production MCP repointing, WorldForge change, - ScrapeStation change, storage rewrite, or self-hosting dependency was introduced. - -## DFG-23 process-stable adapter implementation boundary - -### Changed - -- Added a confined implementation boundary with explicit roots, files, and suffixes. -- Inferred the project-local Python package containing a loader and included its declared - descriptor without requiring every existing adapter to opt in manually. -- Fingerprinted relative implementation paths and bytes at process start under fixed file and byte - limits. -- Rejected edits, additions, deletions, missing files, and unsafe replacements with - `adapter_restart_required` before MCP synchronization or proposal validation. -- Returned bounded change evidence and explicit non-retryable `restart_project_server` - remediation. -- Clarified that current source manifests must treat staged and unstaged deletions identically; - Git staging is not a synchronization operation. - -### Verification - -- Focused tests cover inferred and explicit implementation boundaries, descriptor changes, added, - edited, and deleted files, ignored derived files, and exact MCP remediation. -- Strict Pyright, Ruff lint and formatting, Python compilation, and the HTML/CSS/JavaScript quality - gate passed. -- The complete warning-strict suite passed 87 tests and 2 subtests. - -## DFG-22 deterministic incremental adapter assembly - -### Changed - -- Added an optional language-neutral assembly contract after incremental source extraction. -- Kept raw source contributions inside DocForge's existing fingerprint, dependency invalidation, - cache, and atomic publication path. -- Required assembled projections to retain the manifest-bound identity, revision, and source hash. -- Validated the assembled primary graph and function Logic owners before publication. -- Preserved the stricter unique-source ownership path for adapters that do not need assembly. -- Documented assembly for compilers and language tools that repeat shared declarations across - extraction units. - -### Verification - -- The overlap fixture caches two repeated source contributions, publishes one deterministic node, - reuses both warm cache entries, reparses one changed source, preserves the selected fact, and - passes full/incremental equivalence. -- Focused adapter and onboarding tests passed 14 tests. -- Strict Pyright, Ruff lint and formatting, Python compilation, and the HTML/CSS/JavaScript quality - gate passed. -- The complete warning-strict suite passed 82 tests and 2 subtests. - -## DFG-21 language-neutral project onboarding - -### Changed - -- Added a read-only onboarding assessment that detects common source languages, build evidence, - likely documentation, existing configuration, and capability readiness without writing files. -- Added explicit language selection for C, C++, C#, Go, Java, JavaScript, Kotlin, Lua, PHP, - Python, Ruby, Rust, Scala, Swift, and TypeScript. -- Added conflict-safe generic scaffolding that creates project configuration, one authoritative - overview, a built-in manual template, the derived index, and the rendered starter manual. -- Kept language detection separate from semantic extraction. Every detected source language - remains `adapter_required` until a language frontend passes the adapter contract. -- Added the complete language-neutral onboarding checklist covering authority, manual import, - frontend ownership, C++, Rust, and Java build evidence, incremental compilation, source/manual - links, views, MCP activation, and maintenance. - -### Verification - -- Focused onboarding, CLI, and core tests passed 19 tests and 2 subtests. -- Strict Pyright, Ruff lint and formatting, Python compilation, and the HTML/CSS/JavaScript quality - gate passed. -- The complete warning-strict suite passed 81 tests and 2 subtests. - -## Dev-Rewrite multi-language Logic and traceable browser - -### Changed - -- Added pinned Tree-sitter-backed JavaScript and C++ analyzers behind the existing - language-neutral `LogicProjection` boundary. -- Replaced ambiguous merge terminology with decision, case, loop-exit, and exception convergence. -- Added composable text, family, node-kind, language, and capability filters plus common presets. -- Added direct-neighbor and incident-edge highlighting when a canvas node is selected. -- Increased Logic layer clearance and vertical spacing, with routed edge lanes for branches, - returns, and loop-back paths. - -### Verification - -- Tests cover JavaScript and C++ functions, methods, branches, short-circuit booleans, loops, - cases, exceptions, and returns alongside Python behavior. -- Visualization tests cover filter facets, capability filtering, trace controls, template - identity, and browser asset validity. - -## Dev-Rewrite function-scoped Logic - -### Changed - -- Added a reusable Python AST control-flow analyzer for functions, methods, and nested functions. -- Added dedicated schema-2 SQLite tables for function-scoped logic owners, nodes, and edges without - placing statement-level data in primary graph search or traversal. -- Added the bounded `docforge_get_logic` read tool and a lazy Logic visualization tab. -- Added semantic Entry, Decision, Action, Control, Convergence, and Terminal cards with explicit - branch, loop, exception, return, and raise paths. -- Added Logic-specific hiding that bridges retained predecessors and successors with an explicit - omitted path. -- Preserved Release 1 adapters and full projections. Adapters may emit no logic or opt in source by - source through the incremental extraction contract. - -### Verification - -- Tests cover Python branching, compound booleans, loops, `match`, exceptions, nested functions, - schema persistence, bounded reads, MCP registration, visualization APIs, and Logic UI assets. -- Strict Pyright, Ruff, formatting, compilation, warning-strict tests, web linting, package builds, - dependency audits, and browser QA pass. - -## Dev-Rewrite incremental compiler boundary - -### Changed - -- Added an opt-in source-scoped adapter manifest and extraction contract while preserving Release - 1 complete projections. -- Added persistent extraction caching with fingerprint, path, extractor-version, dependency, and - project/adapter identity invalidation. -- Added reverse-dependency invalidation for added, changed, renamed, deleted, and dependency-changed - sources. -- Added manifest-only stale-state checks so normal MCP reads do not reconstruct the complete - projection. -- Added full/incremental equivalence verification and deterministic build metrics. -- Added first-class relationship-only proposal updates over the existing hash-bound projector. -- Added a lazy function-scoped logic-projection boundary outside the primary architecture graph. - -### Verification - -- Tests cover cache hits, reverse invalidation, renames, dependency changes, deletion, corrupt - caches, failed extraction, atomic preservation, manifest-only stale checks, relationship-only - proposals, lazy logic persistence, and full-build equivalence. -- Strict Pyright, Ruff, formatting, compilation, warning-strict tests, web checks, dependency - audits, source/wheel builds, and isolated wheel installation pass. - -## Release 1.0.0 stable product boundary - -### Changed - -- Designated the complete project-scoped graph, CLI, MCP, changeset, application, rendering, and - visualization surface as DocForge 1.0.0. -- Completed the Nodes, semantic Flow, and convergence Web model. -- Replaced generic node-role circles with semantic cards for Structure, Behavior, Dependency, - Execution, Data, Evidence, Context, and Related contributors. -- Made readable leaf names and node kinds visible on the canvas without truncating long - identifiers. Full qualified identities remain available in tooltips and inspectors. -- Preserved branch-aware hiding so Flow and Web remove upstream-only ancestors while retaining - descendants and alternate paths into the focus. - -### Verification - -- Strict Pyright, Ruff, formatting, compilation, warning-strict tests, HTML/CSS/JavaScript checks, - package builds, and browser QA pass for the Release 1 surface. -- The Release 1 tag is `v1.0.0`. - -## DFG-20 gated application and self-service graph operations - -### Changed - -- Released DocForge 0.13.0 with exact-hash canonical application through CLI and opt-in MCP. -- Added generic Markdown/TOML serialization, rollback, semantic verification, index refresh, and - declared render refresh. Custom adapters retain ownership of canonical serialization. -- Added CLI `reindex`, `visualize`, visualization status, and visualization stop commands. -- Added browser-side node hiding/restoration, bounded source inspection at anchors, and a - scrollable full inspector. -- Replaced the repository quick reference with a dedicated user manual covering setup, CLI, MCP, - visualization, application, adapters, and troubleshooting. - -### Verification - -- Application tests cover all four proposal operations, exact-hash rejection, MCP gating, derived - refresh, and CLI use. -- Visualization tests cover source confinement, browser script validity, hiding controls, and - inspector layout. - -## DFG-19 cross-platform supervised viewer manager - -### Changed - -- Released DocForge 0.12.0 with an authenticated loopback viewer-manager protocol. -- Moved viewer process ownership out of the MCP stdio host and into an OS-supervised per-user - manager. Linux uses systemd user services, macOS LaunchAgents, and Windows Task Scheduler. -- Added `docforge_visualization_status` and changed worker lifetime to a one-hour browser-activity - policy with explicit per-project stop. -- Replaced Unix-socket and inherited-file-descriptor assumptions with loopback TCP and standard - input/output worker control, so the manager protocol works on Windows as well as Unix platforms. - -### Verification - -- Lifecycle tests cover manager worker reuse, browser activity renewal, idle reclamation, explicit - stop, strict MCP surface registration, and manager-mediated visualization startup. - -## DFG-18 persistent visualization lifecycle - -### Changed - -- Released DocForge 0.11.0 with a persistent project-bound visualization worker. -- Replaced browser leases and MCP-owner-process shutdown with an explicit - `docforge_stop_visualization` read tool. -- Added a private, atomically written project-cache registry. It reuses a live worker only when - its authenticated loopback endpoint and exact index snapshot identity match the current request. -- Removed the parent-process `Popen` lifecycle dependency by spawning the session-isolated worker - directly, so no process cleanup warning or parent lifetime remains coupled to the browser. - -### Verification - -- A process-boundary test terminates the launcher, confirms the viewer remains live, confirms a - separate runner reuses its URL, and confirms the explicit stop tool terminates it. -- Focused warning-strict lifecycle and MCP contract tests pass. - -## DFG-17 relationship-aware graph and upstream flow - -### Changed - -- Released DocForge 0.10.0 with the fixed `graph-browser@8` template. -- Assigned generic semantic families, distinct colors, line patterns, and directional endpoint - symbols to common structure, execution, data, dependency, evidence, and context relations. -- Added a static visible-relationship key shared by Nodes and Flow, including deterministic - fallback styling for project-defined relations. -- Renamed topology-derived navigation from ambiguous Children and Edge language to Focus node, - Outgoing paths, and Incoming & lateral. -- Implemented bounded upstream Flow layers. Calls, dispatches, launches, activations, and writes - keep declared direction; reads, imports, and dependencies reverse for lineage presentation; - structure, evidence, context, and unknown relations remain excluded. -- Separated relationship-line and context-node CSS classes to prevent style inheritance and DOM - selector collisions. - -### Verification - -- A deterministic JavaScript harness covers relation classification, fallback styling, semantic - direction, evidence exclusion, upstream membership, dependency reversal, and layered placement. -- Browser interaction QA verifies distinct line colors, dash patterns, endpoint markers, exact - relationship keys, Nodes-to-Flow switching, evidence exclusion, and the destination-on-right - layout without console or page errors. -- HTML, CSS, and JavaScript validation, strict Pyright, Ruff, formatting, compilation, dependency - locks, npm audit, the complete warning-strict suite, and diff checks pass. - -### Limits - -- Flow operates on the already bounded neighborhood returned for the current focus and depth. -- Unknown project-defined relations receive deterministic Nodes styling but do not enter Flow until - their semantic direction is declared in the fixed relation map. -- Cycles are bounded by visited-node traversal. A later gate may add explicit cycle-group rendering - if real project graphs demonstrate that need. - -## DFG-16 browser asset quality gate - -### Changed - -- Added pinned ESLint, Stylelint, CSS-tree, and HTML Validate development tooling. -- Added one `npm run lint:web` gate that extracts the exact embedded viewer assets without writing - generated repository files. -- Validated a freshly rendered fixture manual in addition to the graph viewer. -- Corrected viewer landmark names, explicit input type, ARIA group semantics, inline legend styles, - and HTML doctype casing. - -### Verification - -- HTML Validate passes the served graph document and a freshly rendered manual. -- Stylelint and CSS-tree pass the embedded stylesheet with syntax and property-value validation. -- ESLint passes the embedded browser script with recommended browser rules and no inline disables. -- Strict Pyright, Ruff, formatting, compilation, all 52 warning-strict tests, dependency locks, and - diff checks pass. - -## DFG-15 strict static typing gate - -### Changed - -- Made the existing strict Pyright configuration resolve DocForge's `.venv` automatically. -- Converted validated TOML, JSON, subprocess, socket, MCP, render, and visualization boundaries - from unknown dynamic values into explicit checked types. -- Kept runtime validation and fail-closed behavior at every untrusted input boundary. -- Made strict `pyright` an explicit repository development gate. - -### Verification - -- Pyright reports zero errors, warnings, or informational diagnostics across all source modules. -- Ruff lint and formatting, Python compilation, all 52 warning-strict tests, and diff checks pass. - -## DFG-14.1 detached viewer lifecycle correction - -### Changed - -- Released DocForge 0.8.1 with the existing `graph-browser@5` interface. -- Moved the loopback listener into a detached worker so MCP transport teardown cannot kill an - active viewer. -- Bound the worker to the longer-lived MCP client host plus the existing browser lease and startup - grace. - -### Verification - -- Added a process-boundary regression test that exits the launching transport process, verifies the - viewer still responds, and then verifies lease expiry. -- Retained the in-process listener tests for token confinement, read-only behavior, stale-index - rejection, and lease renewal. - -## DFG-14 durable graph navigation - -### Changed - -- Released the fixed `graph-browser@5` template and DocForge 0.8.0. -- Kept the loopback listener alive across short-lived MCP standard-input transactions with a - browser-renewed lease, while preserving explicit process termination and bounded abandoned-page - cleanup. -- Added a visible disconnected state instead of leaving stale controls to fail silently. -- Added pointer and keyboard resizing for both side panels. -- Made the unblurred modal natively resizable and draggable by its constrained title bar. -- Added generic topology-derived Primary focus, Children, and Edge & context navigation sections. -- Arranged neighborhoods by shortest-hop rings and applied distinct role palettes that darken - progressively by hop distance, capped at fifty percent. -- Kept all category and color decisions client-side without changing project graph facts. - -### Verification - -- Focused HTTP tests cover heartbeat renewal, bounded lease expiry, non-daemon listener ownership, - and the unchanged token/read-only boundary. -- A deterministic JavaScript harness proves topology roles, hop rings, and distance shading. -- Embedded JavaScript syntax and interaction-contract checks cover panel resizing, modal movement - and resizing, unblurred backdrop behavior, grouped navigation, and lease renewal. -- Ruff, formatting, compilation, the complete warning-strict suite, and live project-bound viewer - checks pass. - -### Limits - -- Panel widths, modal geometry, viewport position, and open dialog state are not persisted. -- Topology roles are presentation aids. They do not replace project-authored relationship meaning. -- Background-browser timer throttling is tolerated by the three-minute lease but may delay cleanup. - -### Next gate - -No further gate is planned. Measure use before adding saved layouts, minimaps, or export. - -## DFG-13 graph activation reliability - -### Changed - -- Released the fixed `graph-browser@4` template. -- Delayed SVG pointer capture until movement crosses the four-pixel drag threshold so an ordinary - click remains targeted at the graph node and reaches the modal inspection handler. -- Preserved pointer capture and click suppression for actual canvas drags. -- Added an explicit hidden-state rule so rendered neighborhoods remove the empty-canvas instruction. -- Kept the token-bound HTTP surface, graph data, and listener lifetime unchanged. -- Released the compatible fix as DocForge 0.7.3. - -### Verification - -- Focused interaction-contract checks distinguish click setup from drag pointer capture and cover - empty-state hiding. -- Embedded JavaScript syntax validation, Ruff, formatting, compilation, and the complete - warning-strict 49-test DocForge suite pass. - -### Limits - -- The listener remains owned by the MCP process and closes when that process exits. -- Browser state remains client-local and is not persisted. - -### Next gate - -No further gate is planned. Measure graph-browser use before adding history, comparison, or editing -surfaces. - -## DFG-12 modal node inspection - -### Changed - -- Released the fixed `graph-browser@3` template with a native modal node inspector. -- Made graph-node activation inspect full validated node metadata and content without replacing the - current neighborhood or viewport. -- Added mouse and keyboard activation plus Escape, explicit close controls, and backdrop dismissal. -- Added a separate Explore neighborhood action for intentional graph recentering. -- Kept the existing token-bound, read-only HTTP surface and exact-node endpoint unchanged. -- Released the compatible change as DocForge 0.7.2. - -### Verification - -- Focused HTTP interaction-contract checks cover the dialog, inspection handler, and explicit - neighborhood action. -- Embedded JavaScript syntax validation and the complete warning-strict DocForge suite pass. - -### Limits - -- Dialog state is session-local and is not persisted in the URL. -- Node content remains plain text and is not rendered as trusted HTML. -- The right sidebar continues to describe the current root neighborhood. - -### Next gate - -No further gate is planned. Measure graph-browser use before adding history, comparison, or editing -surfaces. - -## DFG-11 graph viewport navigation - -### Changed - -- Released the fixed `graph-browser@2` template with pointer-centered mouse-wheel zoom. -- Added left-button drag pan with pointer capture and a four-pixel movement threshold. -- Preserved normal node activation by suppressing click navigation only after an actual drag. -- Added keyboard-operable zoom-in, zoom-out, and reset buttons plus a live zoom percentage. -- Reset the viewport whenever a new root neighborhood loads. -- Kept all viewport behavior client-side without adding HTTP endpoints or project authority. -- Released the compatible change as DocForge 0.7.1. - -### Verification - -- Focused HTTP tests and embedded JavaScript syntax validation cover button zoom, reset, - pointer-centered wheel zoom, left-drag pan, and preserved node-click handling. The current agent - runtime did not expose its rendered browser automation connection, so no rendered interaction - claim is made for this gate. -- The complete warning-strict DocForge suite passes. - -### Limits - -- Viewport position is session-local and is not persisted. -- The radial layout itself remains deterministic and fixed. -- A minimap, saved node positions, and alternate layouts remain outside the current contract. - -### Next gate - -No further gate is planned. Measure dense-graph use before adding more navigation or layout -features. - -## DFG-10 project-bound graph visualization - -### Changed - -- Added the fixed `docforge_visualize` MCP read tool to generic, read-only adapter, and - proposal-enabled adapter servers. -- Added the built-in `graph-browser@1` HTML/CSS/JavaScript template with project overview, family - filtering, lexical search, exact node content, and bounded neighborhood traversal. -- Bound the ephemeral HTTP listener to `127.0.0.1` on an operating-system-selected port. -- Added an unguessable per-process URL token and rejected every non-token path. -- Exposed only fixed `GET` and `HEAD` endpoints. Rejected POST, PUT, PATCH, and DELETE. -- Validated the complete project and index once per MCP invocation, then served fast queries from - the exact validated SQLite snapshot. -- Rejected index replacement or alteration after launch and required reinvocation to refresh. -- Accepted no project root, database path, SQL, template path, bind address, command, or renderer. -- Released the capability as DocForge 0.7.0 without changing canonical-write policy. - -### Verification - -- Protocol tests exercised the new tool through the official in-memory MCP transport. -- HTTP tests proved token confinement, loopback binding, security headers, read-only methods, - deterministic results, exact node retrieval, and snapshot invalidation. -- Cross-project tests ran two simultaneous visualization servers and proved separate project data, - ports, tokens, and indexes. -- The complete warning-strict DocForge suite passed. -- Ani-web proof loaded 3,289 nodes and 6,292 edges. After one full validation, the graph overview - returned in approximately 0.30 seconds and a node neighborhood in approximately 0.03 seconds. - -### Limits - -- The browser is a validated index snapshot, not a live canonical-file watcher. -- It is reachable only from the machine running the MCP process. -- It does not persist, publish, or externally host a visualization. -- It does not infer relationships beyond the configured project's graph. - -### Next gate - -No further gate is planned. Measure actual graph-browser use before adding layout modes, exports, -remote access, or project-declared visualization templates. - -## DFG-9 controlled application decision - -### Decision - -- Retained manual canonical integration as the permanent DocForge 0.x policy. -- Added no application command to the library, CLI, or MCP server. -- Kept project builders, tests, Git, deployment, and publication under developer or project-owner - control. -- Required a new approved gate with measured multi-project evidence before canonical application - can be reconsidered. - -### Evidence - -- DFG-8 produced one real content-only AssetForge proposal and one manual chapter replacement. -- Validation, conflicts, diffs, previews, and stale-source handling were already automated. -- Manual integration completed without an error, lost work, or meaningful repeated cost. -- Automating the remaining step would require canonical writers, developer authorization, atomic - rollback, failure recovery, and project-format ownership that the current evidence does not - justify. -- Existing exact-surface MCP tests prohibit application tools, and proposal tests preserve - canonical source bytes. - -### Limits - -- DocForge does not apply, commit, push, build, deploy, or publish canonical changes. -- Reopening the decision requires a separately approved, versioned contract and cannot add MCP - canonical application. - -### Next gate - -No further DFG gate is planned. Continue measured adoption through project-owned integrations. - -## DFG-0 contract freeze and DFG-1 standalone read-only core - -### Changed - -- Created the standalone DocForge repository and versioned the project, node, edge, result, and - reserved changeset contracts. -- Added one-root project descriptors with confined canonical, authority, cache, and index paths. -- Added generic Markdown front matter and TOML node loading, stable IDs, typed relationships, - authority classes, limits, deterministic ordering, dependency-cycle validation, and hashes. -- Added atomic SQLite FTS5 indexes with project-root fingerprints, source revisions, logical row - validation, stale rejection, and preservation of the previous index when rebuilds fail. -- Added exact lookup, bounded search and filtering, backlinks, dependencies, impact traversal, and - cited token-budgeted context compilation with explicit omissions. -- Added deterministic JSON CLI commands for project information, validation, index operations, - retrieval, traversal, and context compilation. -- Added two unrelated generic fixtures. No Worldforge or AssetForge vocabulary entered the core. - -### Verification - -- Ruff lint and format checks passed. -- Python compilation passed. -- All 13 unit and integration tests passed. -- Tests covered root and symbolic-link escapes, unknown configuration, cache overlap, duplicate and - broken graph state, dependency cycles, source-set changes, stale indexes, tampered rows, - cross-project cache reuse, query-time source changes, deterministic retrieval, and bounded context. -- Installed CLI proof built and checked a temporary project index, returned the expected search - result, selected the required node and dependency, used 153 of 180 estimated tokens, and reported - the omitted proof node. - -### Limits - -- No MCP server exists yet. -- No changeset or write operation exists. -- No project adapter or renderer exists. -- The token estimator is deliberately conservative and lexical; measured project adoption remains a - later gate. - -### Next gate - -DFG-2: expose only the proven read operations through a project-bound local stdio MCP server. - -## DFG-2 project-bound read-only MCP server - -### Changed - -- Pinned the official stable MCP Python SDK to the compatible `mcp>=1.28,<2` release line. -- Added a local standard input/output server bound to one immutable project root at startup. -- Exposed eleven read tools for project health, contract boundaries, exact lookup, search, metadata - filtering, backlinks, dependencies, impact, bounded context, source validation, and render status. -- Added project identity, root fingerprint, revision, source hash, adapter version, staleness, server - version, and an untrusted-content warning to tool results. -- Added structured domain failures for missing nodes, stale indexes, and oversized results without - returning partial content. -- Exposed no write, proposal, arbitrary file, shell, Git, build, deployment, publication, or - project-switching operation. -- Kept cache rebuilding as an explicit CLI integration action. MCP queries fail closed when the - derived index is missing or stale. - -### Verification - -- Ruff lint and format checks passed. -- Python compilation passed. -- All 19 core, CLI, and MCP tests passed with `ResourceWarning` treated as an error. -- Protocol tests called all eleven tools through the official in-memory MCP transport. -- A separate subprocess test initialized the server through real stdio transport and retrieved only - its configured fixture project. -- Tests proved the exact read-only tool surface, fixed project identity, structured missing and stale - failures, output limits, explicit omissions, safe fallback when passive Git revision detection is - unavailable, and the absence of canonical write tools. - -### Limits - -- The server cannot create changesets or proposals yet. -- The server cannot rebuild its own index. -- Render status reports `not_configured` until DFG-4 defines renderer orchestration. -- Worldforge and AssetForge adapters remain unopened. - -### Next gate - -DFG-3: add isolated, hash-bound proposal changesets without canonical write authority. - -## DFG-3 isolated changesets - -### Changed - -- Added a confined changeset root and project-declared proposal writers with explicit family and - operation permissions. -- Bound proposal identity once at MCP server startup. Tools cannot select or impersonate a writer. -- Added ordered, project-bound JSON changesets with canonical base revision and source hash, root - fingerprint, creator, optimistic changeset hash, expected node hashes, rationales, and structured - relationship changes. -- Added create, update, same-format move, and delete proposals. Deletes require exact removal of every - incident relationship; required profile nodes cannot be deleted. -- Added deterministic projected graph validation and structured metadata, content, source, and - relationship diffs without changing canonical files. -- Added exact stale-base, stale-node, stale-changeset, ownership, family, operation, path, graph, - source, size, and cross-proposal conflict failures. -- Added process-safe file locking, atomic replacement, symbolic-link rejection, source confinement, - configured limits, and rollback if canonical inputs change during proposal storage. -- Added nine MCP proposal tools, including stale-safe proposal inspection and bounded listing. - Canonical application, previews, arbitrary commands, Git mutation, builds, deployment, and - publication remain absent. - -### Verification - -- Focused core tests cover all four operation types, deterministic diffs, canonical immutability, - simultaneous append serialization, overlapping changesets, stale identities, atomic failures, - family permissions, ownership, target confinement, symbolic links, and configuration validation. -- Protocol tests call all four mutation tools through the official in-memory MCP transport and prove - fixed writer identity, isolated output, validation, deterministic diff retrieval, and the disabled - mutation behavior of a server without a writer. -- Ruff formatting and lint checks, Python compilation, all five JSON schema parses, and the locked - dependency check passed. -- All 29 core, CLI, changeset, concurrency, in-memory MCP, and real stdio tests passed with - `ResourceWarning` treated as an error. - -### Limits - -- Changesets are proposals only. DocForge does not apply them to canonical project files. -- A changeset may operate on a node once; a later operation on the same node requires another - changeset after external integration. -- Moves preserve the canonical source format. Cross-format conversion belongs to a future adapter or - explicit migration contract. -- Preview generation and renderer orchestration remain unopened. - -### Next gate - -DFG-4: add deterministic previews and confined renderer orchestration without canonical application. - -## DFG-4 deterministic previews and renderer orchestration - -### Changed - -- Added optional project-declared template, preview, view, and derived-output configuration with - strict root confinement, overlap rejection, stable view IDs, and configured size limits. -- Added an explicit renderer protocol backed by a closed built-in registry. Configuration cannot - name commands, modules, executable paths, or undeclared renderers. -- Added the `generic_html` renderer with pinned `markdown-it-py` CommonMark parsing, disabled raw - HTML, fixed safe template tokens, deterministic node ordering, navigation, metadata, content, and - relationship output. -- Added render identities covering canonical and proposal inputs, node and edge identities, view - configuration, template hash, renderer contract, and exact Markdown parser version. -- Added atomic per-view CLI rendering, non-writing render status, and isolated changeset previews. - Input changes detected before replacement preserve prior output. -- Added `docforge_preview_changeset` to MCP and made `docforge_render_status` report configured view - hashes and state. MCP cannot render declared project output or select a renderer or command. -- Split shared configuration validation, render configuration, renderer contract, and orchestration - into focused modules instead of expanding the project loader or MCP translation layer. - -### Verification - -- Renderer tests prove repeatable identities and bytes, current and stale status, isolated previews, - escaped raw HTML, CommonMark conversion, unchanged canonical and declared output, configured - limits, symbolic-link rejection, and preservation of prior output after invalid or changing input. -- Configuration tests reject command-like fields, unsupported renderer IDs, protected output paths, - undeclared views, oversized templates and output, and unsafe symbolic links. -- CLI tests cover declared render, render status, isolated preview, and structured unknown-view - failure. Protocol tests exercise preview through the official in-memory MCP transport and prove - declared output remains absent. -- Ruff formatting and lint checks, Python compilation, all five JSON schema parses, and the locked - dependency check passed. -- All 35 core, CLI, changeset, concurrency, renderer, in-memory MCP, and real stdio tests passed with - `ResourceWarning` treated as an error. - -### Limits - -- The first built-in renderer emits one self-contained HTML file per view. Multi-file asset bundles - and project-specific view models remain future adapter work. -- Preview generation validates proposals but does not apply them to canonical documentation. -- Declared project-output rendering is an explicit local CLI integration action, not an MCP tool. -- Worldforge and unrelated-project adapters remain unopened. - -### Next gate - -DFG-5: reproduce Worldforge semantics and generated output through a shadow-only adapter without -changing the live workflow. - -## DFG-5A Worldforge non-AssetForge shadow proof - -### Changed - -- Added a reusable adapter contract with ordered project projections, adapter metadata, root and - identity validation, a standard read-index bridge, and byte-exact artifact comparison. -- Generalized the derived index boundary to accept any immutable project service without changing - generic project loading, proposals, rendering, or MCP behavior. -- Added a Worldforge-local shadow adapter that translates the existing normalized manual index into - core nodes and edges while retaining acceptance and relationship provenance as adapter metadata. -- Kept Worldforge-specific weighted search, backlink ordering, context profiles, and render-model - composition in the Worldforge adapter. -- Excluded the independently managed AssetForge family and combined manual output from this subgate. - -### Verification - -- The shadow graph matched 522 nodes and 805 edges exactly and built through DocForge's standard - disposable index. -- Exact lookup, three weighted searches, active-development filtering, Phase 5 backlinks, and Phase - 5 dependency traversal matched the current Worldforge index. -- Active, Phase 3, and Phase 5 context packs were byte-repeatable. Active also matched the current - derived context cache. -- All 31 generated outputs that do not require AssetForge matched committed bytes. The proof wrote - only temporary derived files and removed them afterward. -- DocForge adapter-contract tests cover standard index use, graph and metadata rejection, identity - changes, cache confinement, and complete byte-exact artifact comparison. - -### Limits - -- The remaining 10 AssetForge nodes, 25 incident edges, AssetForge context profile, and combined - `manual/manual.html` output are not read or rebuilt by this proof. -- The shadow adapter is an explicit local command. It is not discoverable or executable through the - normal MCP server. - -### Next gate - -DFG-5B: complete the full-family shadow proof when AssetForge is explicitly authorized. - -## DFG-5B Worldforge full-family shadow completion - -### Changed - -- Expanded the Worldforge-local adapter from the partial proof to all source families, including - the ten AssetForge nodes and their 25 incident edges. -- Added a Worldforge-owned AssetForge context profile with deterministic source ordering, stable - node and source citations, a hard token budget, and explicit omission records. -- Routed the shadow render comparison through the complete Worldforge builder output inventory, - including the combined `manual/manual.html` output. -- Released the adapter boundary as DocForge 0.4.0. Worldforge-specific context, query, and render - policy remains outside the generic core. - -### Verification - -- The shadow graph matched all 532 nodes and 830 edges exactly through DocForge's standard - disposable index. -- Exact lookup, five weighted searches, development and AssetForge filters, backlinks, and phase - and AssetForge dependency traversal matched the current Worldforge index. -- Active, Phase 3, Phase 5, and AssetForge contexts were byte-repeatable. Active matched the current - cache; AssetForge included all ten nodes under the normal budget. -- A reduced AssetForge budget retained the required root, stayed within budget, and recorded - omissions. An invalid budget failed before producing a context. -- All 32 generated outputs matched committed bytes. The proof wrote only temporary derived files - and removed them afterward. - -### Limits - -- The adapter remains an explicit local shadow command and is not loaded by the normal MCP server. -- Canonical application and public deployment remain outside DocForge. -- Reuse outside Worldforge is not yet proven. - -### Next gate - -DFG-6: prove the generic core with an unrelated project and simultaneous project-isolated servers. - -## DFG-6 unrelated-project proof - -### Changed - -- Added an Awesome Ski Game fixture using the generic project descriptor, five unrelated node - families, six relationships, a bounded `ride-day` context, one proposal writer, and one declared - field-guide view. -- Added an end-to-end proof covering generic loading, indexing, exact graph counts, search, filters, - dependency traversal, deterministic bounded context, isolated updates, validation, diffs, and - escaped preview rendering. -- Added a source guard that rejects Worldforge, AssetForge, phase, or villager vocabulary in the - generic core. -- Added a live isolation proof with two simultaneous MCP server subprocesses bound to Awesome Ski - Game and Alpha Documentation. - -### Verification - -- Awesome Ski Game loaded through `adapter = "generic"` with five nodes, six edges, and trail, - riding, safety, session, and proof families. -- The 300-token context retained its required session node, stayed within budget, recorded - omissions, and reproduced exactly. -- The proposal changed only its isolated changeset and preview. Canonical sources and declared - output remained unchanged, and raw HTML was escaped. -- Both live servers returned their own project identity and nodes, rejected the other project's - stable IDs, and wrote same-named changesets and previews only under their bound roots. -- The complete DocForge suite passes with warnings treated as errors. - -### Limits - -- This proof does not adopt DocForge inside Worldforge or enable any canonical write path. -- The Worldforge adapter and generic Awesome Ski Game fixture remain separate ownership paths. -- HTTP transport, accounts, and web administration remain unopened. - -### Next gate - -DFG-7: adopt project-bound DocForge retrieval for real Worldforge read-only tasks with measured -quality and a documented rollback path. - -## DFG-7 Worldforge read-only adoption - -### Changed - -- Added an explicit adapter-backed read-only MCP constructor that accepts one validated project - service and an optional project-owned context provider. -- Kept adapter discovery, session selection, family partitioning, and project context policy outside - the generic core. -- Added Worldforge-owned descriptors and separate Worldforge and AssetForge sessions with disjoint - derived indexes and the exact fixed read tool surface. -- Added durable retrieval, context-size, omission, latency, stale-state, and rollback evidence. -- Released the adapter-backed read-only boundary as DocForge 0.5.0. - -### Verification - -- Eight real Worldforge and AssetForge retrieval tasks retained every required node in the first - five results; seven matched the current manual index result set exactly. -- Active and Phase 5 contexts reduced the full structured Worldforge session by 97.3% and 98.2%. - Tight budgets reported every omitted candidate. -- Two simultaneous MCP processes retained separate identities, exposed only read tools, rejected - cross-family node access, and kept Worldforge stale-state failure isolated from AssetForge. -- Checked DocForge search measured 84.4 ms median in the adoption run versus 18.8 ms for the current - manual index. The additional validation cost remained below 0.1 seconds. -- The DocForge suite, Worldforge manual suite, integration tests, shadow proof, format, lint, and - generated-output checks passed. - -### Limits - -- DocForge read-only operations do not write canonical Worldforge files or replace its builder. -- Adapter-backed read-only service construction is explicit; the generic server does not discover - project adapters or sessions. -- AssetForge proposal access, canonical application, publication, and deployment remain closed. - -### Next gate - -DFG-8: adopt isolated AssetForge-only proposals with explicit review and the canonical Worldforge -build and verification workflow. - -## DFG-8 AssetForge proposal adoption - -### Changed - -- Added confined adapter proposal settings for canonical sources, writer permissions, changesets, - templates, previews, and declared review output. -- Added a project-owned proposal-validation hook while retaining generic hash, permission, graph, - conflict, atomic-storage, diff, and preview enforcement in the core. -- Moved generic Markdown and TOML source-layout validation behind the generic project owner so an - adapter can enforce its own canonical format without weakening graph validation. -- Added an explicit full-surface server constructor for one configured project service and one - startup-bound writer. -- Marked base, content, source, adapter-source, and index conflicts as stale tool results. -- Released the proposal-enabled adapter boundary as DocForge 0.6.0. - -### Verification - -- OpenClaw was bound to the AssetForge-only session and update-only permission. -- One real proposal updated an existing AssetForge chapter, validated, produced a structured diff, - and rendered an isolated escaped preview before manual integration. -- The Worldforge canonical builder and manual index rebuilt after review. The original changeset - then failed with `base_conflict` against the new canonical source hash. -- Live tests rejected create, metadata, root-manifest, relationship, and cross-family access; - rejected an overlapping changeset; escaped raw HTML; preserved canonical bytes; and rejected - stale canonical sources. -- The complete DocForge and Worldforge manual suites, shadow proof, generated-output check, format, - and lint passed. - -### Limits - -- DFG-8 permits content-only updates to existing AssetForge chapters. Create, move, delete, - metadata, relationship, and manifest changes remain closed. -- DocForge does not apply canonical changes, run the Worldforge builder, use Git, deploy, or publish. -- A developer must review and manually integrate accepted prose. - -### Next gate - -DFG-9: decide from evidence whether a narrowly scoped developer-only application command is -justified or manual integration should remain permanent. +The aggregate gate passed formatting, Python and web lint, strict types, compilation, public +contract checks, tests, dependency validation, package builds, and the maintained benchmark. diff --git a/docs/APPLICATION_DECISION.md b/docs/CANONICAL_APPLICATION.md similarity index 72% rename from docs/APPLICATION_DECISION.md rename to docs/CANONICAL_APPLICATION.md index 8eb5def..3e9baf3 100644 --- a/docs/APPLICATION_DECISION.md +++ b/docs/CANONICAL_APPLICATION.md @@ -1,8 +1,4 @@ -# Canonical application decision - -**Status:** Superseded by the DocForge 0.13 hash-bound application contract. - -## Decision +# Canonical application DocForge may apply one isolated changeset to canonical project sources through an explicit, project-bound canonical applier. Application is available through both CLI and MCP. It is never an @@ -17,7 +13,11 @@ files. - CLI requires `apply CHANGESET_ID --changeset-hash SHA256 --applier WRITER_ID`. - MCP registers `docforge_apply_changeset` only when the server starts with an explicit canonical applier identity and compatible applier implementation. -- The changeset creator and applier identity must match a configured proposal writer. +- The changeset creator must be a configured proposal writer. +- Application defaults to changesets created by the applier identity. A project-owned server may + explicitly bind additional configured proposal writers that its applier is authorized to accept. +- Cross-identity acceptance does not let the applier edit the contributor's proposal and does not + give the contributor an application tool. - The exact final changeset hash is required. Any proposal mutation invalidates an earlier approval. @@ -31,17 +31,15 @@ checks the derived index and regenerates declared render views. Application does not run project commands, tests, shell operations, Git, deployment, publication, or arbitrary renderers. Those remain with the owning project workflow. -## Why the earlier decision changed +## Safety contract -The earlier DFG-9 decision preserved manual integration because there was not yet repeated evidence -for canonical application. Later multi-project use produced recurring proposal application work, -stale-index round trips, and an explicit user requirement for faster approved integration. The new -contract addresses the original safety concerns with: +The application boundary requires: - exact changeset-hash approval; - startup-bound applier identity; +- an explicit accepted-writer allowlist for any cross-identity application; - project-owned serializers for custom adapters; -- canonical path and symlink confinement; +- canonical path and symbolic-link confinement; - rollback and semantic round-trip verification; - deterministic derived-state refresh; and - complete separation from Git, builds, deployment, and publication. diff --git a/docs/COMPATIBILITY.md b/docs/COMPATIBILITY.md index 4907d41..01e0cbc 100644 --- a/docs/COMPATIBILITY.md +++ b/docs/COMPATIBILITY.md @@ -2,8 +2,8 @@ Milestone 0 establishes DocForge2 as the successor repository without renaming or replacing the working DocForge interfaces. Compatibility changes require an explicit decision, a contract-test -update, and migration guidance. DocForge 1.4.0 preserves that baseline and adds the adapter, -rendering, recovery, and release surfaces recorded below. +update, and migration guidance. DocForge 2.0.0 preserves that baseline and the complete 1.4 +adapter, rendering, recovery, and release surfaces recorded below. The compatibility gate is: @@ -69,9 +69,9 @@ names and arguments remain supported. Additive commands, tools, and response fie Removing or changing an existing name, required argument, stable error code, or safety boundary requires an explicit compatibility decision. -Version `1.4.0` comes from one `docforge._version` authority. The four maintained executable -surfaces report `docforge 1.4.0`, `docforge-mcp 1.4.0`, -`python -m docforge.reference_mcp 1.4.0`, and `docforge-viewer-manager 1.4.0` for `--version`. +Version `2.0.0` comes from one `docforge._version` authority. The four maintained executable +surfaces report `docforge 2.0.0`, `docforge-mcp 2.0.0`, +`python -m docforge.reference_mcp 2.0.0`, and `docforge-viewer-manager 2.0.0` for `--version`. Generated generic and adapter client configurations include and hash-bind the same `docforge_version`. @@ -285,7 +285,7 @@ other users and ordinary path access; deliberate arbitrary tampering by another same operating-system UID is outside the compatibility boundary. The historical `v1.0.0` release carried distribution metadata `1.0.0` while its module and MCP -runtime reported `0.15.0`. Version 1.4.0 records that inherited mismatch in its maintained +runtime reported `0.15.0`. Version 2.0.0 records that inherited mismatch in its maintained migration proof and resolves current identity through one authority. See [migrating from v1](MIGRATING_FROM_V1.md). diff --git a/docs/CONTRACT.md b/docs/CONTRACT.md index 780f15d..a7554f1 100644 --- a/docs/CONTRACT.md +++ b/docs/CONTRACT.md @@ -1,4 +1,4 @@ -# DocForge 1.4 contract +# DocForge 2.0 contract ## Authority boundary @@ -34,7 +34,7 @@ commit when Git is available; it cannot change repository state. - Reference adapter configuration: `schemas/reference-adapter.schema.json`, version 1. - Index schema: version 3, disposable and reproducible. - Index attestation: schema version 1, disposable and reproducible. -- Distribution, Python package, CLI, generic MCP, reference MCP, and viewer manager: version 1.4.0. +- Distribution, Python package, CLI, generic MCP, reference MCP, and viewer manager: version 2.0.0. - Incremental extraction cache: version 1, disposable and reproducible. Schema files describe the generic interchange contract. Runtime validation remains responsible for @@ -42,8 +42,8 @@ path confinement, source hashing, relationship resolution, dependency cycles, pr state, and adapter-specific rules that JSON Schema cannot prove by itself. `src/docforge/_version.py` is the sole package-version authority. The maintained executable -surfaces report exactly `docforge 1.4.0`, `docforge-mcp 1.4.0`, -`python -m docforge.reference_mcp 1.4.0`, and `docforge-viewer-manager 1.4.0` for `--version`. +surfaces report exactly `docforge 2.0.0`, `docforge-mcp 2.0.0`, +`python -m docforge.reference_mcp 2.0.0`, and `docforge-viewer-manager 2.0.0` for `--version`. Generated generic and adapter client configurations bind `docforge_version` into their validated hashes. diff --git a/docs/MCP_CONTRACT.md b/docs/MCP_CONTRACT.md index d1c345d..fde17a5 100644 --- a/docs/MCP_CONTRACT.md +++ b/docs/MCP_CONTRACT.md @@ -191,7 +191,10 @@ An explicit project integration may construct the full fixed surface only after confined proposal policy and startup-bound writer. Adapter proposal validators may narrow the writer's declared operations further. They cannot add arbitrary tools or weaken core changeset validation. The fixed application tool is registered only through the separate canonical applier -gate. +gate. Application accepts only changesets created by the applier identity unless the project-owned +factory explicitly supplies `accepted_proposal_writers`. Every accepted identity must already be a +configured proposal writer. This allowlist permits review and acceptance across process identities; +it does not grant proposal mutation or application tools to a contributor process. ## Isolated proposal tools diff --git a/docs/MIGRATING_FROM_V1.md b/docs/MIGRATING_FROM_V1.md index eb24fbe..16a527c 100644 --- a/docs/MIGRATING_FROM_V1.md +++ b/docs/MIGRATING_FROM_V1.md @@ -22,13 +22,13 @@ Disposable index and cache schemas may change. Rebuild them rather than copying ## Maintained v1.0.0 migration evidence `make migration-m5` archives and executes the actual annotated `v1.0.0` release, then opens its -fixture, index, and active proposal through DocForge 1.4.0. The frozen tag object is +fixture, index, and active proposal through DocForge 2.0.0. The frozen tag object is `2d7d306a37da89f1c860c7f0be161c45386acf61`; it identifies commit `593c173b453236a6872d0a4e88e7a51a67a21cde`. The tagged release contains an inherited identity mismatch that the migration proof records rather than hiding: distribution metadata says `1.0.0`, while `docforge.__version__` and the MCP -server report `0.15.0`. DocForge 1.4.0 replaces that duplicated state with one authoritative +server report `0.15.0`. DocForge 2.0.0 replaces that duplicated state with one authoritative version and requires its package and server values to agree. The maintained fixture evidence is exact: diff --git a/docs/MILESTONE_0_CLOSEOUT.md b/docs/MILESTONE_0_CLOSEOUT.md deleted file mode 100644 index 68cfd6a..0000000 --- a/docs/MILESTONE_0_CLOSEOUT.md +++ /dev/null @@ -1,133 +0,0 @@ -# DocForge2 Milestone 0 closeout - -Milestone 0 establishes the public DocForge2 successor without changing the supported `docforge` -product identity or the legacy DocForge repository. - -## Repository state - -- Public successor: -- Successor default branch: `main` -- Successor development branches: `main` and `dev` -- Local `origin`: `forgejo@repo.andraxion.net:administrator/DocForge2.git` -- Local `legacy`: `forgejo@repo.andraxion.net:administrator/DocForge.git` -- Legacy repository: private, nonempty, unarchived, and defaulted to `main` -- Existing annotated tag: `v1.0.0` - -`main` is the last completely verified milestone. `dev` is the integration branch for the next -explicitly activated milestone and begins at the same commit. Historical development branch names -remain in the legacy repository as v1 evidence; they are not replicated as active DocForge2 -branches. - -No tag, release, release announcement, or production integration change was made. - -## Preserved lineage - -The migration began from the advanced -`codex/language-agnostic-onboarding` tip -`bb13258861175aafd0e6c03c1a5235cbaddf6db2`, nine linear commits beyond the legacy `main`. - -The original seven-file no-AST working patch had SHA-256: - -```text -8cd10759c232cd4cf8c5eb024e31bbfed355e0be31fc3e732e1567c1a19a887e -``` - -It was preserved in commit `6c05607` before other integration. The independent local-only adapter -lifecycle commit `1ef76f0271bb339bc0d7eeb62f996d6d680548cb` was retained unchanged and merged by -`15a9130`. The resulting successor `main` contains every commit that was reachable from any local -ref before migration. No rebase, reset, squash, shallow seed, or older-remote seed was used. - -A verified pre-migration bundle was written outside the repository: - -```text -/tmp/DocForge2-milestone0-candidate-20260729.bundle -SHA-256 6cccd4ae2a65fa2d81e324e4592bee488b111942a496fb85f7ac6b8bd319ea2d -``` - -## Legacy integrity - -Before and after the successor push, the legacy repository advertised these exact heads: - -```text -Dev-Rewrite 73165c9f511485ea397aaa00c5e0047bd3e635e2 -DocForge-Dev 82b3b905212e7949c0a440879f3bf866197c3927 -codex/adapter-authoring-docs 7bc2ac1e3f7f9cf23ec4dcad108f9bb59978ca73 -codex/language-agnostic-onboarding bb13258861175aafd0e6c03c1a5235cbaddf6db2 -main 9fcafc290c5b5ee9cb83c4c3b2ff600f75210c8e -``` - -The annotated `v1.0.0` tag object remained -`2d7d306a37da89f1c860c7f0be161c45386acf61`, pointing to -`593c173b453236a6872d0a4e88e7a51a67a21cde`. - -No push, deletion, visibility change, archive operation, or default-branch change was performed -against `legacy`. - -## Compatibility and correctness - -The stable guarantees are recorded in -[`COMPATIBILITY.md`](COMPATIBILITY.md). The dedicated contract gate verifies: - -- Distribution, package, imports, and three executable names. -- CLI command and MCP tool names. -- Published JSON schemas and representative runtime envelopes. -- One-method `load_projection()` adapters. -- Optional incremental behavior and full-projection equivalence. -- Canonical JSON changeset hashing. -- Complete no-AST behavior, including pre-existing Logic, viewer, and application-refresh paths. - -The no-AST policy does not claim to inspect arbitrary adapter internals. It enforces the owner-bound -policy at Logic publication and retrieval surfaces while preserving complete-projection and -genuinely non-AST incremental adapters. - -## Security and publication checks - -Gitleaks 8.30.1 scanned reachable Git history and an exact archive of the candidate tree with full -redaction. Both scans reported zero findings. `git fsck --full` passed. A broader filename and -credential-pattern audit also found no high-confidence matches. - -Forgejo repository creation used one timestamped short-lived administrator token. Forgejo accepted -it for repository creation but returned HTTP 401 when it attempted self-deletion. The exact -task-created token row was then validated by ID, owner, and unique name, deleted in one SQLite -transaction, and rechecked. Zero matching temporary token rows remain. - -The package metadata declares MIT, but the repository has no tracked standalone `LICENSE`, -`COPYING`, or `NOTICE` file. Milestone 0 records that publication weakness without inventing or -changing legal terms. - -## Validation and fresh-clone proof - -The repository-native aggregate gate is: - -```bash -make gate -``` - -It passed in the working tree and in an anonymous HTTPS clone of the public successor. The -fresh-clone proof: - -- Selected the expected `main` commit through the public default branch. -- Passed `git fsck --full`. -- Recreated the Python virtual environment from `uv.lock`. -- Recreated JavaScript dependencies with `npm ci`, with zero reported vulnerabilities. -- Passed Ruff formatting and lint. -- Passed HTML, rendered-manual HTML, CSS, and JavaScript lint. -- Passed Pyright with zero diagnostics. -- Passed Python compilation. -- Passed 8 public-contract tests and 42 schema subtests. -- Passed the complete 95-test and 44-subtest warning-strict suite. -- Passed lock and dependency-tree checks. -- Built the wheel and source distribution. -- Passed the disposable benchmark smoke run. -- Remained clean after validation. - -The maintained performance evidence and known gaps are recorded in -[`MILESTONE_0_BASELINE.md`](MILESTONE_0_BASELINE.md) and -[`benchmarks/milestone0-2026-07-29.json`](../benchmarks/milestone0-2026-07-29.json). - -## Scope confirmation - -Milestone 0 made no speculative storage rewrite and introduced no self-hosting dependency. -WorldForge and ScrapeStation were not read as benchmark fixtures or changed. No production MCP -integration was repointed. `ManualRenderPlan`, `GraphViewPlan`, and a portable graph renderer remain -later-milestone direction, not claimed implementation. diff --git a/docs/POLICY_PRECEDENCE.md b/docs/POLICY_PRECEDENCE.md index 2b275b1..015330d 100644 --- a/docs/POLICY_PRECEDENCE.md +++ b/docs/POLICY_PRECEDENCE.md @@ -43,9 +43,10 @@ Capability modes are: - `operator`: reserved; it currently adds no tools. Mode describes the maximum registered surface. Actual authority can be narrower. A descriptor must -declare the selected writer, including allowed families and operation types. Application requires -the matching configured writer, changeset creator, and canonical-applier identity. A mode name -cannot create a missing descriptor grant. +declare the selected writer, including allowed families and operation types. Application defaults +to a matching configured writer, changeset creator, and canonical-applier identity. A project-owned +server may explicitly authorize its applier to accept changesets from additional configured writers. +A mode name cannot create a missing descriptor grant or extend that accepted-writer allowlist. Generic generated client fragments default to read mode. Other construction paths preserve their documented compatible factory defaults. Treat `docforge_bootstrap.session_contract` and its actual diff --git a/docs/USER_MANUAL.md b/docs/USER_MANUAL.md index 1db7367..df33899 100644 --- a/docs/USER_MANUAL.md +++ b/docs/USER_MANUAL.md @@ -5,8 +5,8 @@ people and AI agents can search, inspect, visualize, and change through reviewab Canonical project files remain authoritative. The SQLite graph, previews, rendered manuals, and viewer processes are derived and can be rebuilt. -This manual describes the DocForge 1.4.0 release. The tagged `v1.0.0` baseline was the first stable -product release. Version 1.4.0 preserves its project-scoped graph, CLI and MCP query +This manual describes the DocForge 2.0.0 release. The tagged `v1.0.0` baseline was the first stable +product release. Version 2.0.0 preserves its project-scoped graph, CLI and MCP query surfaces, hash-approved proposal application, generic and project-owned adapters, declared rendering, and Nodes/Flow/Web model while adding the maintained incremental, projection, adapter SDK, recovery, and release proofs documented below. @@ -132,8 +132,8 @@ python -m docforge.reference_mcp --version python -m docforge.viewer_manager --version ``` -For version 1.4.0 these report `docforge 1.4.0`, `docforge-mcp 1.4.0`, -`python -m docforge.reference_mcp 1.4.0`, and `docforge-viewer-manager 1.4.0`. Package metadata, +For version 2.0.0 these report `docforge 2.0.0`, `docforge-mcp 2.0.0`, +`python -m docforge.reference_mcp 2.0.0`, and `docforge-viewer-manager 2.0.0`. Package metadata, Python imports, generated generic and adapter configurations, and these commands share the same version authority. @@ -815,7 +815,14 @@ docforge-mcp \ ``` 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. +identity, not a command. Generic CLI and MCP application require the changeset creator, configured +writer, and canonical applier to agree. + +A project-owned adapter server can separately pass `accepted_proposal_writers` to +`create_project_server`. This explicit allowlist lets its startup-bound applier accept an exact +reviewed changeset from another configured contributor identity. The default remains the applier +identity only. Accepted contributors retain their original proposal permissions and do not receive +canonical application authority. Call `docforge_bootstrap` first. Its version-1 `session_contract` contains the fixed binding, current graph generation, effective policy, actual capabilities, render policies, prohibitions, @@ -1303,7 +1310,7 @@ make fresh-clone-m5 recovery, task-evidence, fresh-wheel, version, artifact, secret-scan, and benchmark suite. `fresh-clone-m5` anonymously clones the exact published candidate over HTTPS, fetches and verifies the frozen annotated `v1.0.0` migration tag, and repeats `release-gate`. Release operators use -`make release-pretag` before creating `v1.4.0` and `make release-posttag` after the annotated tag +`make release-pretag` before creating `v2.0.0` and `make release-posttag` after the annotated tag points to the exact release commit. Project-specific vocabulary, extraction rules, and serialization belong in the project adapter. diff --git a/src/docforge/_version.py b/src/docforge/_version.py index c0e966c..9b5e0c8 100644 --- a/src/docforge/_version.py +++ b/src/docforge/_version.py @@ -1,3 +1,3 @@ """Single authoritative DocForge distribution and runtime version.""" -__version__ = "1.4.0" +__version__ = "2.0.0" diff --git a/src/docforge/application.py b/src/docforge/application.py index d6130cc..039454e 100644 --- a/src/docforge/application.py +++ b/src/docforge/application.py @@ -1204,12 +1204,39 @@ class CanonicalApplicationService: *, applier_id: str | None, applier: CanonicalApplier | None, + accepted_proposal_writers: tuple[str, ...] = (), index: ProjectIndex | None = None, manual_policy: ManualProjectionMode = "auto", ) -> None: self.project = project self.applier_id = applier_id self.applier = applier + if accepted_proposal_writers and (applier_id is None or applier is None): + raise DocForgeError( + "invalid_application_policy", + "Accepted proposal writers require an enabled canonical applier", + ) + configured_writers = frozenset( + writer.writer_id for writer in project.descriptor.proposal_writers + ) + selected_writers = ( + accepted_proposal_writers + if accepted_proposal_writers + else ((applier_id,) if applier_id is not None else ()) + ) + if len(set(selected_writers)) != len(selected_writers): + raise DocForgeError( + "invalid_application_policy", + "Accepted proposal writer identities must be unique", + ) + unknown_writers = sorted(set(selected_writers) - configured_writers) + if unknown_writers: + raise DocForgeError( + "invalid_application_policy", + "Accepted proposal writers must be configured for this project", + writers=unknown_writers, + ) + self.accepted_proposal_writers = tuple(sorted(selected_writers)) self.changesets = ChangesetStore(project, applier_id) self.index = index or ProjectIndex(project) self.manual_policy = validate_manual_projection_mode(manual_policy) @@ -1227,6 +1254,9 @@ class CanonicalApplicationService: return { "enabled": self.enabled, "applier": self.applier_id if self.enabled else None, + "accepted_proposal_writers": ( + list(self.accepted_proposal_writers) if self.enabled else [] + ), } def apply(self, changeset_id: str, expected_changeset_hash: str) -> dict[str, object]: @@ -1239,6 +1269,7 @@ class CanonicalApplicationService: changeset_id=changeset_id, expected_changeset_hash=expected_changeset_hash, applier_id=self.applier_id, + accepted_creator_ids=frozenset(self.accepted_proposal_writers), application=self.applier.apply, ) refresh_errors: list[dict[str, object]] = [] diff --git a/src/docforge/changesets.py b/src/docforge/changesets.py index 9885c44..f23c2f4 100644 --- a/src/docforge/changesets.py +++ b/src/docforge/changesets.py @@ -598,6 +598,7 @@ class ChangesetStore: changeset_id: str, expected_changeset_hash: str, applier_id: str, + accepted_creator_ids: frozenset[str] | None = None, application: Callable[ [ProjectSnapshot, ProjectSnapshot, tuple[Mapping[str, object], ...]], dict[str, object], @@ -628,13 +629,17 @@ class ChangesetStore: expected=expected_changeset_hash, actual=actual_hash, ) - if document["creator"] != applier_id: + accepted_creators = ( + frozenset({applier_id}) if accepted_creator_ids is None else accepted_creator_ids + ) + if document["creator"] not in accepted_creators: raise DocForgeError( "changeset_owner_conflict", - "Canonical applier does not own this changeset", + "Canonical applier is not authorized to accept this changeset creator", changeset_id=changeset_id, owner=document["creator"], applier=applier_id, + accepted_creators=sorted(accepted_creators), ) projected = ProjectSnapshot( descriptor=snapshot.descriptor, @@ -680,6 +685,8 @@ class ChangesetStore: lifecycle=lifecycle, applied_from_revision=snapshot.revision, applied_from_source_hash=snapshot.source_hash, + proposal_creator=document["creator"], + applied_by=applier_id, **payload, ) diff --git a/src/docforge/mcp_server.py b/src/docforge/mcp_server.py index d98afe0..6c49b47 100644 --- a/src/docforge/mcp_server.py +++ b/src/docforge/mcp_server.py @@ -133,6 +133,7 @@ class DocForgeService: *, canonical_applier_id: str | None = None, canonical_applier: CanonicalApplier | None = None, + accepted_proposal_writers: tuple[str, ...] = (), context_provider: ContextProvider = compile_context, tool_surface: tuple[str, ...] | None = None, binding_metadata: Mapping[str, object] | None = None, @@ -188,6 +189,7 @@ class DocForgeService: self.project, applier_id=canonical_applier_id if application_enabled else None, applier=canonical_applier if application_enabled else None, + accepted_proposal_writers=(accepted_proposal_writers if application_enabled else ()), index=self.index, manual_policy=self.projection_policy.manual, ) @@ -2108,6 +2110,7 @@ def create_project_server( proposal_writer: str | None = None, canonical_applier_id: str | None = None, canonical_applier: CanonicalApplier | None = None, + accepted_proposal_writers: tuple[str, ...] = (), context_provider: ContextProvider = compile_context, binding_metadata: Mapping[str, object] | None = None, no_ast: bool = False, @@ -2124,6 +2127,7 @@ def create_project_server( proposal_writer, canonical_applier_id=canonical_applier_id, canonical_applier=canonical_applier, + accepted_proposal_writers=accepted_proposal_writers, context_provider=context_provider, binding_metadata=binding_metadata, no_ast=no_ast, diff --git a/src/docforge/project.py b/src/docforge/project.py index 17052b3..5d8e882 100644 --- a/src/docforge/project.py +++ b/src/docforge/project.py @@ -397,7 +397,9 @@ def _load_descriptor(root: Path) -> ProjectDescriptor: title = require_string(document, "title", descriptor_path) adapter = require_string(document, "adapter", descriptor_path) if adapter != "generic": - raise DocForgeError("unsupported_adapter", "DFG-1 supports only the generic adapter") + raise DocForgeError( + "unsupported_adapter", "This project loader supports only the generic adapter" + ) sources = document.get("sources") derived = document.get("derived") diff --git a/tests/test_changesets.py b/tests/test_changesets.py index c956990..e2f47b5 100644 --- a/tests/test_changesets.py +++ b/tests/test_changesets.py @@ -328,6 +328,103 @@ class DocForgeChangesetTests(unittest.TestCase): self.assertFalse((root / ".docforge/changesets/.state/update-race.json").exists()) self.assertFalse(tuple(target.parent.glob(".docforge-apply-*"))) + def test_explicit_applier_accepts_a_configured_contributor_changeset(self) -> None: + with tempfile.TemporaryDirectory() as directory: + root = self.copy_fixture(Path(directory)) + descriptor = root / ".docforge/project.toml" + descriptor.write_text( + descriptor.read_text(encoding="utf-8") + + """ + +[[changesets.writers]] +id = "contributor" +families = ["guide"] +operations = ["update"] +""", + encoding="utf-8", + ) + project = Project.open(root) + proposal = ChangesetStore(project, "contributor").register( + "contributor-update", + [ + { + "operation": "update", + "node_id": "guide.workflow", + "metadata": {"summary": "Accepted from a configured contributor."}, + "rationale": "Prove explicit cross-identity acceptance.", + } + ], + ) + default_service = CanonicalApplicationService( + project, + applier_id="alpha-editor", + applier=GenericCanonicalApplier(project), + ) + + with self.assertRaises(DocForgeError) as denied: + default_service.apply( + "contributor-update", + str(proposal["changeset_hash"]), + ) + + self.assertEqual("changeset_owner_conflict", denied.exception.code) + service = CanonicalApplicationService( + project, + applier_id="alpha-editor", + applier=GenericCanonicalApplier(project), + accepted_proposal_writers=("alpha-editor", "contributor"), + ) + result = service.apply( + "contributor-update", + str(proposal["changeset_hash"]), + ) + + self.assertTrue(result["applied"]) + self.assertEqual("contributor", result["proposal_creator"]) + self.assertEqual("alpha-editor", result["applied_by"]) + self.assertEqual( + ["alpha-editor", "contributor"], + service.access()["accepted_proposal_writers"], + ) + workflow = next( + node for node in project.load().nodes if node.node_id == "guide.workflow" + ) + self.assertEqual( + "Accepted from a configured contributor.", + workflow.summary, + ) + + def test_application_rejects_unknown_or_duplicate_accepted_writers(self) -> None: + with tempfile.TemporaryDirectory() as directory: + root = self.copy_fixture(Path(directory)) + project = Project.open(root) + + with self.assertRaises(DocForgeError) as unknown: + CanonicalApplicationService( + project, + applier_id="alpha-editor", + applier=GenericCanonicalApplier(project), + accepted_proposal_writers=("missing-writer",), + ) + with self.assertRaises(DocForgeError) as duplicate: + CanonicalApplicationService( + project, + applier_id="alpha-editor", + applier=GenericCanonicalApplier(project), + accepted_proposal_writers=("alpha-editor", "alpha-editor"), + ) + with self.assertRaises(DocForgeError) as disabled: + CanonicalApplicationService( + project, + applier_id=None, + applier=None, + accepted_proposal_writers=("alpha-editor",), + ) + + self.assertEqual("invalid_application_policy", unknown.exception.code) + self.assertEqual("invalid_application_policy", duplicate.exception.code) + self.assertEqual("invalid_application_policy", disabled.exception.code) + def test_canonical_create_and_delete_races_preserve_foreign_targets(self) -> None: with tempfile.TemporaryDirectory() as directory: parent = Path(directory) diff --git a/tests/test_mcp_server.py b/tests/test_mcp_server.py index 8c65dd2..56420f7 100644 --- a/tests/test_mcp_server.py +++ b/tests/test_mcp_server.py @@ -17,6 +17,7 @@ from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client from mcp.shared.memory import create_connected_server_and_client_session +from docforge.application import GenericCanonicalApplier from docforge.changesets import ChangesetStore from docforge.errors import DocForgeError from docforge.index import ProjectIndex @@ -29,6 +30,7 @@ from docforge.mcp_server import ( SERVER_VERSION, DocForgeService, _create_bound_server, + create_project_server, create_server, ) from docforge.project import Project, project_root_fingerprint @@ -1446,6 +1448,83 @@ class DocForgeMcpTests(unittest.IsolatedAsyncioTestCase): self.assertEqual("Applied through the gated MCP tool.", workflow.summary) self.assertTrue((root / ".docforge/rendered/manual.html").is_file()) + async def test_project_server_accepts_an_explicit_contributor_without_granting_apply( + self, + ) -> None: + with tempfile.TemporaryDirectory() as directory: + root = self.copy_fixture("alpha", Path(directory)) + descriptor = root / ".docforge/project.toml" + descriptor.write_text( + descriptor.read_text(encoding="utf-8") + + """ + +[[changesets.writers]] +id = "contributor" +families = ["guide"] +operations = ["update"] +""", + encoding="utf-8", + ) + project = Project.open(root) + ProjectIndex(project).build() + async with create_connected_server_and_client_session( + create_server( + root, + "contributor", + capability_mode="proposal", + ), + raise_exceptions=True, + ) as contributor: + contributor_tools = tuple( + tool.name for tool in (await contributor.list_tools()).tools + ) + registered = await contributor.call_tool( + "docforge_register_changes", + { + "changeset_id": "accepted-contribution", + "operations": [ + { + "operation": "update", + "node_id": "guide.workflow", + "metadata": {"summary": "Accepted through a separate applier."}, + "rationale": "Prove explicit contributor acceptance over MCP.", + } + ], + }, + ) + + async with create_connected_server_and_client_session( + create_project_server( + project, + proposal_writer="alpha-editor", + canonical_applier_id="alpha-editor", + canonical_applier=GenericCanonicalApplier(project), + accepted_proposal_writers=("contributor",), + capability_mode="application", + ), + raise_exceptions=True, + ) as developer: + contract = await developer.call_tool("docforge_get_contract", {}) + applied = await developer.call_tool( + "docforge_apply_changeset", + { + "changeset_id": "accepted-contribution", + "expected_changeset_hash": registered.structuredContent["changeset_hash"], + }, + ) + + self.assertEqual(ALL_TOOLS, contributor_tools) + self.assertNotIn("docforge_apply_changeset", contributor_tools) + self.assertEqual( + ["contributor"], + contract.structuredContent["canonical_application_access"][ + "accepted_proposal_writers" + ], + ) + self.assertTrue(applied.structuredContent["applied"]) + self.assertEqual("contributor", applied.structuredContent["proposal_creator"]) + self.assertEqual("alpha-editor", applied.structuredContent["applied_by"]) + async def test_stdio_transport_serves_the_same_project_bound_contract(self) -> None: with tempfile.TemporaryDirectory() as directory: root = self.copy_fixture("beta", Path(directory)) diff --git a/tests/test_milestone5_migration.py b/tests/test_milestone5_migration.py index 04c41d0..ebc2d8f 100644 --- a/tests/test_milestone5_migration.py +++ b/tests/test_milestone5_migration.py @@ -10,7 +10,7 @@ class Milestone5MigrationTests(unittest.TestCase): evidence = build_migration_evidence() self.assertEqual("v1.0.0", evidence["tag"]) - self.assertEqual("1.4.0", evidence["current"]["version"]) + self.assertEqual("2.0.0", evidence["current"]["version"]) self.assertEqual(1, evidence["current"]["index_schema_before"]) self.assertEqual(3, evidence["current"]["index_schema_after"]) self.assertEqual( diff --git a/tests/test_public_contract.py b/tests/test_public_contract.py index 901b355..dc60a76 100644 --- a/tests/test_public_contract.py +++ b/tests/test_public_contract.py @@ -282,10 +282,10 @@ class PublicContractTests(unittest.TestCase): self.assertTrue(hasattr(module, name)) version_surfaces = { - "docforge.cli": "docforge 1.4.0\n", - "docforge.mcp_server": "docforge-mcp 1.4.0\n", - "docforge.reference_mcp": "python -m docforge.reference_mcp 1.4.0\n", - "docforge.viewer_manager": "docforge-viewer-manager 1.4.0\n", + "docforge.cli": "docforge 2.0.0\n", + "docforge.mcp_server": "docforge-mcp 2.0.0\n", + "docforge.reference_mcp": "python -m docforge.reference_mcp 2.0.0\n", + "docforge.viewer_manager": "docforge-viewer-manager 2.0.0\n", } for module_name, expected in version_surfaces.items(): with self.subTest(module=module_name): diff --git a/tests/test_release_identity.py b/tests/test_release_identity.py index 734eb18..d264b0d 100644 --- a/tests/test_release_identity.py +++ b/tests/test_release_identity.py @@ -14,13 +14,13 @@ class ReleaseIdentityTests(unittest.TestCase): ) self.assertEqual(1, evidence["schema_version"]) - self.assertEqual("1.4.0", evidence["version"]) + self.assertEqual("2.0.0", evidence["version"]) self.assertEqual( { - "docforge.cli": "docforge 1.4.0", - "docforge.mcp_server": "docforge-mcp 1.4.0", - "docforge.reference_mcp": "python -m docforge.reference_mcp 1.4.0", - "docforge.viewer_manager": "docforge-viewer-manager 1.4.0", + "docforge.cli": "docforge 2.0.0", + "docforge.mcp_server": "docforge-mcp 2.0.0", + "docforge.reference_mcp": "python -m docforge.reference_mcp 2.0.0", + "docforge.viewer_manager": "docforge-viewer-manager 2.0.0", }, evidence["surfaces"], ) diff --git a/tools/check_documentation.py b/tools/check_documentation.py index df32b56..0deca49 100644 --- a/tools/check_documentation.py +++ b/tools/check_documentation.py @@ -39,7 +39,7 @@ REQUIRED_MILESTONE_4_PAGES = ( Path("README.md"), Path("docs/ADAPTER_AUTHORING_GUIDE.md"), Path("docs/AGENT_INTEGRATION.md"), - Path("docs/APPLICATION_DECISION.md"), + Path("docs/CANONICAL_APPLICATION.md"), Path("docs/COMMAND_REFERENCE.md"), Path("docs/COMPATIBILITY.md"), Path("docs/CONTRACT.md"),