Where DocPilot 3.0 stands — the twelve phases, the progress and the latest update. No 3.0 package is published yet, and the 2.x line stays the current version on npm.
Roadmap to 3.0
No 3.0 package is published yet; the 2.x line stays the current version on npm. This page follows the work toward 3.0. The first two phases, the shared document pipeline and the HTML extractor, are already in 2.2.0: see the changelog. Everything else below is a plan, not a feature of the version you can install.
The progress, the latest update and the roadmap are the GitHub pre-release roadmap-3.0, read when this site is built. The note is updated at the end of every phase.
A copy of the GitHub pre-release roadmap-3.0, saved on 2026-11-03: the pre-release could not be read when this site was built.
After 3.0: DocPilot moves to a new website and gets a new product name that does not collide with other products, so people who look for it can find it more easily. The npm package becomes @cloflin/ai (Phase 10); the new name and the new site are announced with the 3.0 release.
Progress: 4 of 12 phases complete · updated 2026-11-03
Plan updates since Phase 4 (2026-11-03)
- Every update now goes through the Markdown snapshot. A webhook, a schedule or
docpilot syncrewrites the one page that changed, and the server's index is built from those pages, so the server index can always be rebuilt from Markdown without asking the service again (Phase 5). - A site's own Markdown docs sync on the server too: the server re-reads them on a schedule and indexes only the pages that changed (Phase 5).
- Intercom's article webhooks (
article.created,article.updated,article.published,article.unpublished,article.deleted) are confirmed in Intercom's own reference. A webhook re-reads only the one article it names; the schedule still catches anything a webhook misses (Phase 5). - An MCP server can be a knowledge-base source: a
type: 'mcp'connector reads its resources, or one named read-only tool, into the same Markdown snapshot (Phase 9). - Sources can be chosen from both sides. A site or product picks the sources of its own panel with a
filterssetting (Phase 6), and the server owner can give each consumer a token whose source scope it cannot leave (Phase 9). - Phase 6 also carries prompt caching (byte-stable tool schemas and system message, OpenAI explicit cache breakpoints), an offline A/B of the next prompt layout, and the measurement that decides whether the server's vectors default to
float32. Each change that alters answers ships only if the evaluation shows it is no worse. - Phase 7, the framework-free chat core, is planned in 15 steps; it runs after Phase 6.
- The 3.0 requirement count is now 140.
Latest update — Phase 4: Server storage and hot swap (2026-11-03)
- The server's index now lives behind one storage interface, exported as
@cloflin/docpilot/store. Five stores ship: the existing index directory, an index served over HTTP (read-only), memory, SQLite through Node's built-innode:sqlite(nothing to install), and Postgres with pgvector through the site owner's ownpgclient. The package imports no database driver. - An existing
rag/directory loads unchanged through the files store and answers as 2.1.1 did: the frozen 2.1.1 rankings replay with no difference. - One exported conformance suite checks every store the same way, and a site owner can run it against a store of their own. It passes on the files, memory, SQLite and Postgres stores; the Postgres run uses PGlite, a Postgres build that runs in the test process.
- A commit is atomic: a reader never sees half of an updated article, and the sync position is saved in the same commit. Each store records the embedding model, the dimensions, the vector precision and the vocabulary once, and a server refuses to start on a store it cannot serve.
- A running server picks up a changed store without a restart. It checks the store every 5 seconds (or when
refresh()is called), builds the next index beside the live one and then swaps to it in one step. A question that is already being answered finishes on the index it started with, and a failed or refused refresh keeps the current index. - Leases keep two server instances from writing the same source at the same time.
docpilot store migrate <from> <to>moves an index between stores without embedding anything again, and checks the result.- A server store can keep its vectors unquantised (
float32orfloat16) beside the 8-bit default. The default stays 8-bit until Phase 6 measures the difference. - 3.0 requires Node 22.13 or newer, and CI runs Node 22.13.0 and 24.
- The 2.2.0 release notes are now in the 3.0 branch. The design record is engine-spec 045. The docs, both committed indexes, both calibrations and the four frozen baselines were updated once, at the end of the phase.
- Still open before the release: a run of the Postgres suite against a real Postgres server, and the first CI run on Node 22.13.0.
Roadmap: DocPilot
Overview
DocPilot 3.0 widens where grounded answers come from and how fresh they stay, and shrinks what a site ships. The roadmap starts by freezing the 2.1.1 baselines and moving the existing sources onto one shared document pipeline with unchanged output bytes. Then it improves HTML extraction, builds the connectors (Intercom, Zendesk, Freshdesk, Generic REST, own-origin pages), puts the server index behind a storage adapter with an atomic hot swap, and adds the sync engine that makes an edit at the source reach answers without a restart (Core Value). Confluence and Notion follow once sync and reconcile exist. Next, one turn pipeline serves browser, server and eval, and server retrieval gains filters, a candidate pool, a reranker and contextual chunks, each backed by eval evidence. The client track then moves chat state onto a Vue-free core and splits the bundle into registered features with a custom-bundle CLI; the existing Vue UI ships in 3.0. The release phase ships the migration path and proves the motivating case on stock DocPilot: a production site that today needs a patched DocPilot and hand-written import scripts. After the release, a last phase decides through a go/no-go whether the whole UI moves to Web Components in a 3.x minor release, as a non-breaking swap.
Two phases were added after the roadmap was created. Phase 9 puts MCP on both ends of the server runtime — an endpoint through which coding agents search the docs, and a client through which the assistant calls other services' tools — under one permission policy that only the server owner writes. Phase 10 renames the package to @cloflin/ai and splits it into one subpath per layer, before the release phase (Phase 11).
Structure Notes
- Ten phases, above the standard 5-8. 106 requirements in 11 categories split into two tracks (server: Phases 2-6, client: Phases 7-8, plus Phase 12 after the release). Research suggested 12 phases. Two merges were made where dependencies stay honest: wiki connectors joined the sync phase (they are the first schedule-first consumers of reconcile), and the turn-driver unification joined server retrieval (the driver is that phase's first deliverable and must be green before any retrieval stage lands). Further merges would cross real boundaries: Phase 1 keeps output byte-identical while Phase 2 deliberately shifts corpus hashes; Phases 4 and 5 would hold 25 requirements; Phases 7 and 8 differ in risk and research needs; Phase 12 is conditional.
- Requirements placed ahead of their category. REL-01 (Node >= 22.13, CI on 22 and 24) is in Phase 4 because the
node:sqliteadapter cannot run in CI before it. SYNC-08 (atomic hot swap) is in Phase 4 because the index holder is built with the store. STORE-08 (ceilings per runtime) is in Phase 1 because the shared pipeline owns the ceilings. SEC-01 to SEC-03 start in Phase 3 because credentials first exist there; later phases keep the secret scan green and extend the visibility fixtures to the wiki connectors. - Embedding-moving changes are batched. All extractor changes land as one extractor-version bump in Phase 2. Eval evidence for that bump, the breadcrumb prefix, the contextual prefix and the reranker is collected together in Phase 6 (EVAL-04), once the Intercom golden set exists, and always before 3.0 ships.
- The 2.x deprecation release (REL-02) is cut before 3.0 final. The list of removed exports and options is final only after Phase 10 (the package split), so Phase 11 owns it. Phase 12 (Web Component UI) is a non-breaking swap in a 3.x minor release and adds nothing to the list.
- Research flags. Phases 3, 4, 5, 6, 8, 9, 10 and 12 need a research pass before planning.
- Two phases were added on 2026-10-30, after the roadmap was created, and the last three were renumbered the same day. 27 requirements in 4 new categories (MCPS, MCPC, PERM, PKG) bring the total to 133 in 15; MCPS-07 and MCPS-08 (the local and the Vercel deploy of
/mcp) were added the same day. Phase 9 (MCP, engine-spec 042) needs the Phase 6 turn driver, where the reader's approval pause is built once for all three drivers. Phase 10 (the package split) needs per-feature exports (Phase 8) and themcplayer (Phase 9); itschat-uisubpath ships the current Vue UI on the Phase 7 core. The release is Phase 11. On 2026-10-30 the release moved from Phase 10 to Phase 12, MCP from Phase 11 to 10 and the package split from Phase 12 to 11; the phases run in number order, so the number order must be the dependency order. On 2026-11-02 REL-11 (the new product name and website) was added to Phase 11, which brings the total to 134 in 15. - The Web Component phase moved behind the release on 2026-11-02. The owner decided that the existing Vue UI ships in 3.0 and the Web Component follows in a 3.x minor release. It was Phase 9 and is now Phase 12 (CORE-11); MCP, the package split and the release moved down to Phases 9, 10 and 11. The swap stays non-breaking because the public UI surface is the mount function, the thin wrappers (props and events) and the
--dp-*tokens.
Phases
Phase Numbering:
- Integer phases (1, 2, 3): Planned milestone work
- Decimal phases (2.1, 2.2): Urgent insertions (marked with INSERTED)
Decimal phases appear between their surrounding integers in numeric order.
Phase Details
Phase 1: Baselines and shared document pipeline
Goal: The 2.1.1 behaviour is frozen as measurable baselines, and Markdown, HTML-directory and OpenAPI sources run through one shared SourceDoc pipeline with unchanged output bytes.
Depends on: Nothing (first phase)
Requirements: EVAL-01, EVAL-02, BNDL-01, CORE-02, SRC-01, SRC-02, STORE-08
Success Criteria (what must be TRUE):
- The maintainer can re-run the golden eval on
ragandrag-local, pluseval --runtime=server, and comparerankedIdsagainst frozen 2.1.1 baselines kept in the repo, so a changed ranking shows up as a diff. The lexical recalibration owed since the stemmer change is done first, on the offlinerag-local+ Ollama path. - A bundle composition report breaks the 1.19 MB
dist/docpilot.web.jsdown by contributor (Vue, Shiki, markdown-it, MiniSearch, panel code, optional features), so later phases choose what leaves from measurement. - Characterisation tests of the 2.1.1 session (submit sequence, state writes, citations, openers, history, quote, budget) pass on today's code and stay as the safety net for Phases 6 and 7.
- Markdown, HTML-directory and OpenAPI sources emit documents in the one
SourceDocshape (id, canonical URL, title, body,updatedAt, locale, visibility, breadcrumb, tags, content hash), anddocs/public/rag/anddocs/public/rag-local/rebuild byte-identical. - A server-runtime corpus above the 64 KB manifest and 5 MB file ceilings builds without patching, while the browser build still refuses it. Plans: 12/12 plans complete in 6 waves
Plans: Wave 1
Wave 2 (blocked on Wave 1 completion)
Wave 3 (blocked on Wave 2 completion)
Wave 4 (blocked on Wave 3 completion)
Wave 5 (blocked on Wave 4 completion)
Wave 6 (blocked on Wave 5 completion)
Cross-cutting constraints:
- Every scenario goes through createHarness; this file never imports session.js (D-14)
Phase 2: HTML extraction
Goal: HTML pages become clean, deterministic Markdown that keeps code, links, tables and structure, and one bad page never fails docpilot index.
Depends on: Phase 1
Requirements: HTML-01, HTML-02, HTML-03, HTML-04, HTML-05, HTML-06, HTML-07, HTML-08, HTML-09, HTML-10, HTML-11, HTML-12, HTML-13
Success Criteria (what must be TRUE):
- Site owner can set
contentandexcludeselectors per source and get only the article body. Without selectors, the rule list removes navigation, footers, cookie banners, breadcrumbs, feedback widgets, share bars and TOC sidebars, and keeps tab panels and accordions with their labels. - A page with
<br>inside a code block produces a multi-line fenced block with the language as fence info, with highlighter spans, line-number tables and copy buttons gone. A page with an OpenAPI description embedded in an article indexes, and its relative link resolves against the canonical URL or degrades to text with a warning. - Heading hierarchy and ids, nested lists, GFM tables (colspan / rowspan fallback),
details, definition lists and blockquotes survive extraction. Entities are decoded, whitespace and Unicode are normalised, and script, style, template and svg noise is gone. - Page title, canonical URL,
langanddateModifiedare extracted, arobots noindexpage is skipped, anddocpilot importanddocpilot doctorprint a per-source report of characters kept and dropped, empty pages and link failures. - After
npm i @cloflin/docpiloton a clean machine,docpilot importworks with nothing else installed, and the parser is absent from the browser bundle. The same HTML gives byte-identical Markdown, and the extractor version is part of the corpus hash. A Readability-class fallback is adopted only if it beats the rule list on a labelled page set, and afetcherhook accepts pre-rendered HTML. Plans: 12/12 plans complete in 5 waves
Plans: Wave 1
Wave 2 (blocked on Wave 1 completion)
Wave 3 (blocked on Wave 2 completion)
Wave 4 (blocked on Wave 3 completion)
Wave 5 (blocked on Wave 4 completion; metered step behind the owner's approval)
Cross-cutting constraints:
- No metered, hosted or LAN-model call outside plan 02-12, and that one only after the price check and the owner's "yes"
- No plan before 02-12 edits docs/**/.md, docs/public/rag/, docpilot/baselines/ or docpilot/golden.jsonl
- Fixtures are synthetic and brand-free; the reference vendor is never named in a tracked file
Phase 3: Source connectors and snapshot pull
Goal: Site owner can pull public content from Intercom, Zendesk, Freshdesk, any JSON API and their own origin into a snapshot directory that docpilot index turns into an index, with no hand-written import script and no credential leaving the build machine.
Depends on: Phase 2 (HTML-bodied connectors reuse the extractor), Phase 1
Requirements: SRC-03, SRC-04, SRC-05, SRC-06, SRC-07, SRC-08, SRC-09, SRC-10, SRC-11, SRC-12, SRC-13, CONN-01, CONN-02, CONN-03, CONN-06, CONN-07, CONN-08, SEC-01, SEC-02, SEC-03
Success Criteria (what must be TRUE):
- Site owner can run
docpilot pullfor an Intercom Help Center (published articles only, per-locale state, collection breadcrumbs, pinnedIntercom-Version), a Zendesk Help Center (incremental endpoint, translations) and a Freshdesk knowledge base (category and folder walk) and get a snapshot directory of Markdown plus front-matter. Each (article, locale) pair is one document.docpilot indexthen reads only files and makes no network call. - When an API call fails,
docpilot pullkeeps the last good snapshot of that source and reports the failure. Pulls retry on 429 and 5xx honouringRetry-After, resume pagination, and lose no document to anupdated_attie or clock skew.docpilot connectors test <name>reports auth result, first page, field coverage and locale / state counts and writes nothing. - Site owner can write their own connector against the exported
Connectorinterface, or configure Generic REST declaratively (auth, pagination, array path, field map, incremental parameter, delete detection,transform). Generic REST refuses private, loopback and link-local targets unless allowlisted. Site owner can map citation URLs withurlTemplate, include or exclude collections and labels before import, and see source tags in chunk metadata. - Site owner can point a sitemap / URL source at their own origin and get its pages with no import script: sitemap discovery, robots, 1 request/s by default, a cookie jar for geo-redirects, a configurable user agent. A WAF soft-block or stub page is reported and not indexed.
- Draft, internal and restricted documents never reach an index (per-connector fixtures prove it), and the static build refuses any non-public document. Connector, store and sync config and credentials never appear in the client config, built bundle, manifest or logs; credentials come only from environment-variable references;
npm run verifyscans the built output for them;docpilot doctorchecks connector auth and scopes. Plans: 16/16 plans complete in 7 waves
Plans: Wave 1
Wave 2 (blocked on Wave 1 completion)
Wave 3 (blocked on Wave 2 completion)
Wave 4 (blocked on Wave 3 completion)
Wave 5 (blocked on Wave 4 completion)
Wave 6 (blocked on Wave 5 completion)
Wave 7 (blocked on Wave 6 completion)
Cross-cutting constraints:
- No metered, hosted or LAN-model call outside plan 03-15, and that one only after the price check and the owner's "yes"; no plan calls a vendor API with a credential (the live vendor checks are the owner's manual verification, D-28)
- No plan before 03-15 edits docs/**/.md, docs/public/rag/, docpilot/baselines/, docpilot/golden.jsonl, or the registration in src/config.ts, src/cli-flags.ts and bin/docpilot.js (D-10, D-31)
- Fixtures are synthetic and brand-free; the reference vendor is never named in a tracked file; connector code runs on Node 20 and adds no runtime dependency (D-29)
Research: Per-connector spikes on live trial accounts: Zendesk deletions in the incremental export, Freshdesk article updated_at, Intercom webhook topics for the account's API version, signature details. Zendesk auth is OAuth client credentials with hc:read, not an API token (https://developer.zendesk.com/documentation/authentication/oauth-migration/); confirm which Help Center endpoints, the incremental export included, accept that scope.
Phase 4: Server storage and hot swap
Goal: The server index lives behind a StorageAdapter that works on files, memory, SQLite and Postgres, and a running server swaps to updated content atomically without a restart.
Depends on: Phase 1 (independent of Phases 2 and 3; can run in parallel with them)
Requirements: STORE-01, STORE-02, STORE-03, STORE-04, STORE-05, STORE-06, STORE-07, STORE-09, STORE-10, SYNC-08, REL-01
Success Criteria (what must be TRUE):
- An existing
rag/directory loads unchanged through the files adapter and answers as it did in 2.1.1 (the Phase 1 baselines show no regression). - Site owner can keep the server index in SQLite through
node:sqlitewith no extra install, or in Postgres with pgvector by passing their ownpgclient (the package imports no database driver). One exported adapter conformance suite passes against the files, memory, SQLite and Postgres adapters. - Replacing one document is atomic, so a reader never sees a half-updated article, and the sync cursor commits together with the documents. The store records embedding model, dimensions and quantisation, and the server refuses to start or sync on a mismatch.
- When a document changes in the store from outside the server process, the running server serves the new content without a restart, and an in-flight turn finishes on the index it started with.
docpilot store migrate <from> <to>moves an index between adapters without re-embedding. A lease keeps a second instance from holding the same source lock.engines.nodeis>= 22.13and CI runs Node 22 and 24. Plans: 14/14 plans complete in 8 waves
Plans: Wave 1
Wave 2 (blocked on Wave 1 completion)
Wave 3 (blocked on Wave 2 completion)
Wave 4 (blocked on Wave 3 completion)
Wave 5 (blocked on Wave 4 completion)
Wave 6 (blocked on Wave 5 completion)
Wave 7 (blocked on Wave 6 completion)
Wave 8 (blocked on Wave 7 completion; metered step behind the owner's approval)
Cross-cutting constraints:
- No metered, hosted or LAN-model call outside plan 04-14, and that one only after the price check and the owner's "yes"
- No plan before 04-14 edits docs/**/.md, docs/public/rag/, docpilot/baselines/ or docpilot/golden.jsonl;
storeenters bin/docpilot.js and src/cli-flags.ts only in 04-14 (D-37) - Shared files (D-30) are read in their current state and edited additively; build-rag-index.ts changes are extraction-only and byte-identical
- Stop conditions, not checkpoints: S2 bind failure on 22.13.0 (D-31), a failed D-42 provenance check or a PGlite that cannot run (D-42), no S1 chunk size within the stall budget (D-21)
Research: Measure MiniSearch rebuild time at 10k and 50k chunks before promising swap latency; test the SQLite vector path with
defensiveon.
Phase 5: Sync engine, freshness and wiki connectors
Goal: An edit at the source reaches the running server's answers without a rebuild or restart, by CLI, schedule or webhook, with reconcile as the correctness backstop; Confluence and Notion join as schedule-first connectors. Depends on: Phase 3, Phase 4 Requirements: SYNC-01, SYNC-02, SYNC-03, SYNC-04, SYNC-05, SYNC-06, SYNC-07, SYNC-09, SYNC-10, SYNC-11, SYNC-12, SYNC-13, CONN-04, CONN-05 Success Criteria (what must be TRUE):
docpilot sync [source]is incremental by default, supports--fulland--dry-run, and exits with codes fit for cron and CI.--dry-runlists documents to add, change and delete and the estimated embedding requests before anything is spent. Only documents whose normalised content hash changed are re-chunked, unchanged chunks reuse cached embeddings, and a per-run embedding cap defers the rest to the next run.docpilot serveruns scheduled syncs (interval or cron string) and never starts a second run of a source that is still syncing. After a source edit and one scheduled run, the running server answers from the new text. The webhook route has its own auth and rate limit: a forged, replayed or stale event is rejected without touching the index, a valid one is acknowledged fast, debounced per document, and the document is re-fetched by id.- A periodic full reconcile removes deleted and unpublished documents. A sync that would delete more than
maxDeleteRatio(default 20%) of a source stops and reports instead. A document that fails to process is quarantined and retried on the next run, and never aborts the sync or corrupts the index. - Site owner can see sync state: last success, added / changed / deleted / failed counts and lag per source in
/metricsanddocpilot doctor, optional freshness lag in answer metadata, and an SSE stream of sync status events. The docs give a CI recipe that refreshes the static index on a schedule or webhook (pullthenindex). - Site owner can ingest Confluence Cloud (allowlisted spaces, storage-format macros for code, panels, expand and include converted by explicit rules) and Notion pages shared with the integration (
urlTemplatefor citation URLs). Both refresh on schedule, and neither lets a draft or restricted page reach the index. Plans: 8/20 plans executed in 10 waves
Plans: Wave 1
Wave 2 (blocked on Wave 1 completion)
Wave 3 (blocked on Wave 2 completion)
Wave 4 (blocked on Wave 3 completion)
Wave 5 (blocked on Wave 4 completion)
Wave 6 (blocked on Wave 5 completion)
Wave 7 (blocked on Wave 6 completion)
Wave 8 (blocked on Wave 7 completion)
Wave 9 (blocked on Wave 8 completion)
Wave 10 (blocked on Wave 9 completion)
Phase 6: Unified turn pipeline and server retrieval
Goal: One turn pipeline drives browser, server and eval, and the server retrieves with filters, breadcrumbs, a larger candidate pool, an optional reranker, contextual chunks and neighbour expansion, each shipped only with eval evidence. Depends on: Phase 3 (facets and breadcrumbs), Phase 4 (async retrieval and the index holder), Phase 1 (characterisation tests) Requirements: CORE-01, EVAL-03, EVAL-04, EVAL-05, SEC-04, RETR-01, RETR-02, RETR-03, RETR-04, RETR-05, RETR-06, RETR-07, CORE-12, RETR-08, EVAL-06, RETR-09 Success Criteria (what must be TRUE):
- The same fixture through the browser, server and eval drivers gives identical
gate,rankedIdsandoutcome. With every new retrieval stage off, results match the Phase 1 2.1.1 baselines. - The eval report header records host, model and the retrieval stages that ran. A golden set for real Intercom help-center content runs on the offline
rag-local+ Ollama path, and eval fixtures with prompt-injection text in ingested documents show the answer stays grounded. - Site owner can scope retrieval by locale, source, collection, visibility and tags through a typed allowlist, and "nothing left after the filter" is its own outcome. Each chunk carries a deterministic breadcrumb / title prefix before BM25 and embedding, and the server retrieves a larger configurable candidate pool than the browser.
- Site owner can turn on a reranker through an HTTP
/rerankadapter. On timeout or error the turn falls back to the un-reranked order, and the relevance gate still scores the pre-rerank channels, so a calibrated threshold stays valid. - Site owner can turn on an LLM-written contextual prefix per chunk at ingest, cached by content hash, and top hits expand to their neighbouring chunk or section on the server. The extractor version, breadcrumb prefix, contextual prefix and reranker each ship only with eval evidence on
rag-local, including Russian probes. Plans: 22 plans in 9 waves
Plans: Wave 1
Wave 2 (blocked on Wave 1 completion)
Wave 3 (blocked on Wave 2 completion)
Wave 4 (blocked on Wave 3 completion)
Wave 5 (blocked on Wave 4 completion)
Wave 6 (blocked on Wave 5 completion)
Wave 7 (blocked on Wave 6 completion)
Wave 8 (blocked on Wave 7 completion)
Wave 9 (blocked on Wave 8 completion)
Phase 7: Vue-free chat core
Goal: Chat state and turn lifecycle run on a framework-agnostic core with per-instance state, and the existing Vue panel, adapters and mount run on it with no change a reader can see.
Depends on: Phase 6 (the unified turn driver), Phase 1 (characterisation tests)
Requirements: CORE-03, CORE-04, CORE-05, CORE-06, CORE-07, CORE-08, CORE-09, CORE-10
Success Criteria (what must be TRUE):
- Code under
src/coreimports novue, DOM or UI framework, andscripts/check-docpilot.shfails the build if it does. Its reactivity is@vue/reactivityinlined into the build, so a consumer of the core never installs Vue. - Two panels on one page, two SSR requests and two tests never share chat state (
createChat()per instance). A send while a reply streams does not double submit, and regenerate is refused while streaming. The core exposes a status machine (submitted, streaming, ready, error) over a transport interface, so browser-direct and server SSE turns share one code path. - Site owner can bind the core from any framework through
subscribe/getSnapshot, and can build their own UI with a headless stores package (ReactuseSyncExternalStore, Vue, Svelte). - The Vue panel runs on the core through a bridge, and citations, openers, history, quote, tools, budget and accessibility behave as in 2.1.1 (the Phase 1 characterisation tests pass). The Vue, React and Docusaurus adapters and
mountare thin wrappers over the same core. Plans: 15 plans in 13 waves
Plans: Wave 1
Wave 2 (blocked on Wave 1 completion)
Wave 3 (blocked on Wave 2 completion)
Wave 4 (blocked on Wave 3 completion)
Wave 5 (blocked on Wave 4 completion)
Wave 6 (blocked on Wave 5 completion)
Wave 7 (blocked on Wave 6 completion)
Wave 8 (blocked on Wave 7 completion)
Wave 9 (blocked on Wave 8 completion)
Wave 10 (blocked on Wave 9 completion)
Wave 11 (blocked on Wave 10 completion)
Wave 12 (blocked on Wave 11 completion)
Wave 13 (blocked on Wave 12 completion)
Phase 8: Feature registry and modular bundle
Goal: A site ships only the features it turns on, the minimal bundle is substantially smaller than today's 1.19 MB, and every size is measured and published. Depends on: Phase 7 (Vue-free core), Phase 1 (bundle audit) Requirements: BNDL-02, BNDL-03, BNDL-04, BNDL-05, BNDL-06, BNDL-07, BNDL-08, BNDL-09, BNDL-10, BNDL-11, BNDL-12 Success Criteria (what must be TRUE):
- Site owner can compose features with
createDocPilot({ features: [...] }), and a feature not listed is not in the bundle. Each optional feature (scope, tools, openers, feedback, highlighters, quote, history and the rest) is a side-effect-free subpath export with an accuratesideEffectsentry, shown by a consumer-bundler tree-shake test. - A feature turned on in config lazy-loads its own chunk through a literal specifier that webpack and Docusaurus resolve. A vanilla launcher of a few KB loads the panel on first open or hover, and Shiki, Prism, highlight.js and
markdown-itload lazily. docpilot bundle --features <list>builds a custom<script>bundle from prebuilt chunks and a generated loader, and the same list gives the same output.docpilot bundle --single-filebuilds one file through an optional esbuild install.npm run verifyfails when the minimal bundle or any feature exceeds its size budget, and the minimal bundle is substantially smaller than 1.19 MB. The docs show a per-feature size table generated from one JSON source.publintand@arethetypeswrong/clipass.docpilot doctorwarns when the config uses a feature the bundle lacks, and when the bundle carries a feature the config never uses. Research:import()from a classic script under strict CSP and under Docusaurus / webpack;sideEffectsaudit of module-level state.
Phase 9: MCP server, MCP client and permissions
Goal: Coding agents reach the docs through an MCP endpoint on the server runtime, the assistant calls the tools of external MCP servers, and one policy that only the server owner writes decides which tool runs for whom; token scopes, tool annotations and reader choices can only narrow it. Design: engine-spec 042.
Depends on: Phase 6 (the unified turn driver for the approval pause; through it, the Phase 4 index holder and StorageAdapter). The panel approval card of PERM-04 lands on the Phase 7 chat core.
Requirements: MCPS-01, MCPS-02, MCPS-03, MCPS-04, MCPS-05, MCPS-06, MCPS-07, MCPS-08, MCPC-01, MCPC-02, MCPC-03, MCPC-04, MCPC-05, PERM-01, PERM-02, PERM-03, PERM-04, PERM-05, PERM-06, PERM-07, CONN-09, PERM-08
Success Criteria (what must be TRUE):
- Site owner turns on
/mcp, andclaude mcp add --transport http docs https://<host>/mcp --header "Authorization: Bearer <token>"connects. Claude Code, Cursor and VS Code listsearch_docs,fetch_section,expand_sectionandlist_pages;search_docsreturns at most 8 ranked sections with the ids the panel cites, and no read calls a chat model. Clients on protocol versions 2025-06-18, 2025-11-25 and 2026-07-28 all connect. - A call with no token off loopback is 401, a foreign
Originis 403, and no response carries a CORS header. A token scoped to one path prefix and two tools can neither read outside the prefix nor call another tool, a revoked token fails its next call, and a swapped index reaches an agent without a restart. - Site owner lists an external MCP server with credentials from the environment, and in a server-runtime turn the assistant calls an allowed tool and cites its result. A tool the policy does not name is never offered, a new upstream tool waits for the policy, a down server leaves the turn answered, and the build scan finds no MCP URL or credential in the bundle, the manifest or the logs.
- A tool in
askmode pauses the turn, and the panel shows the tool, its server and the exact arguments with allow once, allow for this conversation and deny. Nothing runs before the choice, and no reader choice, token scope or annotation makes anofftool callable (one test per widening attempt). docpilot permissions list|explain|setanddocpilot mcp token create|list|revokework, and a change applies on the next call without a restart.docpilot doctorwarns on a risky setup, and every call is logged with the caller, the tool, the decision and the deciding layer.- The maintainer runs
/mcplocally first:docpilot serveanddocker compose -f docker/compose.yaml upboth serve it, and Claude Code on the same machine connects with no token over loopback. Then the same handler runs as a Vercel function on a preview deployment of the docs site: Claude Code connects with a Bearer token that lives only in the Vercel environment, a call without it is 401, and the built-output scan finds no token. - Site owner lists an external MCP server as a connector (
type: 'mcp'), anddocpilot connectors test,pullandsyncturn its resources (or one named read-only tool's result) into Markdown snapshot pages thatindexand the server store read like any other source; its URL and credentials never reach a client artifact. - A product whose proxy sends a token scoped to
source: ['site', 'web']gets answers and MCP results from those sources only, even when its request asks for another source; a request filter narrows inside that scope; a request without a token gets the server's default ceiling. Research: The protocol versions Claude Code, Cursor and VS Code send at that time; the official MCP SDK versus a hand-written client for the client half; the signed pause and resume across the browser, server and eval drivers; whether any target client needs OAuth 2.1 rather than a static Bearer token. For the Vercel deploy (MCPS-08): how a Vercel function serves stateless Streamable HTTP withinmaxDuration, how it loads the static index on a cold start, and where tokens live and how a revoke takes effect on a host with no writable disk.
Phase 10: Package split and rename to @cloflin/ai
Goal: 3.0 ships as one package, @cloflin/ai, whose subpaths core, server, mcp, chat-ui and cli each import alone and carry only their own layer, and every @cloflin/docpilot user has a mapped way across.
Depends on: Phase 8 (per-feature exports), Phase 9 (the mcp layer). The chat-ui subpath ships the current Vue UI on the framework-free core from Phase 7, through a mount function and thin wrappers, with no raw .vue exports.
Requirements: PKG-01, PKG-02, PKG-03, PKG-04, PKG-05, PKG-06, PKG-07
Success Criteria (what must be TRUE):
- In a clean project, the packed
@cloflin/aitarball installs and each of@cloflin/ai/core,/server,/mcp,/chat-uiand/cliimports alone. A server-only or MCP-only install needs no Vue, andchat-uipulls in no Node built-in. npm run checkfails on an import that breaks the layer graph, andsrc/config.tsis split into a browser-safe part and a Node part, with resolution still offline.npx @cloflin/ai indexanddocpilot indexrun the same command.@cloflin/docpilotcarries a final 2.x release and annpm deprecatemessage that names@cloflin/ai, anddocpilot doctor --migrateand the migration guide map every old import to its new subpath.@cloflin/aipublishes through trusted publishing on av*tag, with the first publish and the trusted-publisher setup documented as a manual step. Research: npm trusted publishing for a new package name; hownpx @cloflin/airesolves its bin;exportsand types per subpath underpublintand@arethetypeswrong/cli.
Phase 11: Release and acceptance
Goal: 3.0 ships with a safe upgrade path, and the motivating reference site runs on stock DocPilot with an edit visible in an answer and no eval regression. Depends on: Phase 10 (and all earlier phases, including Phase 9) Requirements: REL-02, REL-03, REL-04, REL-05, REL-06, REL-07, REL-08, REL-09, REL-10, REL-11 Success Criteria (what must be TRUE):
- A 2.x release warns on every export and option that 3.0 removes, and
docpilot doctor --migratefinds old options and imports in a project and shows the replacement for each. - 3.0 refuses an old-format index with a message that names the rebuild command, and strict config validation names the replacement for every removed option.
- A migration guide and both changelogs cover every breaking change, and
3.0.0-rcpublishes on thenextdist-tag without movinglatest. - The reference site that motivated 3.0 runs on stock 3.0, with its DocPilot patch script and hand-written import scripts deleted.
- Acceptance: an edit to an Intercom article appears in an answer without a server restart, and eval recall, refusal and groundedness on
rag/andrag-local/are no worse than the 2.1.1 baseline, with the new sources measured. - The new product name and website are live; the docs site, README, npm metadata and the 2.x deprecation notice name them and link to the new site.
Phase 12: Web Component UI
Goal: A decision backed by the bundle audit and an accessibility spike settles whether a Lit <docpilot-panel> replaces the Vue UI. The phase runs after the release and lands in a 3.x minor release. On "go" the component ships behind thin wrappers; on "no-go" nothing changes, the Vue UI stays and the reason is recorded. The swap is non-breaking: the wrappers' props and events and the --dp-* tokens stay the same.
Depends on: Phase 11 (3.0 is released), Phase 8 (the bundle audit)
Requirements: CORE-11
Success Criteria (what must be TRUE):
- A go/no-go record exists with numbers: Vue's share of the minimal bundle after Phase 8, and spike results for focus trap, aria references, selection / quote and host themes (VitePress, Docusaurus) under Shadow DOM.
- On "no-go", the Vue UI ships unchanged, the phase closes with the recorded reason, and no Web Component code is merged.
- On "go",
<docpilot-panel>works in an open shadow DOM with CSS variables and parts, and thin Vue, React and Docusaurus wrappers pass real-framework smoke tests with accessibility parity against the Vue UI. - On "go", the swap ships in a 3.x minor release without a breaking change: the wrappers' props and events and the
--dp-*tokens are the same as in 3.0, and the Vue UI is removed in that same release, so only one UI implementation ships. Research: Lit and Shadow DOM accessibility spike (focus trap, aria references, selection / quote, host themes).
Progress
Execution Order: Phases execute in number order, which is the dependency order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → 9 → 10 → 11 → 12. Phase 4 depends only on Phase 1 and may overlap Phases 2 and 3. Phase 5 needs both Phase 3 and Phase 4. The client track (Phases 7-8) starts after Phase 6 delivers the unified turn driver. Phase 9 needs Phase 6 and may overlap Phases 7-8; its panel approval plan (PERM-04) waits for Phase 7. Phase 10 needs Phases 8 and 9, and Phase 11 ships after Phase 10. Phase 12 (Web Component UI) follows the release and lands in a 3.x minor release.
| Phase | Plans Complete | Status | Completed |
|---|---|---|---|
| 1. Baselines and shared document pipeline | 12/12 | Complete | 2026-10-30 |
| 2. HTML extraction | 12/12 | Complete | 2026-10-30 |
| 3. Source connectors and snapshot pull | 16/16 | Complete | 2026-11-02 |
| 4. Server storage and hot swap | 14/14 | Complete | 2026-11-03 |
| 5. Sync engine, freshness and wiki connectors | 8/20 | In Progress | - |
| 6. Unified turn pipeline and server retrieval | 0/TBD | Not started | - |
| 7. Vue-free chat core | 0/TBD | Not started | - |
| 8. Feature registry and modular bundle | 0/TBD | Not started | - |
| 9. MCP server, MCP client and permissions | 0/TBD | Not started | - |
| 10. Package split and rename to @cloflin/ai | 0/TBD | Not started | - |
| 11. Release and acceptance | 0/TBD | Not started | - |
| 12. Web Component UI | 0/TBD | Not started | - |