Changelog
All notable changes to this project. Format loosely follows Keep a Changelog; this project adheres to Semantic Versioning.
[0.2.0] - 2026-06-26
Section titled “[0.2.0] - 2026-06-26”The MVP: an LLM-agnostic engine + Claude Code plugin that walks a web app, follows written flows, and emits screenshot-rich docs. Calibration is AI-assisted and rare; execution is deterministic, agent-free, and CI-friendly.
Bare docsxai meta-package
Section titled “Bare docsxai meta-package”docsxaion npm is the batteries-included CLI package.packages/docsxai/carries abin.mjsthat resolves@docsxai/engine’s CLI entry (new@docsxai/engine/cliexport) and runs it in-process (no spawn), plusindex.mjs/index.d.mtsre-exporting the engine’s library surface. Dependencies are exactly@docsxai/engine+@docsxai/viewer- the viewer dep is deliberate, so onepnpm add -g docsxaiputsdocsxai-vieweron the path anddocsxai renderworks out of the box through the engine’s layered viewer resolution. Gated by a real subprocess test (init+lintagainst a fixture workspace through the wrapper bin).
Engine - docsxai doctor
Section titled “Engine - docsxai doctor”docsxai doctor [<workspace-dir>]- environment + workspace health-check: ✓/✗ checklist with a one-line fix per failing row (− rows are informational; exit 1 on any ✗). Checks: Node >= 20; Chromium presence for playwright-core (the documented one-shot install as the fix);.docsxai.jsonfound + parseable (cwd or the arg; informational when absent); every flow-file parses (count; first error fails); auth descriptor parse + cached-session freshness (expired →capture-authfix hint); backend reachability viaGET /v1/healthwhenbackend_urlis configured (with a token-presence note); the plugin declarations through the same stage-1 inspectionplugins listruns - declared/installed/lock/capabilities, no plugin code executed; viewer-bin resolution naming which of the three layers hit; andDOCSX_*env sanity (DOCSX_CACHE_KEYwell-formed when set; unknownDOCSX_*names flagged as likely typos).
MCP server (@docsxai/mcp)
Section titled “MCP server (@docsxai/mcp)”- Standalone stdio MCP server (
docsxai-mcpbin,--workspace <dir>default) exposing calibration meta-orchestration + read-only doc-pack introspection to any MCP-speaking host - no browser primitives (live-page discovery stays browxai’s surface). Fourteen tools:init_workspace,run_flows(flow filter /startFrom/stopAfter/ CDP attach / bounded concurrency; per-flow ok / halt-cause / artifact paths; merged-flowenvironmentpassed into the Playwright session),render_viewer,lint_flows(incl. pluginextraRules),flow_tree,diagnose_halt,style_check,zip_pack,push_pack,pull_pack,list_flows,get_annotations,get_run_artifacts(paths only),plugins_list. Structured{ok, …} | {ok:false, error, hint}results throughout. - Scripted-client acceptance suite - an in-process linked client/server pair over the SDK’s
InMemoryTransportdrives the whole surface as a non-Claude MCP client, includingrun_flowsagainst the toy-site fixture over real Chromium (loopbacknode:http, Chromium-gated). Add-a-tool checklist:docs/ai-context/tool-registration/mcp-tool-registry.md. - Streamable-HTTP transport is not yet implemented; the stdio transport is the supported surface.
Engine - plugins runtime (@docsxai/engine)
Section titled “Engine - plugins runtime (@docsxai/engine)”- Workspace plugin runtime v1 - four extension points (publishers, renderers, lint-rules, auth-strategies) via a
docsxaimanifest on a plugin package’spackage.jsonplus aregister(api)module. Resolved once per CLI invocation; mandatory<namespace>:<name>prefixing (reserved:docsxai,site-docs,core,plugins);dependsOntopological load with cycle rejection; capability declarations (egress:<host-glob>) subset-checked against workspaceplugin_capabilities; in-process and unsandboxed -trustis a review signal. Lifecycle contract:docs/ai-context/plugin-runtime/lifecycle-and-namespacing.md. docsxai plugins list|info|sync- status table (load/disable reasons), manifest introspection, andplugins-lock.jsonsha256 pinning verified before any register module is imported (mismatch fails closed;syncnever executes plugin code).
Engine - ADF export + Confluence publisher
Section titled “Engine - ADF export + Confluence publisher”docsxai export adf+projectDocPackToAdf- pure, deterministic Confluence ADF projection of the doc pack (zero HTTP): one consolidated document with anchored H2 flow sections (defaultsinglemode) or a parent overview + one document per flow (page-tree); markdown-subset → ADF converter (paragraphs, bold/em/code, links, lists, fenced code; raw HTML stays literal text); per-stepmediaSinglenodes referencing burned PNGs (clean-screenshot fallback with a warning) plus an attachments manifest with sha256s. Writes<workspace>/.export/adf/{projection,attachments}.json- the artifact a host agent hands to the Atlassian MCP.@docsxai/plugin-confluence- first publisher plugin (confluence:push): Confluence Cloud REST v2 via built-infetch, capability-declaredegress:*.atlassian.net(the only Confluence egress path - the engine emits projections only). Page identity is the{ section → pageId }config.page_map(each result page echoes itssection); idempotent via adocsxai-content-shacontent-property - re-publishing an unchanged projection performs zero mutations, and attachment uploads are skipped when the same-name attachment carries a matchingdocsxai-sha256:<hex>comment; the API token is masked as<CONFLUENCE_TOKEN>in every error/log line. Verified against an in-process fake v2 server that counts mutations, loaded through the realresolvePluginspath.
Engine - execution determinism + redaction
Section titled “Engine - execution determinism + redaction”environmentblock in the flow-file (clockfreeze,locale,timezone,viewportincl.desktop/tablet/mobilepresets,color_scheme,reduced_motion) applied at session creation; per-key child-winsextendsmerge; CDP-attached sessions apply what page-level APIs allow and warn once on the rest.- Deterministic
redactions- flow-level + per-step, selector- or region-based,box(solid fill) orpixelate(16px mosaic); applied in-memory before any screenshot byte hits disk, halt screenshots included; annotation-on-redacted-target lint guard. - Real
element_stable- best-effort bounding-box stability poll (two consecutive identical reads, 10 s budget). - Lint R005-R010 (missing
extendstarget, unused locator, terminal step withoutsuccess, un-guardedoptional, selector-lesselement_stable, annotation anchored to a redacted element) + injectableextraRulesfor lint-rule plugins. - Byte-identical determinism keystone - frozen-clock + redacted flow re-run twice asserts identical screenshot bytes against real Chromium.
BrowserDriver.screenshotgained an optionalredactionsparameter (external driver implementers take note).
Engine - workspace + CLI hygiene
Section titled “Engine - workspace + CLI hygiene”resolveWorkspacePath/resolveWorkspacePathReal- the filesystem chokepoint: every workspace artifact read/write routes through containment checks (separator-boundary prefix + realpath symlink-escape defense); typedWorkspacePathEscapeError.- In-process deterministic
docsxai zip(fflate) - no systemzipbinary; sorted entries, zip-epoch mtimes, fixed compression: same doc pack → byte-identical archive; workspace-escaping symlinks never archived. - Layered viewer-bin resolution for
render-DOCSX_VIEWER_BIN→ installed@docsxai/viewerbin (run with current Node) → PATH, all three attempts reported on failure. - Full library surface exported from the package root (lint / flow-tree / diagnose / style / backend-client / doc-pack-io / zip were previously CLI-only); dead in-engine pipeline Stage contract removed (the dropped calibration-stage shape - agent orchestration lives at the harness/MCP layer).
Engine (@docsxai/engine)
Section titled “Engine (@docsxai/engine)”- Flow-file format - declarative YAML (
prerequisites/locators/steps[]),extends:composition, schema-validated, hand-editable. Actions:navigate/click/fill/upload(file-input via PlaywrightsetInputFiles) /press/hover/select/check/uncheck/wait. - Deterministic runtime -
docsxai runreplays a doc pack headless with zero agent/LLM involvement; byte-identical re-runs (keystone test). optional: truesteps - best-effort steps for conditionally-present UI (confirmation modals, first-run tooltips, cookie banners); skipped (logged, no screenshot/annotation) instead of halting.- Calibration aids -
docsxai lint(static flow-file checks),flow-tree(extends-graph + collision check),diagnose(halt context + typed recommendations),inspect(live-page locator discovery). - Fast iteration -
run --start-from <step> --cdp <endpoint>skips to a tail step against an already-warm Chrome; sub-3-sec inner loop on long-async flows. actionable()predicate - portable element-state probe (actionable/disabled/off-screen/covered/…) for browser-bridge consumers; contract indocs/actionability-contract.md.- Halt-cause prefix - flow-execution errors lead with an inferred 1-line cause parsed from the Playwright actionability log.
- Target-site auth -
auth/strategy.yamldescriptor +manual-capturestrategy (security-lowered instrumented Chrome, localstorageStatecache, real-cookie-expiry tracking, persistent profile,--cdpattach). - Scripted auth catalogue - unattended re-auth strategies, one module per scheme under
src/auth/:api-login(redirect-chain cookie collection via an own RFC-6265 jar),ui-form(drive the app’s login form;pre_stepsfor pre-login chrome;options.totpRFC-6238 hop with dep-freegenerateTotp/verifyTotp),email-otp(pluggableInboxProviderpolling -http-jsonbuilt-in,code_patternextraction,registerInboxProviderhook),webauthn(CDP virtual authenticator attached before navigation),jwt-injection(static token or OAuth2 client-credentials mint; localStorage/cookie injection),http-basic/pat-header/mtls(connection-level context options),test-backdoor. Credential user pools (comma-separated env values; per-worker consistent pick viaresolveCreds),registerAuthStrategyplugin hook consulted before the built-ins,expiresAtderived whenever credible (cookie expiry / JWTexp/expires_in), secret values never echoed. - Style artifact -
docsxai styleinit/validate + derived JSON + jargon-leak scanner (semantic-reshape enforcement). - Hand-off -
docsxai zippackages a reviewer-ready archive (excludes operator-local.auth/, halts,.viewer/). - Backend client -
docsxai login/push/pullagainst the stub backend (linear immutable revisions).
Viewer - Starlight docs site (@docsxai/viewer)
Section titled “Viewer - Starlight docs site (@docsxai/viewer)”emitStarlightSite/buildStarlightSite+docsxai-viewer site- emits a complete, buildable Astro Starlight project from a doc pack: one MDX page per flow (H2 per step, step prose verbatim,<AnnotatedShot>figures with captions numbered to the burned badge indexes), a landing page of flow cards, a sidebar ordered by the flowextendsgraph, theme accent/logo from the style artifact’svisualkeys (--title/--accentoverrides). Burned PNGs preferred, clean-screenshot fallback. Deterministic (two emits byte-identical), self-contained (no remote fonts/CDN imports);astro@6.4.6+@astrojs/starlight@0.40.0(MIT) exact-pinned into the emittedpackage.json;--buildrunsastro buildagainst the workspace-pinned install via per-package symlinks (zero network at build), real-build E2E gated behindDOCSX_STARLIGHT_BUILD=1. The single-file interactive viewer remains the zero-dependency default/embed renderer.@docsxai/plugin-starlight- first renderer plugin (starlight:site): thin adapter over the emitter/builder, zero capabilities, loaded through the realresolvePluginspath in tests.
Engine - drift detection + test export
Section titled “Engine - drift detection + test export”docsxai baseline+docsxai diff- deterministic drift reports (docsxai/drift@1): id-keyed step deltas, annotation moves beyond a px tolerance, exact RGBA screenshot pixel diffs (withignore_regions), prose line-change counts, locator changes;--format json|md|text(the markdown form is PR-comment-ready) and a--fail-on warn|failCI gate. Drift detection is engine-deterministic; the patch proposal stays an explicit agent step (diagnose) - never ambient.docsxai export playwright- one self-contained Playwright.spec.tsper flow (extends resolved,environmentastest.use()+ fixed clock, optional steps try/catch-wrapped, regenerate-don’t-hand-edit header): the doc pack doubles as a regression suite.
Backend - GitHub App webhook surface (@docsxai/backend)
Section titled “Backend - GitHub App webhook surface (@docsxai/backend)”POST /v1/github/webhook- HMAC-SHA-256-signature-verified (timing-safe; GitHub’s documented test vector pinned), event-filtered, replay-guarded (last 100 delivery ids) webhook endpoint; per-projectwebhook-configCRUD (repo mapping, events, output strategy, revision pin). Zero YAML in user repos - config lives in the backend.- Run dispatch - per-project serial
QueuedDispatcher→SpawnRunner: materializes the configured revision into a temp workspace, runs the engine CLI, appends run history. - Output strategies -
pr-comment(GitHub REST comment with the run/drift summary),viewer-refresh(re-render recorded as a content-addressed blob),wiki-push(the project’s configured publisher plugin via the engine plugin runtime). App registration, webhook URL/secret, and installation tokens are owner-gated (checklist in the backend README).
Backend - persistence, blobs, OAuth, encrypted cache (@docsxai/backend)
Section titled “Backend - persistence, blobs, OAuth, encrypted cache (@docsxai/backend)”- Filesystem persistence -
FsStorebehind the newBackendStoreinterface (atomic tmp+rename writes, traversal-guarded paths), selected via--data-dir/DOCSX_DATA_DIR; the in-memory store remains the default for tests. - Content-addressed blobs -
POST/GET/HEAD /v1/blobs(sha256-addressed, deduplicated) with 10 MB JSON / 25 MB blob body limits (413). Screenshots travel asdocsxai/screenshots@2sha256 manifests; the engine HEAD-probes, uploads, and integrity-verifies on pull (base64 payloads are gone). - Revision finalisation -
POST …/revisions/:rev/finalize; artifact PUTs afterwards are rejected 409 (revision-finalized);docsxai pushfinalizes - linear-immutable is now enforced, not aspirational. - OAuth 2.1 + PKCE - S256-only authorization-code flow with single-use 5-minute codes, refresh-token rotation, sha256-hashed token storage; CI keeps the
DOCSX_TOKENbearer path.docsxai login --oauthruns the loopback handshake and stores tokens at.auth/backend-token.json(0600) with auto-refresh. - Encrypted storage-state relay -
PUT/GET/DELETE /v1/workspaces/:ws/auth-cache/:rolestores client-side AES-256-GCM envelopes (BackendStateCache, key fromDOCSX_CACHE_KEY); the backend never sees plaintext session state. - Run history wired -
docsxai runappends execution records to backend-bound workspaces (offline-tolerant).
Viewer - burn renderer + hardening (@docsxai/viewer)
Section titled “Viewer - burn renderer + hardening (@docsxai/viewer)”burn- durable burned annotations - browser-free Satori → resvg pipeline bakes halo/badge/callout/arrow onto screenshot copies (docs/<flow>/burned/), byte-deterministic, positioned by the sameplaceCalloutas the interactive viewer; vendored Inter (OFL-1.1). The static-delivery path for Confluence/Notion-class surfaces.- Single-sourced overlay - the inline viewer script is bundled at build from
overlay-runtime.tsimporting the realplaceCallout; the hand-maintained ES5 port is gone. - CSP + safe markdown - every emitted page carries
default-src 'none'; img-src 'self' data:; style-src 'unsafe-inline'; script-src 'unsafe-inline'(zero network egress), and step write-ups render through micromark in safe mode instead of<pre>.
Engine - CLI integration
Section titled “Engine - CLI integration”docsxai runapplies the merged flow’senvironmentblock to every launched session;docsxai lintresolves the workspace plugin registry and runs registered lint-rule plugins after the built-ins (plugin failures degrade to core rules with a warning).
Plugin (@docsxai/plugin)
Section titled “Plugin (@docsxai/plugin)”- Claude Code plugin:
calibrate+diagnoseskills;run/render/login/push/pullcommands. - Static bundle validation (
validatePluginBundle) cross-checked against the engine CLI surface.
Viewer (@docsxai/viewer)
Section titled “Viewer (@docsxai/viewer)”- Static HTML viewer: pulsing halo + numbered badges + Popper-placed callouts over clean screenshots; per-annotation
nudge. - Robust two-pass callout sizing measured on a
document.body-attached probe (the callout is detached +display:noneuntil:hoverat build time, so an in-place measure bakeswidth:0pxand collapses it to a one-character column); no-cache metas + visible render timestamp.
Backend (@docsxai/backend)
Section titled “Backend (@docsxai/backend)”- Stub service with the concrete REST endpoint list, bearer auth, in-memory linear immutable revisions. (Persistent backing + OAuth interactive flow are post-MVP.)
Skill (@docsxai/skill)
Section titled “Skill (@docsxai/skill)”- Vendorable
.claude/skills/fallback delegating to the installed plugin.
Cross-cutting
Section titled “Cross-cutting”- Apache-2.0; OSS-clean; public-release-ready content.
- ~208 tests across the monorepo; typecheck clean; CI = typecheck + test on Node 20 / pnpm.
- Browxai is the canonical model-agnostic discovery driver (integration contract in
docs/browxai-asks.md).
Quality + governance baseline
Section titled “Quality + governance baseline”- ESLint flat config with custom rules (
no-tracker-ids-in-comments,no-page-eval-stringified-arrow). - Strict Prettier +
.editorconfig+.githooks/+ extended quality CI workflow (lint / format-check / audit / secret-scan / zizmor / package-contents jobs). - Multi-harness configuration:
AGENTS.md,.cursor/rules/,.codex/,.agents/skills/,.claude/agents/. docs/ai-contextsubtree - architecture, agent-process, secrets-and-egress, testing, release-process, investigations, adopter-reports.- Governance:
SECURITY.md,CODE_OF_CONDUCT.md(Contributor Covenant 2.1),MAINTAINERS.md,THIRD_PARTY_NOTICES.md, expandedCONTRIBUTING.md. - Security best practices for adopters.
- Per-package
tsconfig.build.json(sourceMapanddeclarationMapoff; excludes test files). - Per-package builds clean
dist/+tsconfig.build.tsbuildinfofirst (scripts/clean-dist.mjs), so stale compiled artifacts can never survive a rebuild or leak into a published tarball;scripts/audit-package-contents.mjsnow audits thedocsxaistub tarball too. - Dedicated
packages/docsxai/publishable stub withpublishConfigfor OIDC trusted publishing. - 6-package OIDC publish pipeline in
release.yml. release.ymlgithub-releasejob: creates the GitHub Release for the tag (generated notes) and attaches a CycloneDX SBOM (pinnedcdxgen) once both publish jobs succeed; the scoped-publish filter excludes the repo-only packages (@docsxai/{mcp,plugin-confluence,plugin-starlight,website}) explicitly, matching theirprivate: trueflags.
Docs site (@docsxai/website)
Section titled “Docs site (@docsxai/website)”- Public documentation site (docsxai.dev) - Astro 6 + Starlight 0.40 workspace package in
website/, ember (golden-bronze) brand layer, six-section IA (Start here / Concepts / Guides / Reference / Packages / Project).sync-docs.mjsgenerates the published ports from the canonical sources (docs/*.md, package READMEs,CHANGELOG.md,CONTRIBUTING.md,SECURITY.md) with per-source-depth link rewriting and per-page strike/replace rules;scripts/prose-guard.mjsbans em/en dashes and stock AI-voice tells from every published page. Netlify deploy config + rootdocs:dev/docs:build/docs:previewproxies. docs/agent-guidance.md- the reach-for-this-not-that footgun map for calibration agents (ten temptations, why each bites, the right call with a copyable example), synced to the site under Guides, summarised inllms.txt’s new## Guidancesection, and cross-linked from “for agents” asides on the flow-file / CLI / troubleshooting / writing-plugins pages.- Reference worked examples - every CLI command shows a realistic invocation with its printed output and exit code; per-strategy auth descriptor snippets (env-var names only); a plugins CLI session; MCP call/result pairs per tool family; curl request/response pairs per backend route group. All output shapes transcribed from the engine/backend source, never invented.
- Sidebar spacing per the family spec - group separation, summary padding, label sizing/tracking/opacity, item padding/line-height, and nested-item sizing aligned with the sibling sites’ exact values; selectors verified against the built DOM.
Changed
Section titled “Changed”- Project-wide rename to
docsxai- a single pre-publish clean break (no compatibility aliases): CLIsite-docs→docsxai; npm packages@kalebtec/docsxai-*→@docsxai/*on the registered@docsxaiorg; env varsSITE_DOCS_*→DOCSX_*; workspace config.site-docs.json→.docsxai.json; schema idssite-docs/<thing>@N→docsxai/<thing>@N; API version headerSite-Docs-API-Version→Docsxai-Api-Version; page helperwindow.__siteDocs→window.__docsxai; Claude Code plugin manifest + slash commands/site-docs:*→/docsxai:*. The plugin runtime keepssite-docsinRESERVED_NAMESPACESdefensively. - Renamed workspace packages
@kalebtec/site-docs-*→@kalebtec/docsxai-*(engine, backend, plugin, skill, viewer); workspace rootsite-docs-monorepo→docsxai-monorepo. - CLI bin names
site-docs-backend→docsxai-backend, etc. - 5 scoped workspace packages flipped from
private: trueto publishable. - Repo root structure: historical closure plans moved to
docs/archive/phase-plans/. - Lint baseline driven to 0 errors / 0 warnings (load-bearing CI gate).
- Sourcemap leak gates added; published tarballs verified clean.
- Updated
docs/agent-runbook.mdanddocs/running-against-an-app-repo.mdto use the current viewer / backend bin names (docsxai-viewer,docsxai-backend) after the rename fromsite-docs-*. - Refreshed
packages/plugin/README.md:push/pullcommands shipped, dropped from the TODO row;style-learn/translateremoved entirely (not on the near-term roadmap); MCP-server note recast as a possible future addition rather than a deferred deliverable. - Added
TypeScript configs for packages and libsandPackage formatting scriptssections todocs/ai-context/agent-process/code-quality.md, codifying the per-packagetsconfig.json(dev / typecheck) +tsconfig.build.json(emit, excludes tests) split and the root-cwdpnpm format/format:checkconvention.
- CLI browser-install hints name the
playwright-corecommands that match the repo’s pinned-install discipline (npx playwright-core install chromium; source checkouts:pnpm -C packages/engine exec playwright-core install chromium) instead of the unpinnednpx playwright install chromium. - The missing-flows error now names the workspace, the expected
flows/path, and thedocsxai init/docsxai calibratenext steps instead of the bareno flows directory at <path>. - The website build no longer logs a
/404route conflict on every run: the branded 404 moved from the docs collection to a file-basedsrc/pages/404.astro(still Starlight-framed via<StarlightPage>), Starlight’s injected 404 route is disabled, and the page now emits as404.html- the file Netlify serves for unmatched paths (the collection entry built to404/index.html, which Netlify ignores). - CI build-step ordering (added
pnpm -r buildbeforepnpm -r testso engine’s workspace-package resolution works). - 22-day red CI on
maincleared after lockfile + build-step ordering fixes. - 9 high-severity zizmor workflow findings cleared (cache-poisoning, excessive-permissions, unpinned-uses, bot-conditions).
- One
no-page-eval-stringified-arrowviolation inpackages/engine/src/playwright-instrumented-browser.ts- converted to function expression +PageEvaltype wrapper.
Removed
Section titled “Removed”- Empty
examples/stub directory (real keystone fixtures live atpackages/engine/test/fixtures/toy-site/). - Workspace-root publishable stub (replaced by dedicated
packages/docsxai/sub-package).
Security
Section titled “Security”- Trufflehog secret-scan in CI (replaced gitleaks per universal-baseline rule 28 cost/availability).
- Bot-identity hardening in
dependabot-auto-merge.yml(user.type == 'Bot'+user.login == 'dependabot[bot]'check, not spoofablegithub.actor). - All third-party GitHub Actions SHA-pinned with version comments.
release.ymluses OIDC trusted publishing (noNPM_TOKEN); environment-gated; tag-triggered only.