Skip to content
pleach
Reference

Changelog — combined view (legacy)

Site-content changes for getpleach.com, newest-first, unified view across every SKU. Per-SKU pages live one directory level up at /docs/changelog/<sku>.

This is the combined view — the original chronological, multi-SKU site-content changelog for getpleach.com. It records changes to the site itself: new docs pages, corrections, and the upstream packs each change reflects. It is not the runtime changelog; the per-package CHANGELOG.md files in the upstream @pleach/* repository hold the canonical record of runtime behavior.

For a SKU-scoped view, see the per-SKU pages under /docs/changelog — each one excerpts the entries below that materially touched its docs surface.

The mirror copy at /CHANGELOG.md is the source of truth in the repo. Both files update together, not separately. When a site change tracks an upstream pack, the entry cites the upstream commit so the linkage is auditable.

Format follows Keep a Changelog.

Unreleased

Changed

  • @pleach/mcp documents the shipped transports, security defaults, and multi-tenant routing. The page drops every "throws NotImplementedError", "scaffold", and "Phase B" statement. It now covers stdio, createSSETransport (HTTP+SSE, superseded in the MCP spec by Streamable HTTP, which streamableHttp: true serves from the same server), and createWebSocketTransport over the optional ws peer. New sections cover the loopback-default Host and Origin allowlists and the refusal of a non-loopback bind without tenantIdExtractor, resolveRuntime, or allowUnauthenticated; multi-tenant routing (multiTenant, tenantIdExtractor, resolveRuntime({ connectionId, tenantId, sessionId }), registerSession({ tenantId }), allowUntenantedSessions, fail-closed -32001, visibleTo, register(tool, { tenantScoped }), name-collision errors, registerResources(provider, { perRequest: true })); native execution (nativeExecution: true, fail-closed approval checks, and the shallow argument validation it enforces); the limits table (maxConnections, maxConnectionsPerTenant, maxInFlightPerConnection, maxExecutingRequests, maxExecutingRequestsPerTenant, requestTimeoutMs, idleTimeoutMs, heartbeatIntervalMs, maxPayloadBytes, toolCacheTtlMs) and the per-request AbortSignal; and masked error messages with a correlation ref for remote clients, verbatim over stdio. The quickstart passed an executor that always threw, and an explicit executor wins, so every tools/call failed; it now builds a stock runtime with a plugin tool and sets nativeExecution: true. refreshArtifactCache / refreshSandboxCache are documented with the (runtime, opts) form and the older forms. MCP integration and the Packages row are updated to match. Upstream source, not yet published to npm.

Fixed

  • Server samples import only from @pleach/core/quickstart. @pleach/core/server isn't a published subpath, and Server taught it in five samples. The createHarnessServer sample is now a createPleachRoutes({ capabilities }) override; the createInMemorySharedInterruptResolver sample imports from @pleach/core/quickstart and passes the resolver as capabilities.interruptResolver; the Next.js, Express, and Hono mounting examples use routes.nextRouteHandlers(), routes.nodeHttp(), and routes.fetch. The bare HarnessServer / ROUTES import block is gone, and the handler sections are labelled as internals reached over HTTP. Two corrections ride along: the durable-resolver sample passed a resolver as capabilities.interrupts instead of capabilities.interruptResolver, and the Next.js catch-all samples on Server and API routes omitted basePath, without which the dispatcher can't match /api/harness/... paths. Interrupts, Turn lifecycle, and SessionRuntime now point at the route factory instead of HarnessServer.

Changed

  • Sandbox auth callbacks accept both header shapes. Sandbox providers and File tools keep their auth: async () => ({ headers: { Authorization: … } }) samples and now state that a flat header map ({ Authorization: … }) is accepted too, on httpStream, httpPoll, and awsFargate. A result counts as wrapped only when its single key is headers holding an object; { headers: null } means no auth headers; a non-string header value throws a TypeError that names the header without echoing its value. The samples' environment variables are renamed to the vendor-neutral SANDBOX_BASE_URL / SANDBOX_TOKEN. Upstream source, not yet published to npm.

Added

  • Gateway llm.invocation spans ship. Gateway · OpenTelemetry replaces its "dedicated tracer is roadmap" section and hand-rolled span shim with the shipped behavior: one llm.invocation span per routed call from GatewayClient.route() and per transport-served GatewayRuntime.routeChatCompletion() call; the tracer option (tracer: null disables, omitted → trace.getTracer("@pleach/gateway") from the optional @opentelemetry/api peer); the attribute list per surface; errors recording only error.type and http.response.status_code with the fixed message llm invocation failed; and RouteChatCompletionInput.callClass, validated against ALL_CALL_CLASSES and used for attribution only. @pleach/gateway drops the "OTEL span emission is not in Phase A" bullet, lists spans as shipped, and adds tracer to the constructor-options table. The packages-table row already said spans ship and is unchanged. Upstream source, not yet published to npm.

Changed

  • The three cloud transport pages document the shipped surface. /docs/transport-bedrock covers credentialProvider (AWS SDK v3 provider shape, e.g. fromContainerMetadata()), credentialRefreshSkewMs (default 300000), onAuthError, the generic "bedrock: authentication failed" event, and the optional @aws-sdk/client-bedrock-runtime peer. /docs/transport-azure-openai covers opt-in managed identity (credential: "default"), the Azure-host or allowedEndpointHosts endpoint rule, and the optional @azure/identity peer. /docs/transport-vertex covers ADC and workload identity, the /^[a-z0-9-]+$/ location rule, and a multi-tenant warning that omitting credentials means ambient ADC. All three drop "cloud-specific cost-event emission", which the source doesn't do, and keep the "not yet published, workspace install" framing. Cloud-routed agent fixes its Bedrock example, which resolved the container credential once into credentials and so never refreshed it; it now passes credentialProvider: fromContainerMetadata(). Its claim that the audit row records the role ARN is replaced with what the transports do: the credential error stays server side. New per-SKU changelog pages: content/docs/changelog/transport-bedrock.mdx, transport-azure-openai.mdx, transport-vertex.mdx, linked from the changelog hub.

Added

  • Per-call-class model routing is honoured, not recorded-only. Model resolution matrix gains a "Per-call-class overrides" section for SessionRuntimeConfig.perCallClassModelRouting: routes are honoured by createProviderAdapter and the quickstart standard adapter; cross-family routes, routes whose family can't be derived, and routes that arrive before the lock is observable are refused and disclosed ([PerCallClassRouting] override-refused, auditMetadata.perCallClassRouting); a routed call is priced at the matched rung's rates, and a model in no rung is left unpriced; a custom quickstart providerStream must dispatch to ctx.resolvedModel when it is present. Multi-synthesize drops the "forward-compatible, honoured once the core widening ships" framing for createPerCallClassRouting: core now reads the field. Upstream source, not yet published to npm.

  • Sub-agent cost rolls up to the parent turn. Subagents gains a "Cost attribution" section for SessionRuntime#getTurnCostRollup(turnId?), which returns { turnId, self, descendants, total, partial, truncated } and splits the root turn's own calls from every sub-agent's. Each bucket reports callCount, pricedCalls, unpricedCalls, costUsd (omitted when nothing was priced) and four token totals. The section states the limits: background async.spawn tasks are excluded; callCount and costUsd are floors when calls are unpriced; total can differ from the durable cost.rollup row; retention is LRU over 32 turns, and a row arriving after release or eviction is marked truncated. Event log documents the quickstart message.assistant row's payload.cost_rollup snapshot (root_turn_key, snapshot, as_of, self, descendants, total, partial, truncated). The "Subagent cost attribution to the parent turn" row in content/docs/migrating-from-anthropic-enterprise.mdx now names runtime.getTurnCostRollup(turnId). Upstream source, not yet published to npm.

Fixed

  • Replay no longer promises byte-identical output. A live model can't guarantee it. eval-and-replay.mdx ("Checking a replay for divergence"), glossary.mdx, glossary.schema.ts, seams.mdx, faq.mdx, faq.schema.ts, agent-shapes.mdx, swarm-agent.mdx, the comparison tables in with-mastra.mdx, with-inngest.mdx, and migrating-from-anthropic-enterprise.mdx, fingerprint.mdx, architecture.mdx, config-manifest.mdx, landscape.mdx (row 2 is now "Replay of the agent path"), regulated-domain-agent.mdx, language-agnostic-contract.mdx, use-cases/education.mdx, recipes/subagent-swarm.mdx, with-openai-sdk.mdx, with-anthropic-sdk.mdx, migrating-from-langchain.mdx, migrating-from-openai-enterprise.mdx, the /faq capability list, and components/node-graph-diagram.tsx now say what ships: replay re-serves the recorded stream and drift raises ReplayDivergenceError. Deterministic folds over the event log keep their byte-identical wording; that is code, not a model call.
  • Audit-record claims now match what the code enforces. The homepage pillar, components/session-manifest-diagram.tsx, content/docs/security.mdx, replay.mdx, ci-enforcement.mdx, audit-ledger.mdx, and compliance/gdpr-erasure.mdx said rows are "written once and never edited or deleted" or "immutable". The ledger API has no update or delete primitive, but that does not stop a writer with direct database access. The pages now say so, and say what the hash chain adds: edits, deletions, and reordering become detectable after the fact.
  • Attestation is signable, not signed by default. glossary.mdx, glossary.schema.ts, cloud-routed-agent.mdx, and region-pinned-agent.mdx called the manifest "signed". compliance.mdx already documents that envelopes stay unsigned unless a key store is configured; the other pages now agree.
  • Drifting counts removed or labelled. The package count read 13, 14, 15, or 19 depending on the page, while the packages.mdx table lists 17 entries; overview cards, which-sku.mdx, license-compatibility.mdx, and organization.jsonld now point at the table instead of restating a number. Hook counts are labelled by what they count: 80 total (plugins/authoring.mdx), 71 contribute* hooks (plugin-contract.mdx); the stale 41 in runtime-inspector.mdx is gone. nodes.mdx and graph-node-catalog.mdx disagreed on every node total (44 vs 42); the totals are dropped and the catalog's per-stage counts stay canonical.
  • Competitor and survey claims are dated. Each table in comparison.mdx carries a callout giving the month its competitor column was written. landscape.mdx absolutes ("Nobody forks mid-step", "the finest grain in the field") now read "none of the frameworks we reviewed, as of" a month. The FAQ's AI SDK claim and the homepage capability survey are dated the same way. A date marks when the claim was written, not a re-check.
  • Host-specific names removed. env-vars.mdx, subagents.mdx, recipes/compliant-chatbot.mdx, fabrication-detection.mdx, and lib/theme.ts named one particular embedding host or its domain terms; they now describe a generic host. The exported detector name detectMarkdownSmilesMismatch is unchanged.

Changed

  • Edge runtimes are no longer supported. @pleach/core runs on Node.js (server side) or in a browser. Edge servers (Vercel Edge, Cloudflare Workers) and any server runtime without AsyncLocalStorage are refused: tool execution needs per-request isolation, and a shared context slot would let concurrent requests see each other's identity. Entering a tool-execution scope there throws ToolExecutionContextUnsupportedRuntimeError (code PLEACH_TOOL_EXECUTION_CONTEXT_UNSUPPORTED_RUNTIME, runtime of "edge" or "server-without-async-local-storage"; see Error codes), and the quickstart createPleachRoute() answers 501 before any stream starts. Move Edge routes to the Node.js runtime. The install, quickstart, deployment, and FAQ pages drop their Workers / Edge claims accordingly.
  • Turn stop is a client disconnect with a declared intent. SessionRuntime gains a "Stopping a streamed turn from the client" section: the client declares at stream-open what its disconnect means (header x-pleach-on-disconnect or query on_disconnect), the stream handler classifies the abort ("user" for a declared stop, "error" otherwise, "timeout" first when the server closes the stream — first abort wins), and there is no stop route or shared stop flag. Documents parseDisconnectIntent, bindDisconnectToTurnAbort, createTurnAborter, and DISCONNECT_INTENT; notes the intent values may be renamed before publish. Deployment replaces the abortSignal: req.signal route example with a bound disconnect. Server documents the optional third request argument to HarnessServer.handleExecuteMessage and threads it through the Next.js, Express, and Hono adapters. Turn lifecycle, Session lifecycle, and API routes point at the new contract; resume after a stop hydrates from the session store and checkpointer.
  • Homepage leads with tamper-evidence and narrows two claims. The eyebrow reads "Tamper-evident agent audit" and the H1 "Every model call your agent makes, as one row you own."; title, Open Graph, and Twitter metadata follow. Section headings now state claims, and each capability card carries one artifact quoted from the docs (verifyChain result shapes, ReplayDivergenceError, GROUP BY parent_turn_id). The replay claim drops "byte-identical": replay re-serves recorded responses and names the first divergence, and rerunning the same model with a human or LLM judge for equivalence is marked as not shipped. The subagent claim now matches Subagents: spend rolls up by GROUP BY parent_turn_id, rather than "stored on the parent turn". A proof strip names verifyChain, audit:graph-stages, the Go round-trip, and dated competitor claims. The gateway strip moves below the capabilities. A new "Agent-native" block covers /llms.txt, Markdown twins, and the facet API. "Ways in" shows the two shipped paths, with @pleach/observe as a one-line teaser. npm install @pleach/core sits under the hero CTA and repeats in the closing CTA.
  • Homepage cut to hero, capabilities, three ways in, a three-question FAQ, and a closing call to action. Capabilities now lead with the differentiators in the order Landscape ranks them: the tamper-evident record, then replay with family-lock and event-granular fork, then subagent cost rollup, each beside the diagram that shows it; the hero subhead and meta descriptions follow the same order. The node-graph section moved to core.mdx ("A node graph, not a single stream"); the field section's decision diagram moved to comparison.mdx; the Enterprise section's gateway note and OpenAI Enterprise card moved to migrating-from-anthropic-enterprise.mdx. The FAQPage JSON-LD lists exactly the three questions on the page.
  • The lattice diagram is drawn as a layered network. lattice-diagram.tsx shows each stage as a layer of nodes: three at anchor-plan, six at tool-loop (with a recurrent arc for iteration), one at synthesize, two at post-turn. Edges only join adjacent layers, and signals travel one lit path layer by layer (.pleach-flow in app/global.css, off under reduced motion and below 1024px). Labels and caption are unchanged.
  • The hero background is the rotating six-strand weave again. components/pleach-motif.tsx restores the six rotated strand pairs, the three backing strands, and the 360s .pleach-drift rotation that the visual pass had cut to one static pair.
  • Visual and accessibility pass. One filled call to action; section diagrams stay beside their claims (md:sticky); all diagrams share components/diagram-tokens.ts (two stroke weights, one radius, an 11px label floor, sage for your recorded data). Docs prose is capped at 70ch with tabular numerals in tables. Nested <main> landmarks are gone, docs pages gain a main landmark, and a skip link leads to it. Copy buttons announce "Copied", scrollable code and tables take keyboard focus, coarse-pointer targets are 44px, mermaid renders at securityLevel: 'strict', and the dark-mode primary is lifted to 3.5:1 against the page.

Added

  • Eight new rows in the Comparison capability matrix, covering shipped capabilities that had no row, each verified against the upstream package source before writing:
    • Context compaction — SummarizationMiddleware (token-threshold history summarization) + ResultEvictionMiddleware (oversized tool-result eviction). Recorded as opt-in: neither installs by default; createPleachRoute wires eviction only when resultOffloadBackend is set.
    • Sandboxed code execution — the @pleach/sandbox SandboxProvider contract + endpoint-shape adapters; core's code_exec tool refuses every call until a host injects a runner. No computer-use or browser surface is claimed (none exists).
    • Safety-policy API — defineSafetyPolicy + registry, three enforcement levels (advisory / guardrail / refusal). Recorded honestly: all three map to a log_only effect today (prompt prose + audit record); block_tool_call / block_synthesis are declared future values with no enforcing call site.
    • Agent Skills — SkillLoader, SKILL.md + YAML frontmatter, three sources, intent-matched injection.
    • Durable execution, promoted from the Inngest side-table into the main matrix — implicit per-turn checkpoints, checkpoints.rollback / sessions.resume, event-granular replay; no automatic mid-turn crash-resume (AsyncTaskManager snapshots pending tasks into checkpoint metadata; nothing rehydrates them).
    • Background / scheduled runs — schedule tools persist intent to the store; the runtime has no timer of its own, the host fires due tasks via readScheduledTasks.
    • Long-term memory — @pleach/core/memory fact extraction + cross-agent consolidation (executor-gated post-turn nodes) and pgvector-backed SupabaseStore.search.
    • MCP — @pleach/mcp is a server (MCPServer wrapping the runtime, stdio / SSE / WebSocket transports); the mcpServers client-attach config field exists in types but is unconsumed, so no client-side attach is claimed.
    • Plus: the OTel matrix row now names the semconv boundary — core spans use the pleach.* attribute namespace; the GenAI-semconv gen_ai.* set (gen_ai.system, gen_ai.request.model, gen_ai.usage.input_tokens, gen_ai.usage.output_tokens, gen_ai.operation.name) ships in @pleach/observe's OTel destination.
  • One clarifying sentence at the top of Channels: a channel is a reactive state slot in the execution graph, not a delivery/messaging channel.

Fixed

  • Comparison contradicted the package on memory. The "Agent-memory & knowledge-graph substrates" section framed memory as a category the substrate doesn't ship, while @pleach/core/memory ships extraction, consolidation, and semantic recall. The section now states that up front and its table compares a dedicated memory product against the AuditableCall ledger specifically, not the package as a whole.
  • Migrating from LangChain pointed stream-level subscribers at the wrong API. The pitfalls table said "use runtime.on"; runtime.on subscribes to runtime lifecycle events, not the stream. The row now names runtime.subscribeToStream(mode, callback) (mode first, then callback).
  • Four Graph examples could not compile, each checked against the upstream StateGraph.ts / Annotation.ts:
    • addNode metadata was shown as { stageId, acceptsSeam, inputs, outputs }; the real NodeMetadata is { subscribes?, writes?, retryPolicy?, passiveProjector? } (inputs / outputs exist nowhere; stageId / acceptsSeam live on the separate *_NODE_METADATA constants the lattice gate reads).
    • AnnotationRoot({...}) was called as a function; AnnotationRoot is a class and the factory is Annotation.Root(schema).
    • Two-arg .addConditionalEdges(from, routeFn) calls; the third destinations: Record<string, string> argument is required.
    • Route functions returning Send[]; PathFn is (state) => string | string[], and the core barrel itself marks Send / isSend as exported-but-not-engine-wired. The Send section now documents the envelope as consumer-composable and names string[] returns as the fan-out the engine honors. The default-agent-graph example's import was also repointed from the unpublished @pleach/core/graph barrel to the published @pleach/core/graph/defaultAgentGraph + @pleach/core/graph/defaultAgentState entries.

Added

  • Six shipped @pleach/core mechanisms documented for the first time, each verified against the upstream source before writing:
    • Graph — G-14 subscription-derived transition validation: the engine routes by subscription, and audit:graph-stages derives writer → subscriber stage pairs from declared subscribes/writes, validating them against the lattice with per-(subscriber, channel) exemptions in ACCEPTED_SUBSCRIPTION_TRANSITIONS that fail the gate when stale.
    • Graph — SuperstepRunner engine guarantees (@pleach/core/engine): convergence detection, configurable termination channels, per-node RetryPolicy override with exponential backoff, write-filtered node skipping.
    • Tamper-evident hash chain — keyed (HMAC-SHA256) C9 chains: EventLogWriter's c9SigningKey makes row_hash recompute-resistant against a database-level rewriter; rows record chain_key_version = 'pleach.c9.v2' so the verifier resolves the mode per chat.
    • Tamper-evident hash chain — chain segment anchors: computeSegmentSeed / isSegmentAnchorRow and the _chain_segment_anchor marker, stamped before payload_hash / row_hash so both hashes cover it; off by default because minting an anchor is a semantic act on an append-only ledger.
    • OTEL spans — the graph.stage span bills to the dispatch stage (a pure function of the triggered node set), not the reporting stage that carries the stage-transition breadcrumb and lattice verdict.
    • Providers — the stream-watchdog ladder behind the stalled-provider pivot: a record-only content-starvation audit threshold, class-scoped zero-delta and starvation unwind thresholds, and a tool-call-phase grace window.

Fixed

  • Graph contradicted itself about synthesize → tool-loop. The allowed-patterns paragraph named it as the bounded re-entry while the forbidden-set paragraph also listed it as forbidden. The upstream topology.ts is unambiguous: the pair moved to ALLOWED_EDGE_PATTERNS on 2026-08-14 as the bounded re-entry, and the forbidden slot beside synthesize → anchor-plan is the retired synthesize → synthesize self-loop. The forbidden paragraph now matches, keeping the 9-allowed / 7-forbidden split over the 4×4 cross-product intact.

  • The graph-node registry count was stale by one everywhere it appeared: 43 → 42 (Graph, Node catalog, Audit gates, Ownership). The upstream NODE_STAGE_MAP in topology.ts carries 42 keys; the 43 figure predated the upstream 2026-08-21 registry cleanup.

  • Node catalog listed two names that were never nodes. workspaceIndex is a channel name; toolLoopStream is a seam-observation identity. Both rows were deleted from the upstream NODE_STAGE_MAP on 2026-08-21 and are now removed here. The same pass re-stages garbledContentGuard and repetitionGuard from the tool-loop table to post-turn, matching their upstream 2026-08-20 re-stage; the per-stage headers now read 9 / 23 / 1 / 9.

  • Plugin hook counts corrected on three pages, from one re-enumeration of HarnessPlugin. Core said 68 contributeX hooks; the interface carries 71. Authoring said 77 hooks (68 + 9); the real total is 80 (71 contribute* + 9 lifecycle), and its bucket table — which summed to 67 — now carries all 71 (contributeStreamFilters, contributeErrorClassifiers, contributeAuthEventSink, contributeIntentJustifiedTools, and contributeIntentClassificationInstruction were the missing five). Plugin contract keeps its 70 — that number is the audit:plugin-contract-completeness roster, a narrower denominator — and now names that denominator so the three pages stop appearing contradictory.

  • Two mirrors in scripts/audit-docs-vs-contract.mjs were behind the upstream contract. CANONICAL_HOOKS was missing contributeIntentJustifiedTools (79 → 80 entries). CLAIM_ANCHORS omitted three rows present in the upstream manifest: Family lock → pickNextInFamily, Graph → four-stage lattice, Call classes → synthesisQuality.terminalSynthesis. All three phrases were already on their pages, so the rows arm the drift guard without changing shipped prose.

  • Heartwood — the loader's two-scope resolution and shadow semantics, previously undocumented. createFileHeartwoodLoader resolves first-non-empty-wins across an explicit path, ./HEARTWOOD.md (the per-project soul), and ~/.pleach/heartwood.md (the user-global soul). The scopes shadow, not merge: the first file found wins entirely, so a project ./HEARTWOOD.md fully overrides the user-global file rather than concatenating with it. The page had named only the path override.

  • Prompt builder — the composition-determinism guarantee stated outright. A static or core contribution's content is a pure function of its PromptContext and does not vary with tool-loop depth or turn recursion. contributeRuntimeAwarePrompts is the only channel that varies per turn, and static contributions are held out of the RuntimeStateSnapshot on purpose. Matching pointer added to Prompts.

  • Skills — the create_skill base-tool for agent-authored skills. An agent can name a repeatable procedure as a reusable skill mid-session. create_skill is opt-in (list it in include) and available when the runtime has a durable store to persist to; authored skills surface through the same progressive-disclosure path as loaded skills — an in-prompt index entry plus an on-demand skill_view body.

  • Defensive patterns — a new Architecture page: six design rules the runtime holds itself to, each paired with the shipped @pleach/core API that embodies it. Orthogonal outcome reporting (GraphExitMeta.aborted vs abortedByUser), explicit default resolution, the branded-id idiom (SafetyPolicyId / PromptContributionId), load-time config failure (PluginValidationError, assertShredCapableDdl), teardown quiescence (AsyncTaskManager.seal() / awaitQuiescence() / SessionRuntimeConfig.destroyQuiescenceTimeoutMs — upstream dfbbd6f239 + a3ad79dce1), and per-plugin exception containment in PluginManager fan-outs. States honestly which rules are mechanism and which are convention.

  • Tuning shadow (experimental) — the new @pleach/core/graph/tuning subpath. Five tool-loop knobs (TuningKnobId), quantile-and-clamp derivation (KnobDerivationPolicy), the TuningShadowSnapshot holder and TUNING_SHADOW_SNAPSHOT env installer, and the [tuning:shadow] knob-delta telemetry contract — including the reading rule that a zero-emit capture means no snapshot installed, never "no divergence". Upstream 938cbeb90d.

  • Human feedback — the new @pleach/core/feedback subpath. recordFeedback writes up to two sinks (a durable domain.<ns>.feedback.recorded row plus a meta-namespace memory write for corrections/preferences), never throws, and returns a structured result with six error codes. The section states the bounds and the honest status: the corrections namespace has no reader yet. Two matching rows added to Subpath exports. Upstream 4cb20440c5.

  • Per-turn tool directives and the step cap (Session runtime, Migrating from the AI SDK). executeMessage now takes toolChoice and activeTools; SessionRuntimeConfig gains maxGraphSteps (lowering-only, resolved by resolveGraphStepBound). The migration page maps maxSteps / stopWhen → maxGraphSteps, toolChoice → toolChoice, experimental_activeTools / activeTools → activeTools, with the two semantic differences stated. Upstream 022c2cd00e.

  • runtime.run() — the non-streaming turn verb. Documents run(sessionId, content) as the fold over executeMessage, the TurnResult field table, foldTurnStream from the root barrel, and the name collision with @pleach/core/testing's different TurnResult. Upstream 895e3b7224.

  • The defineTool → ToolDefinitionLite bridge. toToolDefinitionLite, isToolDefinition, and AnyToolDefinition from @pleach/core/tools and the root barrel; createPleachAgent applies the bridge automatically. Also documents the additive execute second parameter ctx?: ToolLiteExecuteContext ({ toolCallId?, signal? }). Upstream d75b4aafc4.

  • Bulk cancellation on AsyncTaskManager. cancelAllPending(filter?) returns an AsyncTaskBulkCancelReceipt; the page explains why executorAcknowledged is the load-bearing figure. Upstream f47547dd60.

  • Durable pending interrupts. InterruptManager.snapshotPending() / rehydrate() persist pending approvals to CheckpointMetadata.pendingInterrupts, so an interrupt pending at checkpoint time survives a process restart or time-travel restore. Upstream 6d0c3e0fc2.

  • answer.sufficiency joined HARNESS_EVENT_TYPES, and flush() reports real durability (Event log). emitAnswerSufficiency + ANSWER_SUFFICIENCY_REASON_MAX_CHARS documented; createPgEventLogWriter().flush() resolves to an EventLogFlushResult and never rejects — check .ok. Upstream 5624e43040, 6fdfcf0875.

  • Redaction fail-open is now observable, or forbidable (Compliance). PipelineResult carries failures/complete, ingressDetailed/egressDetailed return the text alongside the evidence, and createRedactionGate({ failClosed: true }) throws RedactionIncompleteError instead of handing back part-scrubbed text. The fail-open default is stated plainly, with the reason. Upstream 018fb5c11e.

  • unsupported-algorithm added to the attestation verdict table. Split from schema-invalid because the distinction is evidentiary: one state says the record is malformed, the other says the verifier is older than the record. Still fail-closed. Upstream e9204811ae.

  • What a fork inherits. TimeTravelAPI.fork() stamps the parent's chat manifest onto the forked session row as well as the forked checkpoint, so a branch survives source-checkpoint pruning. Upstream 1dffcff710.

  • The CLI page's TUI rewrite gets its changelog row. The page was rewritten for the fold-in of the Go terminal UI into @pleach/core: four subcommands, pleach tui as what a bare npx pleach runs (previously the init wizard — a breaking CLI default, called out in a warning box), the --print/--events/ --tune flags, and the deprecated --demo alias that runs a real billed turn. Upstream 586cfe12e6.

Changed

  • @pleach/replay's cache-mode member renamed: strict-mode → log-only (Replay, Comparison). The rename ships without a back-compat alias — core's CacheReadPolicy keeps a strict-mode member for a different boundary, and an accepted "strict-mode" would preserve exactly that collision. The mode table, prose, and example now say log-only; the comparison page's "strict-mode replay" phrase was disambiguated to strict replay (@pleach/replay/strict). Cache and Eval are correct as written and unchanged. Upstream a43b94f526.

  • replayTurn() resolves the turn boundary by identity, not adjacency (Replay). turn.completed is a colliding event type — the stream terminal never reaches the durable log, and the stored row is per-LLM-call — so the handle forward-scans for the last row bearing the turn's message_id. Upstream 8be1010f3b.

  • Safety enforcement v1.2 documented (Safety policies). SAFETY_ENFORCEMENT_EFFECTS now maps guardrail → block_tool_call and refusal → block_synthesis, gated on the operator opt-in safetyEnforcementMode: "enforce" (default "prose-only" preserves the prior posture byte-for-byte). Two concrete guard kinds ship; the page's "no kind is implemented yet" and "v1.1 is prose-only across all three" claims are corrected. Upstream 4c785c4db1.

  • verifyAfterBatch is three-state (Hash-chain middleware, What's new 2026-06). The verdict is now HashChainVerifyVerdict with outcome: "verified" | "nothing-to-verify" | "verification-unavailable"; the third arm reports chainValid: false. The page previously documented the soft-fail of the runtime-error sentinel to { chainValid: true } as intended policy — that inversion is exactly what upstream fixed, and the section now says so. Upstream 018fb5c11e.

  • Send[] fan-out carries the engine-wired semantics (Graph). Scoped per-Send state overlay, Send-index fold order for replay determinism, anchor-plan/tool-loop same-stage admission, the maxSendsPerSuperstep cap (default 16), and loud errors on the sequential fallback path and post-terminal Sends. Upstream f4a0863346.

  • Both contract snapshots re-synced to upstream 2026-09-06. The export map gains ./feedback and ./graph/tuning (no removals — no taught path broke); the symbol snapshot re-walked all 19 packages to 335 subpaths. Subpath exports' named-entry count corrected 148 → 180.

Fixed

  • EvalSuite accepts cacheBackend and cacheReadPolicy but reads neither (content/docs/eval.mdx). Both are declared on EvalSuiteOptions; the class stores this.opts and reads only suiteId and runtime. The ## Per-suite cache backend section taught them as working knobs. It is now ## Cache configuration and points at the knobs that are live — SessionRuntimeConfig.cacheBackend and runtimeMode: "interactive" | "deterministic", including its fail-closed-without-tenantId rule — and states plainly that the two EvalSuiteOptions fields are accepted and inert in Phase A.

  • The query layer does not read only tables the runtime writes (content/docs/query.mdx). The page claimed it "reads from the same tables the runtime writes to". ai_chat_messages is the exception: it is host-provided, no code in @pleach/core writes it, and no DDL for it ships in the schema bundle — the three readers (query/usage.ts, query/tools.ts, query/review.ts) only .select(). The table now names the shipped .sql file per row and marks that one No — host-provided. Also recorded: ai_chat_manifests and refresh_chat_manifest_from_events ship in no SKU, so getChatManifest, getManifestJobsByStatus, getConversationState and getSessionReview require consumer-supplied schema.

  • @pleach/compliance does not add CI gates to a consumer's build (content/docs/compliance.mdx). The page described two gates — audit:tenant-scoping and audit:harness-event-log-tenant-id-required — as inherited at adoption time, across nine sites. Neither ships: the package declares no bin, and its files allowlist is dist, the two SBOMs, src/tenant-rls/policies.sql, and metadata — no scripts/ directory exists in the package at all. Both gates are monorepo-only; audit:tenant-scoping is an RLS-policy census over supabase/migrations/*.sql and never reads a .ts file. The section is now ## Wiring tenant isolation into your own CI and documents what does ship: the src/tenant-rls/policies.sql template and auditRlsPolicies(), which you call from your own CI. The gate table is reused verbatim from content/docs/audit-gates.mdx.

  • @pleach/observe's in-tree version is 0.1.0, not 0.1.0-alpha.0 (Packages, the docs index). Both call sites updated; the package remains scoped and not yet on npm (verified against the registry). Historical changelog entries keep the number they were written with.

Fixed

  • ObserveRow's parent-schema version was stated three different ways across the site. @pleach/observe and two recipe pages (agent instrumentation, BYOK observability) said AuditableCall v13; adoption paths and the package matrix said v7. The canonical AuditableCall row page says 19, verified against the upstream core package in the 2026-07-02 reference-page accuracy sweep — the two lower numbers predate it and were never re-swept. All nine call sites now read v19. Historical changelog entries keep the number they were written with.

  • The forward-compatibility claim was pinned to a version literal that wasn't carrying it. "Rows the SDK wrote yesterday remain valid v7 rows the runtime can read tomorrow" reads as if the version were the guarantee. The guarantee is that every bump in AUDIT_RECORD_VERSION_HISTORY is additive. Adoption paths now names the mechanism and drops the trailing version literal.

  • The Graph callout said seven symbols were unreachable; it is now six. Upstream published @pleach/core/graph/defaultAgentGraph the day after the callout was written, giving buildDefaultAgentGraph a home. A documented defect has a shelf life exactly like a documented feature. The six that remain: START, END, DEFAULT_TURN_FLAGS, StateGraphNodeMetadata, AnnotationSchema, InferAnnotationState.

  • The committed export-map snapshot was 32 entries stale one day after being committed. Upstream added 32 named @pleach/core subpaths and removed none between 2026-08-29 and 2026-08-30. Ten carry no previously-unreachable symbol — they narrow an already-reachable surface into a named entry rather than add capability, which is why they get no docs rows.

  • The page claimed the row does not carry "the fingerprint payload". Adding ObserveRow.fingerprint falsified the sentence directly beneath the shape. Reworded: the row carries its own narrower fp_v1: hash over {family, model, callClass, input}, computed by the SDK rather than lifted from the v13 record, while the full RoutingDecision, cascade walk history, and attestation hashes do stay undefined.

  • The @pleach/core/* wildcard section described a hatch that no longer exists (Subpath exports, with references on Versioning, Audit gates, and Publishing contract). The bare ./* export was replaced upstream by the scoped ./internal/*, so the page's "It works today" rule of thumb — and both worked examples, @pleach/core/graph/... and @pleach/core/replay/types — named paths that now throw ERR_PACKAGE_PATH_NOT_EXPORTED.

  • Graph and Graph node catalog taught import blocks that cannot compile. Both imported from @pleach/core/graph, which is not a key in the published exports map. Seven of the thirteen symbols in the Graph example had no published import path at all: START, END, buildDefaultAgentGraph, DEFAULT_TURN_FLAGS, StateGraphNodeMetadata, AnnotationSchema, InferAnnotationState. Corrected to import only what resolves, with a callout naming the seven and the workaround. Fixing the path alone would have produced an import that resolves and still fails to bind.

  • Hook-catalogue counts were stale by ~70% (Plugin contract, Runtime inspector). Both cited 41 hooks / 38 wired. Measured from the instrument the claim names, upstream audit:plugin-contract-completeness: 70 hooks — 66 wired end-to-end, 3 baselined awaiting consumer, 1 declared without a collector (contributeAuthEventSink). HarnessPlugin declares 78 members.

  • AuditRecordVersion cited as 19, now 25 (CI enforcement). Six additive versions landed since: outcome.why.stats.servingProvider, sub-agent attribution (parentTurnId / subagentId / subagentDepth), decision.lockedFamily, the provider-exhausted status, decision.fallbackChain becoming additive-optional so an omission is an admission rather than a fabricated [], and decision.rungOrdinal.

  • @pleach/core/audit-ledger is not a subpath (Attestation) — the published path is @pleach/core/audit. @pleach/observability is not a package (OTel observability) — the SKU is @pleach/observe and the shape is a destination. @pleach/core/schema/postgres (Schema) corrected to @pleach/core/schema/postgres/*.sql, the published .sql asset glob.

  • Subpath exports claimed to snapshot @pleach/core@1.x. No @pleach/* SKU has shipped past 0.1.0 — the same version-epoch error corrected across nine files in the entry below, in a tenth file that pass missed.

  • audit:docs-vs-contract gained a fourth check: EXPORT-MAP DRIFT. Every @pleach/... specifier the docs teach is now resolved against a committed mirror of each package's published exports map, so a specifier that would throw ERR_PACKAGE_PATH_NOT_EXPORTED on a fresh npm install fails at the point of drift. The site-side mirror of the upstream audit:doc-example-import-resolution gate. 2,348 specifiers resolved against 19 export maps; every fix above was found by it.

  • createFargateSandboxProvider now cites its own subpath (Sandbox). It was listed as shipping from @pleach/sandbox (root); upstream added @pleach/sandbox/adapters/awsFargate, matching the other three adapters. The root re-export still works and is noted.

  • Version-epoch claims corrected to 0.1.0 across 9 files — no @pleach/* SKU has shipped past the first-wave floor. Versioning claimed "the substrate has shipped one major (1.0.0) so far," directly contradicting Packages's own "every shipping package at the same 0.1.0 floor" and every upstream package.json. Also fixed: Fingerprint (PLEACH_CORE_VERSION example), Eval and replay (pleachVersion before/after example), Deployment + API routes (health-probe response "version"), Recipes (install example, also fixed from caret range to the required exact pin), @pleach/langchain (install example, was ~0.3.2 — not even internally consistent with the package's own real 0.1.0), and Plugin authoring standards (peer-dependency "Acceptable" example showed ^1.0.0, contradicting the exact-pin table nine lines below it in the same section). Left untouched: the many definePleachPlugin({ version: "1.0.0" }) examples across the site — those illustrate a plugin AUTHOR's own arbitrary semver, not a claim about any @pleach/* package.

Added

  • The *_CALL_CLASS constants from @pleach/core/graph/seams/callClassConstants. The page explained that lint:callclass-literals rejects a bare "synthesize" but never said what to write instead when you need the value rather than the type.

  • Six new subpath rows on Subpath exports: graph/defaultAgentGraph (the only published home for buildDefaultAgentGraph), graph/seams/callClassConstants, eventLog/durableFlush (setWaitUntilImpl / deferFlush / awaitPendingFlushes — the serverless durability seam), strategies/schemaCondensation, skills with its two narrower entries, and the four runtime/facets/* client-facet entries.

  • audit:docs-vs-contract gains a fifth check: SYMBOL REACHABILITY. Check (4) asks whether an import path resolves; this asks whether the symbol is exported by it. Correcting only the path yields an import that resolves and binds nothing. 1,265 named imports checked against a committed mirror of 7,166 symbols across 329 subpaths, mutation-proved three ways.

  • Reading rows back — the read side was entirely undocumented. query(filter) on the Memory, Postgres, and Supabase destinations, with the two boundary rules a consumer needs before aggregating: the window is half-open [since, until) so adjacent windows tile without double-counting, and both bounds compare against startedAt rather than completedAt, so a long call is attributed to the window it began in. QueryNotSupportedError is thrown rather than returning [], because an empty array is indistinguishable from "no rows matched". Also the opt-in persistFingerprint column and isRecorderInitialized().

  • ObserveRow.byokFailureChain and ObserveRow.fingerprint added to the documented row shape. byokFailureChain carries a four-character keyHint and never the key itself, so the row stays safe to ship to a dashboard your key-holders don't control. isCostAttributionKey / extractCostAttributionTags added to Cost attribution.

  • Four new @pleach/core subpaths on Subpath exports — attestation/cms, crypto, context, and the corrected wildcard story. @pleach/core/crypto is carried as experimental with its DDL precondition inline: on a schema declaring wrapped_dek or iv as NOT NULL, shred() raises SQLSTATE 23502 while getOrCreateDek still succeeds — so enabling encryption there mints ciphertext that can never be erased, and GDPR Article 17 becomes impossible. Verify nullability before the first DEK.

  • The CMS envelope — @pleach/core/attestation/cms emits a detached CMS (RFC 5652) SignedData over an attestation's canonical bytes, Ed25519 per RFC 8419, alongside AttestationV1.signature rather than instead of it. Documents buildAttestationDetachedCms, why certificateDer is effectively required for an independently-checkable artifact, and the RFC 5652 §5.4 re-tag invariant: signedAttrs is encoded [0] IMPLICIT but signed as a universal SET, and getting it wrong yields a structure that verifies nowhere while staying self-consistent. Core re-reads the emitted DER and throws a named signed-attributes-mismatch at emit time. Detect with isCmsAttestationError, never instanceof.

  • Which merkle construction built the root — MerkleConstruction and the merkleConstruction field on ChainProofV1. generateProof(...) defaults to "legacy" deliberately: switching a chat to "rfc6962" changes every root it produces, and existing anchors countersigned the legacy roots. Names both defects RFC 6962 fixes — no domain separation (leaf and internal node are both bare SHA-256, the second-preimage precondition) and odd-node duplication (the CVE-2012-2459 shape, where [A,B,C] and [A,B,C,C] share a root). Absence of the field means the proof predates it. Separate axis from chain_key_version.

  • session.ended and HARNESS_EVENT_TYPES. session.ended makes a clean close a positive fact rather than an inference from absence — and its own absence proves nothing, since a session whose process dies never writes one. HARNESS_EVENT_TYPES is the runtime mirror of the HarnessEvent union, pinned by an exhaustive Record<HarnessEventType, true> in production source. Membership means emittable, never persistable.

  • Auth events. AuthEventType, AuthMethodClass, AuthEvent, AuthEventSink, and contributeAuthEventSink. Core owns the vocabulary, the host owns the store: the C9 chain is keyed (tenant_id, chat_id) and an auth event has no chat by nature — measured at 4,269 chatless rows, zero chained — so writing them to the harness event log would produce a trail that looks complete while its integrity guarantee stops short of the access events an auditor reads first. Status stated honestly: no collectAuthEventSink() collector yet and no published exports entry for the vocabulary, so implementing the hook today compiles and does nothing.

  • Optional peer dependencies. @peculiar/asn1-{schema,cms,x509} for CMS attestation, @pleach/rbac-contract for @pleach/core/rbac, @modelcontextprotocol/sdk for MCP, @sigstore/core for RFC 3161 receipt verification. Each fails with a named error identifying the package rather than a module-resolution stack.

  • @pleach/observe/testing — the destination conformance harness. assertObserveDestinationConformance throws on the first failed check; runObserveDestinationConformance returns a ConformanceReport for a suite that wants every failure in one pass. The ObserveDestination interface constrains shape; the harness constrains behaviour. The API-surface table moves from six subpaths to seven.

  • The RFC 3161 surface is now reachable from the paths consumers actually walk, not only from the primitives. createPleachAgent takes a timestampAuthority — before this the quickstart called attestChainState without one and exposed no way to supply it, so the default path produced claim-only attestations permanently. Both the agent and the runtime now expose evidence (runtime.evidence: timestamped, mintAnchorMs, clockInjected), which reports what was wired and deliberately not what is true of the outside world — a configured-but-unreachable authority still reads timestamped: true, and there is no clockAnchored field because core cannot verify that claim.

  • chainAnchorScheduler in @pleach/recipes composes the scheduled anchor-and-verify pass that every consumer previously wrote by hand. It exposes runOnce() and no loop: a convenience start() was written and removed, because a scheduler with no retries, no at-most-once story and no observability is strictly worse than the one a consumer already runs, while looking like a supported way to do this in production. Also documented in Hash chain.

  • Hash chain now documents the anchor-verification surface, closing a promise the page already made — it ended on "the property is only real if something actually performs that check" without saying how. Covers verifyChainAnchors (re-deriving a witnessed merkle root catches a mid-chain deletion whose rows were re-linked cleanly, and therefore passes a prev_hash walk — a chain that verifies is not the same as a chain that matches its witness), evaluateChainAnchorFreshness (grade liveness on staleness, never on row count; anchorCount and timestampedAnchorCount are separate signals because damage and staleness are independent failures), and classifyChainAnchorAlertLevel. Two decisions are written up as generally applicable: liveness never shares a channel with tamper detection, and damaged evidence may withhold an escalation but must never produce a de-escalation.

  • Attestation documents createAnchoredClock (@pleach/core/runtime) — skew-corrected, monotonic, suspension-aware — and is explicit that it reduces honest clock error only. It does not upgrade issuedAt from a claim to a proof; only the TSA countersignature does that. Upstream: ivybiosciences-next RP-340.

  • @pleach/rbac-contract documented — new dedicated page, packages table row, subpath-exports entry, and cycle-break-pattern cross-reference. Zero-dep cycle-break contract package for role-based access control (RbacRuntime: checkPermission + getRolesForActor), the second SKU to use the pattern established by @pleach/compliance-contract. Landed upstream 2026-08-15. Documents @pleach/core/rbac's createRbacApprovalFlow adapter and its caveat: the ApprovalFlowContribution.checkApprovalNeeded plugin hook it targets has no shipped consumer in the reference host, so wiring the adapter alone is advisory pre-wiring, not an enforcement boundary.

  • Subpath exports gains three @pleach/core entries. @pleach/core/model-family (the RoutingDecision audit contract + model-family matrix + cascade logic — previously internal, now the surface @pleach/gateway routes through instead of a host-path alias, landed 2026-08-03) and @pleach/core/react/pure (browser-pure SessionSwitcherView / SessionCheckpointTimelineView / RecallPanelView, zero useHarnessContext dependency, for fetch-split apps, landed 2026-08-02) join @pleach/core/export (documented alongside the rbac-contract entry above).

  • @pleach/tools deprecation reflected on the packages table and its changelog page. The SKU flipped pleach.stability to deprecated upstream on 2026-08-03, the same day as @pleach/base-tools — the contract now ships inside @pleach/core at @pleach/core/tools / @pleach/core/tools/unified, standalone package retained only as a re-export shim. The dedicated @pleach/tools page already carried this callout; the packages table row and per-SKU changelog page did not.

  • Agent-forward usage surfaced as a value-prop on the homepage and Comparison. Pleach's surface is built to be operated by agents, not a human console with agent access added on. The homepage "Quick answers" intro now names the fuller discovery surface (per-page Markdown twins, a live MCP server, an agent-skills index, the introspectable facet API) rather than just /llms.txt; Comparison gains a cross-cutting "An agent-forward surface (a usage axis)" section citing the shipped artifacts (facet API + audit:facet-coverage gate, TechArticle JSON-LD from a controlled tag vocabulary, the MCP server with per-page SHA-256 digests). A usage axis, distinct from the capability differentiators; no existing value prop changed.

  • Regulated-domain agent names the reconstructibility test and adds validation-audience vocabulary. A new opener paragraph frames the auditor's question the way validation teams name it — reconstructibility: can a competent third party, working only from the audit trail, reconstruct what the agent did, on which inputs, and through which model, months later? It maps that bar to mechanisms the page already documents — the ordered, hash-chained event log folded to byte-identical state on replay — and states the boundary bolt-on tools hit: evidence produced by construction, not reconstructed after the fact. Adds the terms this audience actually searches — computer system validation (CSV), GAMP 5, audit-trail review.

  • Regulated-domain agent gains a keyword override and external-entity anchors. The page's keywords and TechArticle JSON-LD now lead with 21 cfr part 11, computer system validation, gxp, and audit trail, with sameAs anchors to eCFR Part 11 and the GxP / CSV / HIPAA / SOC 2 references so the page emits mentions for AI-search entity fusion. It previously inherited only the generic "Use cases" cluster tags.

  • Comparison adds a governance-control-plane / AI-gateway category. Covers Portkey, Cloudflare AI Gateway, Kong AI Gateway, LiteLLM, and TrueFoundry, plus the enterprise governed-proxy control planes now emerging above them. Frames the split as altitude, not timing: a proxy governs the call at the HTTP boundary and routes all traffic through a vendor plane; @pleach/core governs the agent's execution graph — records subagentDepth and the turn tree a proxy can't see — and writes the AuditableCall row to a database you own. Corrects a tempting-but-wrong "runtime-native vs post-hoc" line: true against the read-side observability tools, false against a governed proxy that also enforces in flight.

  • Gateway gains a "Not a proxy" framing block. The SKU that overlaps a governed proxy feature-for-feature (routing, over-budget refusal, cost attribution, failover) now states the distinction: gateway is an in-process routing client that never opens a socket of its own, versus a proxy that routes all traffic through a vendor and holds the audit trail on its side.

  • Landscape row 1 acknowledges proxy-side tamper-evident audit. The Tier-1 hash-chain row notes that governed-proxy control planes advertise "tamper-evident audit trails," but the trail lives on the vendor's side — a proxy-side log, not a hash-chained row in a database you own.

  • Five more @pleach/core public exports documented (720a6e8a3 / de4403b6a). Interrupts adds rewriteToolArguments (natural-language → structured-args rewrite for approval-with-edit; utility call class, never throws). Tools adds the standalone createDiscoverToolsTool / DISCOVER_TOOLS_TOOL_NAME factory. Server adds createPluginToolRegistry behind /tools and /tools/:name. Storage adds composeDurableStore plus the optional blob member and createMemoryBlobStore / MemoryBlobStore. Adoption paths names BrownfieldRuntimeMenu; Prompts names the optional PromptDescriptor surfaced by runtime.prompts.describe(). Upstream trunk, not yet published to npm.

  • A wave of previously-undocumented public reference surfaces added across the docs. From the same upstream sweep: the @pleach/core/manifest chat-manifest and config-manifest verify API (Config manifest, Checkpointing); the harness edge-case detector battery (Playground & DevTools); createInMemorySharedInterruptResolver (Server); gateway Identity providers and swarm governance, walkSessionTree, queryAudit / exportAuditPdf, and the RLS auditor (Gateway, Swarm agent, Audit ledger, Multi-tenant); the replay fork API + reproducibility manifest (Replay); eval cost estimation + judge seam (Eval); observe emitters + sampling (Observe); MCP projectors + MIME barrel (MCP); createMultiSynthesizePolicy (Coding agent); the named base-tools safety policies (Base tools); plus SubagentFanOutExceeded, the delivery: audit vocabulary, and the @pleach/langchain/to-langchain subpath.

  • Subpath exports reconciled with the @pleach/core exports map. Added ./pricing, ./testing, ./react/lab, the ./graph/* family (seams, recovery, topology, defaultAgentState), and six ./strategies/* entries.

  • New Pricing math page. Documents the previously undocumented @pleach/core/pricing subpath — computeTurnCost, the default rate matrix, the live-rate resolver, the OpenRouter fetch, and the cost-event reconciliation seam.

  • Four more undocumented public surfaces documented. Replay adds a Cache adapters section (disk / Redis / S3). Eval adds a Bundled benchmarks section (MMLU, HumanEval, SWE-bench, custom domain). Recipes adds the Clerk org → permitted families helper. React documents the full lab component kit and names @pleach/core/react/lab as its canonical subpath.

  • Reference sections for the corrected gateway/compliance surfaces. Gateway adds Tenant resolution, Failover, and Region routing sections. Compliance adds Advanced redaction (pipeline + PHI/Presidio/LLM scrubbers), cross-linked from Scrubbers. Determinism adds a Compliance certifier section. Sandbox adds an Endpoint-shape adapters table.

  • Fabrication detection grounding-detector cohort documented. Added the ~13 stable detectors the "Public exports" table omitted — the tabulated-absent, unresolved-job, and failed-compute checks plus the offloaded-envelope predicates.

  • Three @pleach/core prompt- and context-management capabilities documented. Orchestrator middleware adds the optional summaryProvider field on SummarizationConfig — a callback supplying a higher-quality (e.g. LLM-generated) rolling summary in place of the default extractive char-slice summary, falling back to the extractive default when it returns an empty value or throws. Prompt builder adds the "Cache-stable prefix" section: the stability: "stable" | "volatile" tag on BudgetedSection and the stableBoundaryIndex field on ComposedPrompt. composeBudgetedPrompt hoists stable sections into a contiguous prefix (untagged input stays byte-identical) and reports where the volatile suffix begins, so a consumer places its provider cache_control breakpoint after included[stableBoundaryIndex - 1]. Prompts adds "Persisting an agent's role" — put durable persona in the core.role-template slot via replaceCore / prependPersona and tag it stability: "stable". Performance gains one cross-reference to the new prefix helper. Upstream trunk, not yet published to npm.

  • Model-pipeline surface documented — two new pages plus eight section additions. Model hooks documents the @pleach/core/hooks pre/post-model seam (PreModelHook, PostModelHook + historyTrimmerHook, lazyModelDefaultsHook, toolCallValidatorHook, repetitionDetectorHook). Orchestrator middleware documents @pleach/core/middleware (OrchestratorMiddleware, MiddlewareStack, ResultEvictionMiddleware, SummarizationMiddleware, LanguageModelMiddleware, CHARS_PER_TOKEN). Both join Subpath exports under a new "Model pipeline" category with @pleach/core/synthesis. Sections added: finalizeAnswer

    • the { banner } return on postSynthesisGuard (Plugin authoring); ProviderCatalogContract and the SLOW_COLD_START_PLANNER_FAMILIES / isSlowColdStartPlannerFamily gate (Providers); InterruptManager.requestApprovalWithId (Interrupts); runtime.abort(reason) / AbortCoordinator + TURN_ABORT_REASON (Session runtime); the durable subagent.tool_used audit row (Subagents); and the harness_event_log_owner_select per-user RLS policy (Multi-tenant). Existing published @pleach/core surface; upstream trunk, not yet on npm.
  • Four @pleach/core runtime-behavior sections documented. Each mechanism shipped upstream but had no doc home. Tools gains weakToolSchemaBudgetPlugin (@pleach/core/prompts) plus createWeakToolSchemaPredicate (@pleach/core/modelfamily) — the proactive tool-call budget for weak-tool-schema families (google/deepseek/moonshot, defaults maxBatch: 4 / maxSameTool: 2). Turn lifecycle documents the no-first-token dead-air hard-cut (reduceTurnDeadAir; upstream d062ab24d5). Providers documents the stalled-rung cascade pivot, classed SYSTEM_ABORT not USER_ABORT (upstream e1fa3f1487). Fabrication detection documents metadata.uncoveredPlanSteps and the honest "not dispatched" note (upstream bb0f995fce, ca9dc86644). All from published subpaths or documented runtime behavior; upstream tree 8f224cbf42 on trunk, not yet published to npm.

  • Landscape and the homepage comparison now weigh OpenRouter's @openrouter/sdk. The routing/agent-loop SDK joins the field considered: named in the tier intro, folded into Tier 1 row 7 (adoption paths — callModel wraps the loop with routing and automatic tool execution but writes no audit primitive), and Tier 2 row 11 (per-turn cost — the callModel loop accumulates totalCost across turns and caps a run with a maxCost stop condition, but that total is in-memory guardrail state, not a persisted column). Added a homepage CompareCard for the SDK: one client across 300+ models with provider fallback, versus no turn-keyed audit row, no replay determinism, and no recorded family provenance after a fallback.

  • Standalone hosted-agent route family documented across API routes, Server, Quickstart, Storage, and Query. @pleach/core now ships a factory that mounts the whole route family, not just the single execute leg. Documented, all from published subpaths: createPleachRoutes and createPleachAgent (@pleach/core/quickstart) mount sessions CRUD, execute+SSE, interrupts, checkpoints, rollback, events-recall, sync, and fork. createPleachAgent({ context, tools, db }) is the three-arm façade over createPleachRoutes, returning { fetch, nextRoutes(), nodeHttp(), store }. DurableStore + createMemoryDurableStore() (@pleach/core/store) unify storage, checkpointer, event-write, event-read, and recall behind one binding; MemoryEventLog (@pleach/core/query) is the keyless in-memory recall ledger with an asQueryClient() Supabase-shaped shim — together they let recall work with no Supabase (omit db → in-memory store). Also documented createHarnessServer({ runtime, storage, checkpointer?, events? }) as the build-only auto-bind factory over the still-unpublished @pleach/core/server subpath, plus the known limitation that the default interrupt resolver binds a per-request in-process InterruptManager (a durable multi-request deployment supplies its own resolver via createPleachRoutes(...).capabilities.interrupts). Softened the API routes and Server "not a published subpath" callouts — the family is reachable from the published @pleach/core/quickstart subpath. Upstream: pleachtui Track A, @pleach/core@0.1.0 on trunk (Waves 0b34ab8742, 095d037933, add6562a15, 2b20c9c4be) — landed on trunk, not yet published to npm.

  • Homepage: a "Node graph, not a single stream" section. A new top-level homepage block argues why a graph of typed nodes beats a single message stream for complex agents: Send[] fan-out with per-slice state, deterministic merge through commutative reducers, a NamedBarrier fan-in, conditional-edge branching on state, and per-channel checkpoint fork at any past event. It distinguishes the three primitives — nodes (work), channels (typed state), edges (what fires next) — and notes the audit row is written per model call, not per node. A new single-stream-vs-graph diagram matches the existing 75vw diagram-block pattern. Links to Graph, Channels, Nodes, Time-travel, and Subagents. The copy notes the default agent graph spans dozens of typed nodes across the four stages, not a fixed handful.

  • Mermaid flowcharts now render as diagrams. Twelve mermaid fenced blocks across seven pages — including the Overview "mental model", Architecture, Turn lifecycle, Determinism, Family lock, Config manifest, and Replay — were authored as Mermaid but had no renderer, so each showed as bare text. The site now renders them as theme-aware diagrams via the fumadocs Mermaid integration. Mermaid is loaded only on pages that carry a diagram.

Changed

  • The governed-proxy comparison no longer treats "provider cost plus 5%" as the category's price floor. Concentrate launched 2026-06-10 on a $5M pre-seed with routing, cross-provider fallback, PII redaction, RBAC, SSO, and audit logs in a free tier at zero markup on tokens; it paywalls log retention, org- and model-level rate limits, and the contract instead. The section now names Concentrate alongside Merge Gateway and states the consequence: routing is not a priced surface in this category any more.

  • The proxy comparison's "Adoption cost" row was still written against greenfield only. The cell read "model your agent inside the runtime" — accurate before @pleach/observe shipped, stale after. It now reads ~15 LoC around the loop you already run, with the adapter graft as the step up. A new paragraph states what the brownfield SDK closes and what it doesn't: the audit row, yes; family-lock, replay, and checkpoints, no — those need the runtime to drive the loop.

  • Homepage and onboarding reweighted to lead with brownfield adoption; greenfield demoted. The homepage hero leads with the shipping brownfield graft (createPleachRuntime + setOrchestratorAdapterCtor from @pleach/core/runtime) and its primary call-to-action points to Adoption paths rather than the greenfield Getting started. The greenfield hero snippets are replaced by one muted line for a fresh build. The "three ways in" cards lead with shipped core-brownfield, and @pleach/observe is marked "days away on npm" everywhere it appears (it is 0.1.0-alpha.0, not yet published). Getting started and Quickstart gain a top callout routing existing-loop readers to the brownfield graft; the docs index and Which SKU cards lead with the brownfield entry.

  • Replay-determinism claims reconciled from "byte-identical" to "deterministic; divergence-detected." Determinism, Comparison, and Migrating from Anthropic Enterprise no longer claim a recorded turn re-generates a live model call byte-for-byte. Deterministic replay reproduces the recorded response, tool-call sequence, and terminal state, and names any drift with ReplayDivergenceError; a replay re-serves the recorded response, it does not re-run the provider. "Byte-identical" is kept only where it holds by construction — fold-based state hydration and deterministic channel reducers. Corrects a load-bearing over-claim; the property is reproducible control flow + attributable divergence, not byte-equality. Adds the serial-execution caveat to the replay claim: replay determinism holds only under serial graph execution (one node per superstep).

  • Two hand-drawn ASCII diagrams converted to Mermaid. The build pipeline on Supply-chain risk & SBOM and the reference architecture on Air-gapped architecture were box-drawing text; both now render as Mermaid diagrams. Node text is preserved verbatim — no claim change.

Fixed

  • Model-resolution matrix — Google's fast tier was stale. Model resolution matrix listed gemini-3-flash-preview for the Google converse and utility rungs; the live matrix resolves both to gemini-3.5-flash-lite.
  • Off-policy example term scrubbed from Prompts. Two gatedPrompt examples keyed on a "modal" tool; both now key on the neutral "sandbox" capability. Example-only — no API or claim change.
  • Swarm agent roadmap reconciled. The per-root-turn cost ceiling and the session-tree audit walker were marked future work; both ship (@pleach/gateway/swarm, @pleach/compliance/swarm). The roadmap wrongly placed the walker in @pleach/replay — it shipped in @pleach/compliance/swarm.
  • Nine stale "not shipped / future work" claims corrected against the upstream package source. A ~200-commit sweep of the @pleach/* packages surfaced load-bearing claims that asserted shipped features don't exist. Gateway — failover and region routing were called "v1.x work"; both ship as experimental subpaths. Compliance — "No broader scrubber set. Four scrubbers ship" corrected; PHI, Presidio, and LLM scrubbers plus a redaction pipeline ship under @pleach/compliance/redaction. Air-gapped deployment — "v2+ roadmap item" corrected; the runtime ships fail-closed airGapped enforcement plus an in-perimeter endpoint override. Sandbox — adapters ship inside @pleach/sandbox, not as separate @pleach/sandbox-<vendor> packages. Coding agent — the fictional four-tool block replaced with the eight shipped factories. Observe — "three publishable subpaths" corrected to six. Adoption paths — createBrownfieldRuntime ships, no longer "proposed."
  • Graph node catalog core registry corrected from 44 to 43. Two domain plugin nodes were listed as core and the core node syntheticExpansionDetector was missing; plugin nodes self-declare their stage and aren't part of the core registry.
  • Config manifest no longer overstates hash coverage. Only the plugin surface carries real content today; prompt/channel/filter builders return empty and node bodyHash is a placeholder. Manifest equality means "same plugin set," not "same substrate."
  • Two family-cascade diagrams used an invalid Mermaid arrow. The "no crossover to the other family" edge on Architecture and Family lock was written with an unparseable -.x link; corrected to -.-x (dotted line, cross head). The diagrams rendered as bare text before the Mermaid renderer landed, so the break was never visible. All Mermaid blocks on the site now parse.

Added

  • Comparison gains a category for agent-memory & knowledge-graph substrates (a read-side category). Generalizes the event-sourced-memory-graph shape — memory layers and knowledge-graph engines (Letta, Mem0, Zep) whose reader is the agent itself, not a human dashboard. The section pins the read-vs-write delineation: a memory substrate is a read substrate (the graph exists so the agent can query it to decide), @pleach/core is a write substrate (the ledger exists so every provider call is recorded, then read to account). Shared skeleton (append-only, content-addressed, causal chain, fork/replay); divergent object of record (the agent's knowledge/decisions vs. one provider call with model/tokens/cost). Framed as compose-not-compete — a memory graph reads the same session the AuditableCall row writes. Distinguishes this read-side from the observability read-side (reads for a human dashboard).

  • Homepage rebuilt as six diagram-paired blocks in a side-by-side layout. Every block — hero, "What you can do", "Should you stay", "Already paying the lab", "How it works", and "Quick answers" — now pairs left-aligned copy with one SQL-grounded diagram: a full AuditableCall record (SELECT *), the per-tenant GROUP BY rollup, a shape → tool decision flow, the contract-composes-underneath stack, the four-stage lattice, and a new append-only session_manifest event log with a fork-point checkpoint. Diagrams animate via CSS only, gated on prefers-reduced-motion, with gentle continuous pulsing on the load-bearing fields. Content width moved to ~75vw; the footer aligns to the same width.

  • Homepage gains a seventh block — "Keep your stack", the brownfield @pleach/observe path. A new top-level section between "Should you stay where you are?" and "Already paying the lab": a buyer already shipping on the Vercel AI SDK, LangChain, or a hand-rolled loop adds the audit row in ~15 lines, no rewrite. Its diagram (components/observe-brownfield-diagram.tsx) shows the existing loop on top, the init + per-turn recorder + destination-plug hook in the middle, and a fan-out to the four destinations you pick — postgres(), supabase(), otel(), memory() — over the BYOK code shape. Cross-links @pleach/observe, adoption paths, and BYOK observability. The ObserveRow-is-a-strict-subset-of-AuditableCall runway claim is the figure caption.

  • /investors — public-safe positioning page, footer-linked. A new top-level page states the fair-source thesis without numbers: the runtime is free and trust-protected, the hosted operational layer is the business, and the FSL conversion clock makes the openness contractual rather than revocable. Investment specifics route to getpleach@protonmail.com rather than living on the page. Linked from the footer only, between Pricing and Security — not in the top nav.

  • engine/ superstep scheduler named as an architecture piece + facets.mdx synced to the shipped facet inventory (pkgclean 06 D7/D9). Architecture and Concept clusters now name the engine/ scheduler (SuperstepRunner + its primitives) as the deterministic superstep executor that runs the compiled graph — previously determinism/scheduling was attributed only to "the graph". Facets gained the two shipped SessionRuntime accessors it omitted — runtime.observe (record(row)) and runtime.probes (emit / typed typed<K>) — plus the four per-stage graph introspection facets graph.anchor / graph.toolLoop / graph.synthesize / graph.postTurn.

  • @pleach/gateway/next documented as shipped (createGatewayRoute). Gateway → migration from core flipped from "roadmap / NOT shipped today" to shipped. The factory is a Web-standard (req) => Response POST handler wrapping GatewayClient; docs now carry the real opts shape (client | clientOptions + tenantId, optional transports / resolveRoute) and the { family, callClass, model, prompt, byokKey? } request body. The never-shipped { runtime, credentialStore, costEmitter } params were removed.

  • @pleach/coding-agent/context documented as shipped (createLruContextStrategy, createImportanceContextStrategy). Coding-agent → long session flipped from "(roadmap)" to shipped for the two pure ContextStrategy eviction factories. The fictional importance options (recencyWeight/frequencyWeight) were corrected to { maxEntries }, the additive ContextEntry.accessCount field documented, and the runtime-side CodingContextManager kept honestly labeled as roadmap.

  • @pleach/core/skills + @pleach/core/agents/types are real emitted subpaths. Skills updated to import SkillLoader, parseSkillFrontmatter, Skill, and SkillFrontmatter from the @pleach/core/skills barrel (no /loader, /parser, /types sub-subpaths); Agents prose corrected from "wildcard path" to a real emitted @pleach/core/agents/types subpath.

Changed

  • @pleach/core/internal/… subpaths retired from the public docs surface (pkgclean 06 D8). streamSingleTurn and Subpath exports no longer present @pleach/core/internal/strategies/streamSingleTurn/helpers (+ its four direct helper entries) or @pleach/core/internal/tools/execution/registryResolvedTools as stable, installable public imports — the internal/ segment marks implementation details, not a supported API. The removed copy-paste example that imported the streamSingleTurn helper barrel is replaced; the internal paths now live in a "Not a public import surface" section with their public alternatives: ToolDefinition from @pleach/core/types/generic, and @pleach/core/tools/execution for the resolved-tools registry functions. No package.json:exports change.

  • Homepage section order resequenced to a how-then-whether-then-where arc. "How it works" moves up ahead of "Should you stay where you are?" so the reader learns the structure before the qualification, and the new "Keep your stack" block lands between "Should you stay" and "Already paying the lab". Final order: hero → What you can do → How it works → Should you stay → Keep your stack → Already paying the lab → Quick answers. No copy on the moved blocks changed.

  • /pricing FSL-conversion explainer deduplicated to one canonical statement. The "fair source = source-available with delayed Apache-2.0 conversion" definition appeared four times (hero, License table row, "What FSL-1.1-Apache-2.0 lets you do" opener, "For procurement & legal"). It now reads once, canonically, in the hero; the table's License row keeps its tabular one-liner. No load-bearing claim changed — the pleach.fslConversionDate package.json pointer, the LICENSE link, and the permission rows are intact.

Fixed

  • Doc-fence drift campaign — 129 findings surfaced by the fixed audit:doc-snippet-typecheck gate; all doc TypeScript fences now compile against the shipped @pleach/* APIs. The gate now resolves @pleach/* against source (not a build-state-dependent dist/) and excludes syntax-broken fences that had been suppressing program-wide semantic analysis — the honest run exposed 129 usage-drift snippets. Corrections span: SessionRuntimeConfig capabilities → plugins — the invented flat safety:, systemPrompt:, routing:, context:, callClassFamilies:, transport:, and region: fields on new SessionRuntime({...}) removed; safety policies + system prompts now flow through definePleachPlugin(name, { safetyPolicies, prompts }), permittedFamilies / permittedRegions hoisted to their real top-level ReadonlySet config fields, userId / organizationId / tenantId hoisted out of the fictional context wrapper, and per-call-class family pinning reframed as the model-family matrix (family × callClass) rather than a session field (customer-support-agent, internal-knowledge-agent, regulated-domain-agent, region-pinned-agent, cloud-routed-agent); OrchestratorRegistry shape — langchain's setOrchestratorRegistry({ tools }) rewritten to the ergonomic definePleachPlugin contributeTools path; WithTenantHeaderOptions — withTenantHeader(fetch, { runtime, header }) corrected to { header, tenantId } (multi-tenant); plus earlier waves: AuditableCall nested payload paths, VersionHistoryEntry fields, ReplayTurnOutput / ReplayTurnInput / replay RuntimeConfig shapes, and VerifyResult narrowing.

  • Contract / plugin / audit-page accuracy sweep (F260–F331) — 31 doc/impl divergences corrected against packages/core + packages/compliance. event-log-projections: real folded event types restored per projection (configProjection → session.created; messageProjection → message.user / message.assistant / content.delta; toolCallProjection → tool.started / tool.completed / tool.failed; jobProjection states → pending | completed | failed | timeout); the fabricated sessionStateProjection export replaced with the real reconstructSessionState function; built-in count "six" → nine + composite; events.iterate / fold options corrected to { chatId?, fromSequenceNumber?, tenantId? }; HarnessEventReader → HarnessEventLogReader; the fabricated pre-filter selector replaced with the real post-fold finalize. audit-ledger: TamperEvidence → link / verifySequence / schemeId (sync); PIIRedactor → redact(record): AuditableCall + policyId; GDPRSoftDelete → single softDelete(...); AuditEmitter 5 → 10 methods. scrubbers: scrubbers do not declare event-type allowlists (global SCRUBBABLE_FIELDS); ScrubResult → { redacted, matchCount, matchedScrubberIds }; the three bundled scrubbers independently implements Scrubber; opt-out via [] / SCRUB_NONE_AUDITED. plugin-contract / authoring / stream-observers / plugin-authoring-standards: retired onSessionCreated / onToolCompleted / onMessageAdded removed (→ runtime.events); hook tally 65+5 → 67 contributeX + 7 top-level; not-contributed collectors 5 → 11; stream-observer verdict halt → stop; definePromptPlugin → definePromptsPlugin. hash-chain: prev_hash is the prior row_hash copied verbatim; created_at → sequence_number in the canonical field order. attestation: deleted the fabricated pleach.unsigned.v1 short-circuit paragraph. audit-gates: NODE_STAGE_MAP 43 → 44. tenant-facet: withTenantHeader({ header, tenantId }) (raw string at wrap time, header required with no default).

  • Reference-page accuracy sweep (F226–F295) — 34 doc/impl divergences corrected against packages/core. Error codes re-derived from src/errors/codes.ts (1002 TOOL_VALIDATION_FAILED, 1003 TOOL_EXECUTION_FAILED, 1004 TOOL_TIMEOUT, 2002 SESSION_CONFLICT, 2003 SESSION_EXPIRED, 2004 SESSION_LOCKED, 3001 SYNC_NETWORK_ERROR, 4003 STORAGE_QUOTA_EXCEEDED, 5001–5005 provider codes, 6002/6003 checkpoint codes); the fabricated "safety-refusal on code 5004" example rewritten to model-not-found (no safety-refusal code exists in the enum). Graph node catalog 43 → 44 nodes (added the answerSufficiency post-turn judge; post-turn 6 → 7) with corrected source-org file counts. Edge catalog: "three conditional routers" → two (shouldContinue + afterHallucination); recovery dispatch is a stream-filter collection, not a router. Model matrix + env-vars: mistral marked unrouted (excluded from EXPOSED_FAMILIES), GOOGLE_GENERATIVE_AI_API_KEY added as the primary Google var, and FEATURE_HARNESS_V2_RUNTIME / FEATURE_TOOL_CALL_RUNAWAY_HARD_BLOCK moved to a host-read section (core reads no FEATURE_*). Auditable-call row + typed records: version 18 → 19 (outcome.why); the fabricated payload.kind discriminated-union framing replaced with the real named optional slots narrowed on stageId (no payload.identity / payload.output.auditNote; principal is top-level; pluginPayloads[] is the extension slot); interrupt outcomes corrected to verdict: approved | edited | rejected | timeout. Glossary tenant facet fixed to the runtime.tenant.id / .subId properties (no getTenantId() methods). Subpath exports: SectionContributor → PromptContribution; capability list 38 → 35 (31 modern + 4 deprecated). Schema: 10 → 12 SQL files (added 000_supabase_compat.sql + 011_spawn_event_fields.sql) and the config manifest renumbered to 012_harness_config_manifest.sql. Removed the fabricated config_manifest_retention_days identifier.

  • Fictional @pleach/* identifiers in .mdx snippets corrected — surfaced by the audit:doc-import-resolution TS2724 pass. The React interrupt hook was documented as useInterrupt with a { pending, resolve, ignore } return and a resolve({ type, args }) HumanResponse-shaped payload — none of which exist. The real hook is useInterruptUI(config) (handler-driven: { activeInterrupts, renderActive, resolveInterrupt, cancelInterrupt }); it surfaces a PendingInterrupt (interrupt.toolCall.name / .arguments, not action_request / config.allow_* / description — those live on the separate HumanInterrupt envelope), and decisions are an ApprovalDecision ({ approved, note?, modifiedArguments? }). Rewrote both usages: interrupts now shows the useInterruptUI handler pattern, and platform recipes uses the imperative runtime.interrupts.resolve(id, decision) loop. Grouped with two other identifier corrections from the same TS2724 pass: the plugin-bundles page's definePromptsPlugin rename (was a fictional factory name), and the query page's tool-inspection + cross-session analytics signature fixes.

  • Behavioral / semantic prose drift corrected across the conceptual and recipe pages (findings 150–225), each verified against shipped @pleach/* source. Recipes: observableChatbot({ serviceName }) takes no subagent field — the row label is observeSubagent(serviceName), and the disable switch is serviceName: false (Pleach recipes); a second init(...) on @pleach/observe throws (singleton-per-process), it does not warn-and-return; and destination errors — sync throws and async rejections alike — are swallowed by default, surfacing them is opt-in via init({ throwOnDestinationError: true }) (BYOK observability, observable chatbot). Facets: graph.synthesize.getSeamIdentity() always returns undefined today; the sync.resolveConflict receipt has no conflictedPaths; runtime.interrupts exposes a manager property (not getInterruptManager) and runtime.timeTravel an api property (not getTimeTravelApi()) (facets). Graph / nodes: the compiled graph ships 44 node names / 7 post-turn nodes (adding answerSufficiency, D-NC-6), and a metadata-less node subscribes to every channel rather than inferring reads/writes from its body (graph, nodes). The reasoning seam is reserved/planned — the default runtime has no live consumer routing through it (seams). Interrupts: removed fabricated surfaces (plugin ctx.raiseInterrupt / ctx.tokenUsage, ApprovalDecisionKind with reason/riskLevel, and runtime.getInterruptScratchpad); InterruptConfig enables via interruptBefore / interruptAfter / interruptOn (not enabled/perToolApproval/globalApprovalThreshold); and resolving an interrupt consumes an ApprovalDecision — an approval-with-edit is { approved: true, modifiedArguments }, so an { type: "edit", args } payload leaves approved === undefined and reads as a rejection (interrupts). Query: usage rollups read ai_chat_messages (not harness_auditable_calls); getSessionReview throws QueryError("NOT_FOUND") so the never-throws guarantee is scoped, and the three codes are NOT_FOUND / DB_ERROR / INVALID_INPUT; queryHarnessEvents orders by created_at, cursors on a base64 created_at|id compound, and returns { events, nextCursor, count }; getEnrichedSessionReview gates on includeCitations / includeEntities / includeUsage; and the chat-keyed readers take a chatId, not a sessionId (a session id silently returns []) (query). Subagent provenance is delegated_from, not used_result_of (lineage). Host adapter / runtime: the module-loader probe sample uses an early-resolved key rather than the post-stream streamDegenerationGuards; metaToolNames is probed lazily on first read and setOrchestratorAdapter is a deprecated delegating stub; module loaders re-invoke every call (dedup is the process-wide import() cache, not per-runtime) (host adapter); HARNESS_MOCK_MODE is read only by the host-side MockToolExecutor (it synthesizes tool results; it does not classify seams or write AuditableCall/ledger rows — the default ledger is the no-op) (runtime construction); an absent providerFallback loader throws MODULE_NOT_FOUND rather than falling through a built-in chain (runtime strategies); and a custom streamSingleTurn body registers through the global module-loader seam, not a SessionRuntimeConfig strategy slot (stream single turn).

  • Method / field / type prose drift corrected across the migration and comparison pages (findings F107–F140). Usage-shape corrections (not import paths), each verified against the shipped @pleach/* source: ProviderFamily now lists all seven families including xai; provider-detection prose reframed to "six of the seven families (xai has no standalone env-var detection) plus openrouter"; the @pleach/transport-bedrock credentials note corrected to "static AWS keys or an STS session token today; container/role-assumption resolution is planned" (the BedrockCredentials shape requires accessKeyId + secretAccessKey). Method/field fixes: useHarness() returns isLoading, not isStreaming; the AgentProvider seam method is execute, not invokeStream; tool.started is a StreamEvent on the executeMessage() iterable, not a runtime.on(...) emitter event; session read is runtime.sessions.find(id) (returns Session | null) then session.state.messages, not runtime.getSession(id).messages; AuditableCall nests call.call.model + call.outcome.latencyMs; the ad-hoc runtime.audit.recordCall(meta, fn) wrapper rewritten to the shipped runtime.observe.record(row); the family + transport lock is applied at runtime.sessions.create({ provider, model }) (runtime.providerLock does not exist); @pleach/eval usage is new EvalSuite({ ... }).run(), not runEval({ suite, target }); the checkpoint rollback surface is runtime.checkpoints.rollback(sessionId, checkpointId) / .list() (not checkpointer.snapshot() / restore() or restoreCheckpoint(...)); the fabricated SubagentSpawnRecord type replaced with the real primitives (SpawnTreeState / parentTurnId / rootTurnCostCap, and the AuditableCall row's parent turnId where the claim is about a stored, GROUP BY-queryable rollup); and hash-chain verification (verifyChainForChat / generateProof) re-attributed to @pleach/core/eventLog, which @pleach/replay composes.

  • @pleach/* doc import paths corrected across 26 concept pages, surfaced by the now-fixed audit:doc-import-resolution gate. The gate had been resolving @pleach/* doc imports against dist/ — build-state-dependent, so an absent .d.ts silently typed the module as any and false-greened real drift. It now resolves against package source via tsc, which exposed 59 imports naming a symbol on a path where it does not ship. Most were root-vs-subpath drift, now pointed at the barrel that actually re-exports each symbol: StateGraphNodeMetadata / START / DefaultAgentState / buildDefaultAgentGraph / DEFAULT_TURN_FLAGS / AnnotationSchema / InferAnnotationState → @pleach/core/graph; CallClass / ProviderFamily → @pleach/core/modelfamily; ProviderMessage / ProviderToolDef (and the sibling provider types) → @pleach/core/providers; FabricationDetector / FabricationDetectorContext / FabricationFinding / SanitizerPass / FinalizationPassContext / PluginGraphNodeRegistration / PluginGraphNodeContext / composePlugin → @pleach/core/plugins; StreamObserverRegistration → @pleach/core/plugins/stream; Scrubber → @pleach/core/scrubbers; EventLogRow → @pleach/core/eventLog; MemoryProviderDecisionLedger → @pleach/core/audit; the guest-interrupt bus helpers (setGuestInterruptStore / publishInterruptRequest / popInterruptRequest / recordInterruptDecision / waitForInterruptDecision) → @pleach/core/guestInterruptBus; ToolDefinition → @pleach/core/types/generic; ConnectivityMonitor → @pleach/core/sync; and the BYOK gateway helpers (createCredentialRoutingMiddleware → @pleach/gateway root, createPostgresCredentialStore → @pleach/gateway/byok/adapters/postgres). Four snippets imported symbols that ship nowhere and were rewritten to the real API: @pleach/observe's startTurn() / turn.recordCall() → the shipped init + top-level recordCall(row) surface; the fabricated appRegistries.setProviderDecisionLedgerFactory(...) object → the free setProviderDecisionLedgerFactory({ fromSupabase }) accessor from @pleach/core/runtime; durableFlush.register(...) → setWaitUntilImpl(...) from @pleach/core/eventLog; and pickNextInFamily / deriveFamilyFromModelId (host-supplied — the harness ships no model registry) reframed as host functions handed in through the contributeFamilyPivot plugin hook. The registerIntentLabel() roadmap page now imports only the shipped definePleachPlugin and declares the proposed helper.

  • mcp / sandbox / coding-agent / replay doc pages reconciled with the shipped surface (devharness FINDING 94–103). MCP: registerSession(sessionId, runtime, { tenantId? }) is a live in-memory session registry (plus getSession / listSessions / unregisterSession) — no longer a NotImplementedError("D-PA-184") throw; resources/* and prompts/* are dispatched live on the MCPServer wire (both the SDK setRequestHandler path and the pluggable dispatchPluggableMethod); the pluggable dispatcher implements the initialize handshake (not -32601 Method not found); McpRuntime.registerCapability lands resource / prompt kinds in the last-wins ledger without throwing; the createSSETransport().start() factory throws a generic Error (the typed NotImplementedError("D-PA-181") is the options-bag server.start({ transport: "sse" }) path). Coding agent: the @pleach/sandbox peer-dep is ^0.1.0 (was ^1.0.0). Sandbox: there is no ctx.sandbox — the low-level SandboxProvider contract is execute / readFile / writeFile / listFiles, and @pleach/coding-agent exposes a thin SandboxClient facade (exec / readFile / writeFile, no list) the tool handlers close over. Region-pinned agent: createReplayRuntime takes sessionRuntime (not liveRuntime); replayTurn input is { chatId, tenantId, messageId } (not { turnId, mode }) and returns { chatId, tenantId, messageId, state, sequenceNumberRange } — there is no .diff field (the hash-chain verifyIntegrity verdict covers tamper-evidence, not parity).

  • observe / eval / replay / core concept-page snippets reconciled with the shipped signatures (devharness FINDING 83–93). Observe: getRecorder() returns ObserveRecorder and throws pre-init (never undefined); a second init throws (singleton-per-process); a throwing redactor is fail-closed (swallow + warn [Observe:redactor-threw] + drop the row, never write raw); the OTel envelope is span `<family>.<callClass>` + gen_ai.* / pleach.observe.* attrs (not pleach.audit.call); BUILT_IN_MATCHERS = email + phone + SSN (no credit card). Eval: cross-mode buckets are interactive/headless-eval/headless-replay (not production/replay/eval-noncached). Replay: eval-coupling is new EvalSuite({ suiteId, runtime }) + suite.setReplayClient(replay) (no replay ctor field; suiteId required). Determinism: ledger read is await ledger.getSession(sessionId) (not ledger.list({ sessionId })), and runtimeMode distinguishes five contracts (not three). OTel observability: executeMessage(sessionId, "hello") is positional. Stream events: re-read via runtime.sessions.resume(sessionId) (there is no sessions.get()).

  • More SKU doc-page snippets reconciled with the shipped signatures (devharness FINDING 80–82). Fabrication detection custom-detector example (no ctx.toolArgs; real FabricationFinding = {detectorId, severity, reason, evidence?}, no suspect/tier); Multi-tenant getAggregateUsage is 3-positional (client, store, filters), no groupBy:"tenantId", dates under dateRange, requires userId; Determinism fingerprint round-trip reads fingerprintComposite (string), not .fingerprint. The ctor-shape/call-arity/ field-name classes the audit:doc-import-resolution gate doesn't cover.

  • Event-log read side documented as store-agnostic — eventReader / HarnessEventReader. Event-log projections claimed runtime.events.iterate / .fold read harness_event_log rows and went live "on the Supabase backend in PA-1 Phase A.2" — store-specific language corrected to the shipped surface: both accessors delegate to a HarnessEventReader you inject as eventReader (read-side counterpart to eventLogWriter), backing the same iterate/fold/resume surface with Postgres, Supabase, SQLite/pglite, or an HTTP API. iterate gains tenantId; the reader is required (no implicit store fallback). New Backing the reader section shows the one-method contract. Session runtime config table gains eventLogWriter + eventReader; Storage grows the ci:devharness-sql battery from four durable properties to nine.

  • SKU doc pages reconciled with the shipped import/construction surface (devharness FINDING 76–79). Building a chat UI fabricated a @pleach/react chat-hook API (useChat/HarnessProvider from root, useInterruptDecision, useChatVercelCompat, sendMessage) → corrected to the real surface. LangChain: LangChainProvider positional ctor + top-level provider: slot. Base tools: scratchpad is per-session, param operation, string value. Coding agent: sandbox tools register via a contributeTools plugin (no tools/context config field). Import-path half regression-locked by docImportSurface.smoke.test.mjs.

  • Observability + gateway-cost docs corrected to the shipped surface (devharness FINDING 73–75). @pleach/core ships no @opentelemetry/* dep + never reads the global tracer provider — the NodeSDK/OTLP recipe captured zero pleach spans; OTel observability + Observability now show the real new SessionRuntime({ otelExporter }) bridge path (default NoopOtelExporter drops spans), and runtime.spans.snapshot() returns {inFlightCount,isShutdown} (use CapturingOtelExporter.captured for emitted spans). Gateway cost events: computeCost read fields absent from RouteChatCompletionOutput (asTenantId(undefined) threw → zero CostEvents) — corrected to real output fields + host context, with a slice-2-stub note.

  • Subagents + async-tasks docs reconciled with the host-completion-required reality (devharness FINDING 66–72). Bare @pleach/core's subagent surface is host-completion-required; the docs over-promised a substrate-delivered one. Subagents: dropped the fabricated spawnsSubagent flag; LightweightRuntime → LightweightSessionRuntime from @pleach/core/subagents with its real ctor; fetchWorkspaceContext/formatWorkspaceContextPrompt moved to the subpath; concurrency corrected (hard SUBAGENT_LIMITS cap, fail-not-queue on the runtime path; SubagentManager queue/DAG is host-driven); context.variables inert; host-completion caveat added. Async tasks: the tool-loop async bridge is not wired in bare core (ASYNC_TASK_BRIDGE_NOT_WIRED), and the task executors are host/plugin-supplied, not "in-tree defaults".

  • Abort + resume docs synced to the shipped runtime behavior (devharness FINDING 56 + 62). Aborting a turn now records outcome.status: "user-aborted" (not "aborted" / not provider-error) at both the decision call and the synthesis terminal — corrected across session lifecycle, SessionRuntime, turn lifecycle, API routes. And resuming a session now describes the real three-layer rebuild (storage row → version-guarded checkpoint overlay → server-only event-log hydration of ephemeral card state onto a transient Session.hydratedHarnessState), correcting the prior "hydrateFromEvents rebuilds messages" claim.

  • Model-resolution-matrix path corrected — it is host-supplied, not a @pleach/core dir (pkgclean 06 D7). The docs cited the family-lock matrix at the fictional src/graph/modelfamily/ (family-lock) and @pleach/core/ai/modelFamily/matrix.ts (quickstart, provider detection) — neither path exists in the package (there is no ai/ or graph/modelfamily/ dir). The (family × callClass) matrix table is host-supplied and reached through the AgentAdapter.resolveModel<C>() seam; the ProviderFamily set is now pointed at the real @pleach/core/modelfamily export. The routing-decision seam's Ivy-internal host path was also removed from routing decisions.

  • Docs reconciled with the shipped @pleach/core runtime (value-prop-vs-impl audit, devharness FINDING 56–64). Corrected doc claims that diverged from the implementation across Time travel (fork sets parent_id: source.id), Checkpointing (message/event-boundary checkpoints discriminated by CheckpointMetadata.source, no per-stage stageId; SupabaseSaver "replicated"; rollback source: "manual"; string fork arg), Session lifecycle (checkpoint snapshot authoritative; event-log canonical reader is a flag-gated shadow), Sync (interactive conflict resolution / sync.conflict / 3xxx codes are enterprise-tier/planned; open-core is SyncCoordinator last-writer-wins-on-push), Query (dropped non-existent queryAuditableCalls; fixed getChatUsage / lookupModelCost / getSessionReview / getInterruptChain sigs+shapes), Memory (graph-node extraction path is production, not the memoryExtractionHook → queue pipeline; LearnedFact.source string+object), and Lineage (opt-in via config.lineageTracker; runtime records the node + branched_from fork edge, other relations host-recorded; completeSession host-called).

Added

  • Landscape — new page. Twenty agent-runtime capabilities ranked by how differentiated @pleach/core actually is, in three tiers: structural to the audit row, assembled here from parts the market sells separately, and table stakes. Each capability names its mechanism and where the rest of the field lands, graded against the observability / cost / eval / durable-execution cohort (Helicone, Langfuse, LangSmith, Portkey, LiteLLM, OpenMeter, MLflow, Logfire, Braintrust, LangGraph, Temporal, Inngest, the OpenTelemetry GenAI conventions). States plainly where the substrate is structural (hash-chained AuditableCall row, deterministic replay + family-lock, subagent spend rolled to the turn) and where it is commodity (per-tenant cost, checkpointing, PII redaction). Linked into the sidebar after Comparison.

  • Family-locked routing gains a "Why the lock matters: provenance" section. Frames the value around audit provenance, not operational breakage: when the model that answers changes (transient failover, or a migration over a release cycle), the ledger has to record which provider and model ran, and when it changed. In-family-only fallback (fallbackStep with inFamily: true) plus an explicit sessions.updateProviderModel re-lock (session-lock-resynced event) keep the provider / transport on every AuditableCall row trustworthy — provenance for an auditor, not a UI label or a local dev-tool file.

  • Homepage value-prop tiles reordered to lead with the differentiated capabilities. Leads with deterministic replay, family-lock, subagent-cost rollup, and the hash-chained row; demotes the commodity per-tenant-cost framing and drops the niche sync-conflict tile. The family-lock tile reframes around model provenance — proving which provider and model produced each answer after a failover or migration. Links the new Landscape page.

  • Comparison gains a read-side cohort table. Adds an "Observability, cost, and eval tools" section covering Helicone, Langfuse, LangSmith, LiteLLM, MLflow, Logfire, Braintrust, and OpenMeter — the tools a team shops against for "audit, cost, replay" and which the prior matrix omitted. Draws the write-side-substrate vs read-side-store boundary, marks where each lands data (their store vs your DB), and states the compose pattern (Pleach writes the row; the read tools stay good at reading).

  • Agent instrumentation recipe — new recipe page for the do-it-yourself instrumentation path. Subscribe to the runtime lifecycle with runtime.events.on(kind, handler) over model.called plus the stage.* / turn.* / recovery.fired / retry.attempted / stream.* kinds, then bridge model.called to a destination with observeSink({ destinations }) in one line. model.called now fires for both the main agentic turn and each synthesize / reasoning / utility seam call — seam-call rows carry real costUSD from per-1M-token rates, main-turn rows carry a 0 sentinel (cost derived downstream from llm.turn token counts). Distinct from observable-chatbot (recipe wrapper) and BYOK observability (no-@pleach/core brownfield path). Registered in meta.json and the llms.txt Recipe-walkthroughs group.

  • "Live lifecycle events" on observable-chatbot — links the chatbot recipe to the bare-subscription instrumentation path and shows bot.runtime.events.on("model.called", ...) off the recipe's runtime escape hatch.

  • CI enforcement of the audit contract — new Reference page indexing the audit-gate catalog by the auditability and replayability clause each gate enforces. Pairs every clause with its named gate and the condition that turns it red — audit:auditable-call and audit:auditable-call-soak for the row shape and DB wire-format, audit:event-log-manifest-hash-completeness plus the three audit:config-manifest-* gates for substrate reconstruction, audit:c8-event-type-allowlist-coverage for scrubber coverage, audit:c9-hash-chain-integrity and audit:eval-phase-a-coverage for replay. Names the graphnoderef, local-clone, and per-SKU consumer-rehearsal CI jobs. Cross-linked from Audit gates.

  • Contribution namespaces — new page documenting the nine namespaces every HarnessPlugin contribution hook resolves to (prompts, stream, safety, audit, intent, tools, middleware, policy, lifecycle) as the canonical, audit-gated contract layout, with representative hooks per namespace and the rolling-out typed namespaced authoring form (plugin.stream.contributeX, additive alongside the flat form). Cross-linked from Plugin contract.

  • Config manifest — new page documenting the content-addressable substrate snapshot the runtime writes to harness_config_manifest: one row per distinct plugin/prompt/node/channel/filter set, keyed by a SHA-256 Merkle roll-up (pleach.manifest.v1 prefix, 0x1F separator, mirroring the hash chain's pleach.c9.v1 canonicalization). Covers the five per-surface child hashes, the nullable manifest_hash foreign reference on harness_event_log, reference-counted retention (default forever, tenant-overridable floor), full-snapshot storage, and the replay-by-config, cross-tenant-by-plugin-set, and substrate-reconstruction query shapes. Marked in-flight — table and event-log column land as additive schema files during rollout.

  • What Pleach writes to your database — new page mapping every table the runtime and its plugins write, what's on by default versus opt-in, and what each row carries. Leads with the destination-is-yours posture: no phone-home; writes land in your Postgres / Supabase / OTel collector / Memory buffer.

  • manifest_hash cross-references added to Event log (stamping section + EventLogRow field) and Schema (rolling-out harness_config_manifest section).

  • MCP Server Card (SEP-1649) at /.well-known/mcp/server-card.json and a backing JSON-RPC endpoint at /api/mcp. The card declares streamable-http transport (MCP protocol 2025-06-18) pointing at /api/mcp and enumerates two read-only docs tools — search_docs (full-text over the docs corpus) and get_doc_markdown (markdown twin of any docs page by slug). The endpoint handles initialize, tools/list, tools/call, resources/list, ping, and the notifications/* no-ops; tools/call for search_docs runs the same createFromSource(source) engine that backs /api/search, and get_doc_markdown resolves through source.getPage() against the same processed body the agent-skills index digests. Advertised via rel="mcp-server-card" in the Link headers on / and /docs/:path*, in the <link rel> mirror in the root layout, and under service-meta in the RFC 9727 /api-catalog linkset.

  • WebMCP browser provider mounted from the root layout. Calls navigator.modelContext.provideContext({ tools }) (with a fallback to per-tool registerTool for older Chrome origin-trial builds) to expose the same two tools — search_docs, get_doc_markdown — to AI agents embedded in the browser. Silent no-op on browsers without the API. Tool shapes are identical to the HTTP MCP surface, so an agent reaches the same operations whether it dials in over /api/mcp or rides inside a browser tab.

  • Agent Skills Discovery index at /.well-known/agent-skills/index.json. Follows Cloudflare's RFC v0.2.0 shape. Every docs page is exposed as a documentation-type skill whose url points at the per-page markdown twin (/llms.mdx/docs/<slug>/content.md) and whose sha256 digests the same processed body that URL serves. A changed digest is the signal a page has been re-authored; agents can verify ingestion against it byte-for-byte. The index iterates source.getPages() so any new docs page joins automatically. Advertised via rel="agent-skills" in the Link headers on / and /docs/:path*, in the <link rel> mirror in the root layout, and under service-meta in the RFC 9727 /api-catalog linkset.

    An isitagentready.com audit also flagged OAuth metadata, /auth.md, MCP Server Card (SEP-1649), WebMCP, and DNS-AID. The MCP Server Card and WebMCP additions above resolve two of those flags; the remainder still don't apply — this site has no protected APIs and no agent-registration surface, so OAuth metadata and /auth.md would advertise endpoints that don't exist. The existing crawl surface — sitemap, llms.txt, llms-full.txt, per-page .md twins via Accept: text/markdown, robots.txt, ai.txt, /api-catalog (RFC 9727), and RFC 8288 Link headers — is what an agent actually needs to crawl the docs effectively.

  • Node catalog and Edge catalog reference pages, slotted into the Architecture sidebar after Channels. Node catalog enumerates the 43-name registry the audit:graph-stages script accepts, grouped by lattice stage with the acceptsSeam literal and a per-node gated column (always vs. config.<field> — the executor or hook the host must supply for the node to wire). Edge catalog enumerates the nine allowed cross-stage edge patterns plus the seven forbidden ones verbatim, then documents the four static chains (pre-LLM, enrich-route, post-tool, terminal), the two conditional routers (post-LLM four-arm, post-hallucination two-arm), and the four post-turn recovery stream filters (refusalHintFilter 100, retryNarrationFilter 200, garbleRecoveryFilter 300, standardRecoveryFilter 400) with per-arm target tables.

  • DX sections in Node catalog and Edge catalog documenting the three extension paths external developers can use. Node catalog adds an "Adding or removing nodes" matrix covering config omission (drop a gated executor, the chain composes around the absent node via .filter(hasNode)), the plugin path (HarnessPlugin.extraGraphNodes() with the substrate's registration constraints), and the custom-builder path (a raw StateGraph for full topology control under the lattice gate). Edge catalog adds a parallel matrix plus the asymmetric removal story: a synthesize → tool-loop edge cannot be re-added through any extension path, and removing an allowed pattern requires upstream contribution to topology.ts. Both pages keep the upstream-contributor checklist as a separate section so the two audiences don't collide.

  • Ownership boundaries page, slotted into the Get Started sidebar after Which SKU do I need?. Single-page map of where each SKU's locked surface ends and host code begins. Three columns per SKU: Owned by the SKU (locked, upstream-contribution-only), You configure (typed config field, plugin hook, or registry), You must supply (required at construction). Covers every shipping @pleach/* SKU. Names the two structural pins that hold across every SKU — the four-stage lattice and the AuditableCall row shape — and the cross-SKU concerns where ownership spans packages (audit ledger, cost rollup, storage, determinism). Closes with a "Quick lookup — I want to change X" table mapping 20 common host-side change requests to their surface and path. Fills the gap between Which SKU do I need? (task → install list) and Plugin contract (full extension API).

  • DX additions to six existing pages after a corpus-wide audit of where extension guidance was missing or weak. The audit scanned 177 MDX files; the pass rate was high (the site was already DX-aware on most surfaces). Six rows landed: (1) The AuditableCall row gains a locked-contract callout naming the three extension slots (tenantId, payload.identity, payload.output.auditNote) and pointing the rest at upstream contribution; (2) Fabrication detection gains an "Adding a custom detector" section with a worked contributeFabricationDetectors example plus the three detector rules (sync detect, side-effect-free, tier-determines-routing); (3) Event log gains an "Authoring a custom projection" section against the verified GraphProjection<T> interface plus the three contract rules (pure, order-preserving, total); (4) Observability gains an "Extending observability — plugin hooks" section surfacing contributeStreamObservers and contributeFinalizationPasses; (5) @pleach/mcp gains a "Registering custom capabilities" section honest about what works today (McpToolRegistration) versus what throws (McpResourceRegistration + McpPromptRegistration are shape-stable but body-deferred until Phase B second slice); (6) Audit gates gains a "Mirroring gates in your own repo" section citing the audit:plugin-contract-completeness script shape as a small reference for host-side invariant gates. Every hook name in every example was verified against the upstream source before landing — no fabricated APIs.

Fixed

  • AuditableCall row AuditRecordVersion corrected 13 → 14 — both the literal description and the version-log range (v8 through v14) now match the upstream AUDIT_RECORD_VERSION_HISTORY, whose latest entry is to: 14 (Cluster C: additive rewriteStatus? + tokenCost.callClass).

  • Dead link /docs/plugins-and-extensions corrected to Plugin contract on Install.

  • Docs home "Three paths" header corrected — it preceded four cards; the count was dropped.

  • Schema codeRepository + sameAs corrected across seven SKUs in the site's Organization + SoftwareApplication JSON-LD @graph. @pleach/base-tools, @pleach/observe, @pleach/compliance, @pleach/compliance-contract, @pleach/gateway, @pleach/mcp, and @pleach/recipes each declared https://github.com/pleachhq as their canonical repository — a leftover from when the SKU schemas were drafted against an upstream monorepo. Both codeRepository and sameAs now point at https://github.com/pleachhq/<sku>, matching the canonical pattern set by @pleach/core, @pleach/tools, @pleach/eval, @pleach/replay, @pleach/sandbox, @pleach/coding-agent, and @pleach/react. Load-bearing because sameAs is the field AI search engines (ChatGPT, Perplexity, Gemini, AI Overviews) use for entity reconciliation across the npm ↔ GitHub ↔ docs boundary; the wrong URL was being served to every crawler on every page request via the JSON-LD @graph inlined in the docs root layout.

  • Schema codeRepository + GitHub sameAs entry added to @pleach/langchain. The langchain SKU's SoftwareApplication block was the only entry in the JSON-LD graph without a codeRepository field, and its sameAs array referenced only the npm page and the docs page (not the GitHub repo). Now declares https://github.com/pleachhq/langchain consistent with the other SKUs.

  • Pleaching metaphor branches list corrected across four surfaces. The prior framing named the four stages (intent / tool pick / refusal / answer) as the branches woven into the lattice, but stages are sequential phases of one turn — not parallel branches the metaphor needs. The glossary already had the right framing, matching the upstream @pleach/core README: branches are the addressable events (each LLM call, tool dispatch, subagent spawn) — each one writes a row to the ledger. The bad list had been introduced during the lift-and-rewrite from the upstream metaphor passage and replicated to the homepage hero, the docs index, the overview, and the audit ledger page. All four now align with the glossary and the upstream README, and a closing line on the homepage and docs index/overview names the four stages as the trellis and the audit row as the weave so the metaphor's load-bearing parts each have a job. No change to the glossary, the upstream README, or replay (which uses branch generically and was already metaphor-safe).

Removed

  • Company attribution and private references stripped from shipped copy. A company name, private repository links, a private filesystem path, and internal tracker links were removed from the homepage and docs; a few domain-specific example terms in prose were genericized.

  • Internal planning citations removed across the docs. Decision, pack, slice, and open-question IDs that meant nothing to an outside reader were stripped, each annotated claim left intact. Live runtime symbols a consumer sees — the PACK_* constants and the literal NotImplementedError("D-PA-181") / ("D-PA-184") payloads — were retained.

  • Homepage Four Properties section deleted, plus the duplicate hero "From those three" paragraph. The Four Properties grid (cost / audit / compliance / legibility) restated the same primitive — tenantId / turnId / tokenUsage rolled up via GROUP BY — that the What you can do with it section two blocks above already covered, with different labels. The hero paragraph "From those three: per-tenant cost in a GROUP BY, compliance review in SQL…" restated the load-bearing fact the previous paragraph (session / turn / row) had just landed. Both cuts follow a verbosity audit of every public non-docs page; the deletions shorten the homepage by ~120 lines without losing a load-bearing claim — scrubber names and the four-stage shape are still documented at Compliance and Architecture, which the deleted pillars linked to anyway. The Agent shapes CTA the deleted section carried is rewired into the Should you stay where you are? section, folded into the existing shape-enumeration paragraph so it lands where a reader is already asking the what-shape-am-I question.

Changed

  • @pleach/observe repositioned from shipping to alpha across the site. Packages, the docs home, and Which SKU had listed it at 0.1.0 · npm; @pleach/observe is 0.1.0-alpha.0 — scoped, not yet on npm. Install recommendations now tag it (alpha).

  • Package-count framing corrected to 14 published. @pleach/compliance-contract joins the first-wave list; @pleach/observe (alpha) and @pleach/trust-pack (reserved) move out of the shipping set.

  • Homepage @pleach/coding-agent version aligned to 0.1.0 — it had shown 0.2.0-alpha.0, contradicting the first-wave cut on Packages.

  • Which SKU persona section rewritten to named archetypes. Internal persona codes became plain audience shapes.

  • What's new — June 2026 reframed as reader-facing release notes — reorganized by package; slice numbers, commit SHAs, and persona codes removed.

  • Graph lattice docs synced to the current @pleach/core topology across eight pages. Corrected three load-bearing claims that shipped against an older substrate. The NODE_STAGE_MAP registry is 43 names, not 48. ALLOWED_EDGE_PATTERNS carries nine rows and FORBIDDEN_EDGE_PATTERNS seven, not eight/eight — the tool-loop → post-turn recovery-dispatch edge moved from the forbidden table into the allowed table. Recovery shaping is no longer four synthesize-stage graph nodes (recovery, refusalHint, retryNarration, garbleRecovery) plus a recoveryDispatchPredicate derivation node and a shouldContinueWithGarbleRoute wrapper; it is four post-turn stream filters (refusalHintFilter 100, retryNarrationFilter 200, garbleRecoveryFilter 300, standardRecoveryFilter 400) dispatched via StreamObserverRegistry and locked by audit:recovery-dispatch-single-surface. synthesize is now a true singleton — only synthesizer. Touched Graph, Node catalog, Edge catalog, Nodes, Architecture, Ownership boundaries, and Plugin contract; Audit gates gains graph + config-manifest gate rows. Node catalog also gains a "How the substrate source is organized" section — the src/graph/ layout (nodes/ one-file-per-node, wiring/ registrars split by stage, the topology.ts lattice layer, concern-split seams/ / predicates/ / strategies/) — and its upstream-contributor steps now point at the wiring/register<Stage>Nodes.ts registrar rather than the thin defaultAgentGraph.ts orchestrator.

  • Config manifest foreign key corrected in Config manifest. The page claimed the harness_event_log.manifest_hash reference was gate-enforced "rather than a database foreign key." It is a real foreign key with ON DELETE SET NULL and a load-bearing DEFERRABLE INITIALLY DEFERRED clause — deferring to commit time lets the fire-and-forget manifest write race the first event-log write within one transaction without a transient FK violation. Added the missing reference_count column to the table DDL and cited the audit:config-manifest-fk-constraint-applied and audit:config-manifest-referential-integrity gates.

  • Authoring a HarnessPlugin informal "12 buckets" reframed as the scan view of the canonical nine namespaces. The at-a-glance hook grouping now points at Contribution namespaces as the canonical, audit-gated contract layout. Hooks and counts unchanged; the framing reconciles the two pages so the site carries one canonical taxonomy.

  • Graph structural pin corrected from a fixed "32 nodes / 70 edges" count to a config-honest framing. The old prose claimed the canonical graph "compiles to 32 nodes and 70 edges" and that the audit asserts that count is byte-identical PR-to-PR. The numbers were correct for a specific compile config but misleading as a general claim: the NODE_STAGE_MAP registry in topology.ts carries 43 names, and the actual compiled count depends on which executors and hooks the host supplies to buildDefaultAgentGraph(config). The corrected prose names the 43-name registry as the upper bound, names the audit:graph-stages byte-identity guarantee as per-config not absolute, and links to the two new catalogs (Node catalog, Edge catalog) as the enumerated references.

  • Schema @pleach/core description amended to name the language-agnostic contract. The description field in the Organization + SoftwareApplication JSON-LD graph previously described @pleach/core only in TypeScript terms, contradicting both the marketing surface (which states the wire contract is language-agnostic with an independent Go implementation) and the editorial position at /ai.txt. The description now names the wire shapes — HTTP+SSE, StreamEvent, AuditableCall, Checkpoint, version vector — as language-agnostic and clarifies that the npm package is the TypeScript reference distribution. programmingLanguage: ["TypeScript"] stays accurate — the npm package IS TypeScript; the language-agnosticism belongs to the contract, not the publishable artifact. See Language-agnostic contract for the full wire-shape inventory.

  • /llms.txt per-page markdown advice tightened from .mdx to .md. The closing ## Machine-readable surface block in the curated AI index previously instructed agents to construct URLs like https://getpleach.com/llms.mdx/docs/<slug>.mdx, hitting the underlying route handler directly. The site's markdown-negotiation proxy supports the more idiomatic https://getpleach.com/docs/<slug>.md form, which is the pattern most AI crawlers actually look for. The instruction now recommends the proxied form and notes it's equivalent to requesting the same URL with Accept: text/markdown.

  • Pricing page export-bridge prose tightened, "What we sell on top" restructured. The export-bridge paragraph collapsed from four sentences with dual "If your team / If you don't" framing to two sentences carrying the same destination list (Postgres, Supabase, OTel collector, custom) and the same bridge-vs-destination framing. The "What we sell on top" paragraph — a 70-word run-on with three nested parentheticals (Hosted Gateway, Hosted Observe at enterprise scope, marketplace bundles) — became a three-item bulleted list, one SKU per line. Same audit pass as the homepage cut above.

Added

  • Agent-discovery surface extended to deep-link landings and body-only fetchers. Three reach extensions to the existing RFC 8288 Link: header + robots.txt + /llms.txt + /ai.txt + /.well-known/api-catalog stack — none of them corrections, each one closes a gap where a non-default crawler shape misses the discovery surface.
    • The docs root layout mirrors the homepage Link: headers as <link rel> elements in <head> on every page, so agents that read rendered HTML body but never see response headers (cached archive fetchers, lightweight AI ingestors) discover api-catalog, service-doc, alternate → /llms.txt, describedby → /ai.txt, sitemap, and author the same way they would from the header.
    • The site's Next.js header config extends the same Link: headers (with Vary: Accept) to every /docs/* URL. Agents arriving at a deep-link citation in an AI answer now get the same discovery hints — api-catalog, service-doc, ai.txt, sitemap, author — without traversing back to /. The home-only /llms.txt alternate is omitted from this path because the per-page markdown twin is the same URL with .md appended, served via the markdown-negotiation proxy; advertising /llms.txt would falsely imply that's the markdown twin of the current page.
    • The sitemap generator emits a .md twin entry for every docs page at priority 0.4 (below the 0.7 HTML form, so search engines prefer the human-facing URL for ranking). Sitemap-only crawlers — some AI ingestors don't follow Accept: text/markdown content negotiation — now discover the machine-readable surface from the sitemap alone.
  • Pleaching metaphor surfaces on the homepage hero and docs index. The horticultural framing the runtime takes its name from previously lived only in the brand motif component and the glossary's P section. The homepage hero and the docs index now carry a single voice-tightened paragraph between the lede and the payoff — pot-and-stakes for ai-sdk/LangChain, lattice for Pleach, branches for intent / tool pick / refusal / answer. Lifted and rewritten from the metaphor passage in the upstream @pleach/core README; the docs-index version cross-links the canonical glossary entry. One flourish per page per voice rules; mechanism still leads, metaphor follows. Three concept pages pick up a single sub-metaphor each: Comparison carries the pot-and-stakes-vs-lattice contrast right under the lede; Audit ledger adds "the lattice carrying weight — every branch lands in a row at the same grain" after the stage walkthrough; @pleach/replay adds "walking the rows in order is walking the lattice" under the determinism claim. Skipped determinism.mdx, concept-clusters.mdx, checkpointing.mdx, and API references — too instrumental for the flourish to earn its weight.
  • Fumadocs UI surface broadened — the docs MDX registry now carries Steps/Step, Accordion/Accordions, TypeTable, File/Files/Folder, Banner, ImageZoom, InlineTOC, DynamicCodeBlock, and GithubInfo alongside the existing defaults. Card/Cards and Callout were already in the fumadocs defaults; the new registrations unlock the rest across every page without further wiring.
  • Three first-party enterprise-shape components — StatusBadge (8 semantic statuses: stable, beta, preview, alpha, deprecated, reserved, pre-1.0, in-flight), VersionPill (monospace pkg@version pill with optional href), and Kbd (themed keyboard-shortcut display). Pure-SSR React, theme-aware via text-fd-* tokens, no client JS. /docs/replay adopts <StatusBadge status="in-flight">Phase A + Phase B</StatusBadge> under its Status heading as the reference adoption.
  • <TypeTable> on reference pages — /docs/auditable-call-row converts all five sub-shape tables (Identity, Principal, Call, Decision, Outcome) into <TypeTable> blocks. /docs/stream-events and /docs/env-vars each convert one representative table as the pattern reference for follow-up work.
  • <Accordions> on the FAQ Capabilities cluster — the 9-question "Capabilities" section of /docs/faq now renders as a single <Accordions> with each Q an <Accordion> carrying an explicit id for deep-link stability. The main FAQ above stays as ##-headed prose; the FAQPage JSON-LD graph is unaffected.
  • <Steps> on the migration pages — /docs/migrating-from-ai-sdk and /docs/migrating-from-langchain wrap their six step sections in <Steps>/<Step>. The auto-numbered left-rail track replaces the ## Step N — prefix in each heading, so H2 anchor IDs are now content-only (#convert-your-tools instead of #step-2-convert-your-tools). No inbound links pointed at the old anchors.
  • <Callout type="info"> on migration scoping blocks — the "You don't need this migration if" pre-flight bullets and the "Costs that don't go away" sections in both migration pages now render as info callouts.

Changed

  • /docs/replay error hierarchy diagram — the ASCII tree rendering ReplayError / ReplayDivergenceError / ReplayCacheMissError / ReplayUnknownEventError / NotImplementedError is now a mermaid classDiagram with inheritance arrows and per-class fields. Matches the established mermaid idiom used on /docs/overview, /docs/architecture, /docs/determinism, /docs/family-lock, and /docs/turn-lifecycle.

  • Four SKU placement pages — /docs/sandbox, /docs/transport-bedrock, /docs/transport-azure-openai, and /docs/transport-vertex. Each page is a thin orientation: what the SKU is for, where it slots in the substrate, which contract page it implements, and a pointer to the package's npm README as the canonical source for constructor signature and option shape. Authored to retire four audit failures for SKUs already on SKU_PUBLISHED. The repo's audit:docs-vs-contract script now reports 0 missing pages.

  • /docs/recipes jump-link table — 10-row index inserted after the lead so a reader scanning for one recipe doesn't sift through ~1,000 lines. Each row names the recipe's central primitive (@pleach/react + createPleachRoute, ProviderDecisionLedger, etc.) in 3–8 words.

  • HowTo schema on /docs/adoption-paths — 5-step JSON-LD mirroring the brownfield→greenfield progression. Improves AI-search citability on a load-bearing discovery page.

  • FAQPage schema on /docs/comparison — 11 Q/A entries across the four comparison clusters (TS LLM libraries, durable-execution platforms, agent harnesses, Enterprise contracts). Each Q matches a question shape a reader would type into ChatGPT or Perplexity; each A is the load-bearing fact from the page.

  • ---Transport providers--- sidebar group below Bundled packages, listing transport-azure-openai, transport-bedrock, and transport-vertex. sandbox slots into Bundled packages after base-tools.

Changed

  • /docs/session-runtime — facets-first restructure. The facets inventory (runtime.sessions, runtime.events, runtime.sync, runtime.dev) now appears directly after Strategy injection. The flat method surface relocated under a new Flat method surface (legacy) H2 with a one-line banner forward-pointing to facets. Readers previously learned the deprecated path first; the new order matches the deprecation contract the page already states.
  • /docs/adoption-paths — brownfield→greenfield framing promoted. What used to be a page-bottom section is now a callout directly after the two-paths comparison table, so decision-makers see the upgrade path before they pick a lane. Hook sentence: "Every choice you make on the SDK destination travels with you when you adopt the full runtime."
  • Sidebar group rename: Use cases → Agent patterns. Same six pages (customer-support-agent … regulated-domain-agent) — the prior name read as features, the new name reads as patterns. Operations stays as a single group; cosmetic clustering wouldn't help scanning.
  • /docs/recipes lead — count flipped Nine → Ten and the inline name list extended to include the regulated-host end-to-end recipe.

Fixed

  • /docs/plugin-authoring-standards — ghost hook reference. A code example referenced a non-existent contribute-prefixed spelling of the pre-plan primer hook; the real hook is prePlanPrimer (no contribute prefix — lifecycle hooks like prePlanPrimer, postSynthesisGuard, onJobDispatch carry no prefix; the contribute prefix is reserved for contribution-slot hooks). Caught by the in-repo audit:docs-vs-contract script — first F-11 drift hit since the SKU coverage check landed. Audit now reports 0 novel ghosts.

Added

  • Rank-2 per-recipe deep-dive pages — four additional pages under /docs/recipes/ covering the recipes excluded from the prior six because their peer SKUs were outside the first-publish wave: observableChatbot (composes @pleach/observe), instrumentedCodingAgent (composes @pleach/coding-agent + @pleach/sandbox + @pleach/observe), enterpriseAgent (composes @pleach/compliance + @pleach/observe, surfaces the procurement-visible ENTERPRISE_PERMITTED_FAMILIES_TAG envelope a gateway-aware host reads), and evalLab (composes @pleach/eval
    • @pleach/replay via DI-callback factories so the recipe doesn't take hard build-time peer deps). The four are rank-2-publish-relevant once eval, mcp, sandbox, and coding-agent ship per the upstream rank-2 runbook. Each page mirrors the prior six-page convention — best fit, quickstart, runtime composition, TypeScript config interface, common gotchas, cross-links. Sidebar registration in [the docs meta.json] adds the four pages immediately after the prior six under Bundled packages.
  • Per-recipe deep-dive pages under /docs/recipes/ — six new pages covering the first-publish wave (@pleach/core, @pleach/tools, @pleach/compliance, @pleach/gateway) and the brownfield observability SDK: simpleChatbot, ragChatbot, compliantChatbot, verticalAgent, subagentSwarm, and BYOK observability. Each carries a quickstart, the runtime composition the recipe wires, a TypeScript config interface, common gotchas, and cross-links. Recipes composing SKUs outside the first-publish wave (observableChatbot, instrumentedCodingAgent, enterpriseAgent, evalLab) are not yet covered and will land when those SKUs ship.
  • /robots.txt — emits Content-Signal: search=yes, ai-train=yes, ai-input=yes per the contentsignals.org draft. The signal mirrors the editorial position already on /ai.txt — crawling, indexing, retrieval, and training are all permitted.
  • Homepage Link: response header — the / response now ships RFC 8288 Link: advertising /.well-known/api-catalog (rel="api-catalog"), /docs (rel="service-doc"), /llms.txt (rel="alternate"; type="text/markdown" — the markdown twin of / under content negotiation), /ai.txt (rel="describedby"), /sitemap.xml (rel="sitemap"), and the maintainer inbox (rel="author"). / also gets Vary: Accept so a CDN can't cross-contaminate the HTML and markdown responses. Agents can find the discovery surface without parsing HTML.
  • /.well-known/api-catalog — RFC 9727 catalog returned as application/linkset+json (RFC 9264). Two anchors: the site root and /api/search (the docs search endpoint).

Changed

  • Markdown-for-Agents on the homepage — / with Accept: text/markdown now rewrites to /llms.txt (which uses fumadocs's q-value-aware isMarkdownPreferred to choose text/markdown over text/plain and ships Vary: Accept). Per-page markdown under /docs/* is unchanged.

  • /pricing — Two surfaces. One runtime. closing paragraphs refine to drop claims cohort research contradicted, without committing to hypothesis-grade tier prices still gated by buyer-outreach. Specifically: compliance attestation drops as a standalone enterprise surface and folds inside Hosted Observe at enterprise scope (nobody sells "cryptographic audit chain" as a standalone procurement category — Vanta / Drata / Credo AI all sell per-framework + per-headcount); Hosted Gateway description rewrites to per-tenant subscription pricing with optional consolidated billing, drops any percentage-on-routed-spend framing (100% of disclosed-pricing LLM router cohort runs zero markup on inference — Vercel + OpenRouter have done buyer education); the bridge paragraph expands to acknowledge the self-serve segment where Pleach becomes the destination (no existing observability stack to bridge to). New closing paragraph names self-serve tiers as in development without committing to specific prices.

  • /faq and /docs/faq — Is there a hosted version? answer rewrites the hosted product list: compliance attestation folds inside Hosted Observe Enterprise (no separate SKU); Hosted Gateway names per-tenant subscription pricing and "no markup on inference"; self-serve tiers named as in development.

  • /pricing — What stays free, and what doesn't rewritten as Two surfaces. One runtime. with a side-by-side comparison table (substrate vs hosted) across 11 dimensions: license, phone-home, license check, account-to-run, retro-paywall, self-host, SSO/SAML/SCIM, SLA, retention, SOC 2, pricing. The table makes the trust-vs-revenue boundary structurally instead of by meta-commentary. Two short closing paragraphs add: (a) audit rows ship where you point them — Postgres, Supabase, OTel collector into Datadog / Honeycomb / Grafana / your existing OTLP backend, or a custom destination; the enterprise integration is the bridge from @pleach/observe into the review surface your team already runs, not "adopt another dashboard"; (b) what we sell on top: Hosted Gateway, compliance attestation services, Hosted Observe at enterprise scope, AWS/Azure/GCP marketplace bundles. The prior absolutist lines — self-hosting the equivalent stays on the table at every release and no procurement-style enterprise tier today — drop because they foreclosed the only viable revenue stream.

  • / — homepage hero closer rewrites the no procurement-style enterprise tier line in favor of hosted products on the runtime are first-class enterprise products. Trust commitment intact; revenue posture honest.

  • /faq and /docs/faq — Is there a hosted version? answer rewrites under the two-surface frame. Hosted Gateway, Hosted Observe at enterprise scope, and compliance attestation services name themselves as enterprise products with per-seat pricing, SSO/SAML/SCIM, retention SLAs, and SOC 2 wrappers. Runtime trust commitments intact.

Added

  • @pleach/observe — new top-level page for the brownfield audit-row SDK. Documents the five-entry facade surface (init, startTurn, flush, recordCall, subagent, getRecorder), the ObserveRow shape as a strict subset of the AuditableCall v7 schema, the four destinations (Postgres, Supabase, OTel, Memory) on the ./destinations subpath, the custom-destination interface (write + optional flush), the hookable-vs-not-hookable split against the runtime, and composition with @pleach/core when both surfaces run in the same process. Phase 0 status callout makes the design-target stance explicit — @pleach/observe@0.1.0-alpha.0 is scoped, not yet on npm; Phase 1 publish is the next cut. Slotted into the Bundled packages cluster after @pleach/gateway.

  • Adoption paths — new top-level orientation page making the brownfield-vs-greenfield decision first-class. Leads with a side-by-side capability table (audit row, family-locked routing, replay determinism, channels, checkpoint/restore, migration cost), then "pick brownfield when" and "pick greenfield when" sections with concrete code shapes for each, then the monotonic brownfield-to-greenfield composition story (runtime detects SDK init, startTurn becomes a no-op inside a runtime-managed turn, shared fingerprint compute, no double-recording), then "pick neither when" — single-shot RAG, provider-dashboard-is-enough, prototyping-and-changing- weekly. Slots in at the top of the Compose & migrate cluster as the orientation page the per-stack migrating-from-* walkthroughs (AI SDK, LangChain, Anthropic Enterprise, OpenAI Enterprise) sit downstream of.

  • Packages — added the @pleach/observe matrix row in the Reserved tier with the row note 0.0.1 · Reserved · 0.1.0-alpha.0 scoped, and reworked the Reserved bullet in the intro narrative to distinguish @pleach/trust-pack (placeholder, no contract published) from @pleach/observe (Phase 0 contract locked, scoped for Phase 1 under FSL-1.1-Apache-2.0).

  • Sidebar — added observe under Bundled packages after @pleach/gateway, and Adoption paths at the top of Compose & migrate ahead of the migrating-from-* pages.

  • Attestation — new top-level page on the Ed25519-signed envelope substrate that sits on top of the hash chain and turns a row-slice into third-party-verifiable evidence. Documents the @pleach/core/attestation subpath (signer, verifier, key-store interface), the two stub production adapters (AWS KMS, Vault Transit), and the file-backed attestation/testing adapter. Frames the boundary against policy and rotation, which stay in @pleach/compliance or host-side. Slotted into the Tamper evidence cluster directly after Hash chain.

  • Audit gates — new top-level page cataloging the CI- and PR-time invariant checks in scripts/audit/ — package-shape, plugin-contract, tool- coverage, event-log integrity, runtime soak ledgers, and cross-repo reservations. Documents the :strict / :json / :list / :update-baseline suffix convention and the soak-ledger generalization. Slotted into the Reference cluster after Subpath exports.

  • Project layout — new top-level page giving the orientation that previously had to be reconstructed from the use-case and recipe pages. Leads with the three things the runtime actually requires (a SessionRuntime per process, a chosen ProviderDecisionLedger, a host adapter if HTTP is in play); shows one working Next.js-shaped layout with each piece cross-linked to its canonical docs page; descends into the six use-case shapes (customer support, research, coding, internal knowledge, multi-tenant SaaS, regulated domain) via a <Cards> block; points at the three filesystem-touching recipes (Next.js streaming, SQLite storage adapter, custom event-log projection); and closes with the deliberate non-choices (no pleach.config.ts, no reserved .pleach/ dir, no agents/ folder convention — the agents/<specName>/ prefix in Agents is a channel-path string, not a directory). Slots into a new Project layout sidebar cluster between Getting started and Agent shapes. Voice-aligned to the library-not-framework stance: describe, don't prescribe.

  • Sidebar — added the Project layout cluster. The cluster has room for siblings (deployment-shape layouts, multi-tenant layouts) without a future re-org.

  • Per-use-case Project layout sections appended to all six use-case pages — Customer support, Research, Coding agent, Internal knowledge, Multi-tenant SaaS, Regulated domain. Each shows the same baseline tree from Project layout with the shape-specific delta inlined (split tools by integration; subagents directory; sandbox boundary + durable checkpointer; index + ingestion split; per-request runtime factory; compliance/ wiring the three audit plug-points). Section is inserted before the existing Where to go next block so the descent from Project layout lands, deepens, and exits through each page's existing cards. Voice-aligned: each entry names the failure mode the structural choice fixes, not a generic benefit.

Changed

  • Cross-docs status-flip pass — rolling correction across ~55 docs pages tracking the alpha-ship of @pleach/compliance, @pleach/gateway, and @pleach/replay. Claims that previously read "planned" or "no shipping code yet" now name the actual alpha (@pleach/compliance@0.8.0-alpha.0 four-scrubber bundle; @pleach/gateway@0.8.0-alpha.0 Phase A with Anthropic transport real and other transports deferred to Phase B; @pleach/replay@0.7.0 hash-chain verifier shipping verifyChainForChat / generateProof, with writer-side stamping in @pleach/core/eventLog behind c9PhaseBEnabled). Touched pages include Audit ledger, Compliance, Gateway, Replay, Hash chain, Eval and replay, Event log, Event-log projections, Subpath exports, Seams, Prompts, Prompt builder, Session runtime, Recipes, and the rest of the Trust + integrity, Providers, and Reference clusters. Each edit is a load-bearing claim correction, not voice tightening — readers who saw the prior pages learned that pieces "weren't shipping" that now are, and the changelog entry exists so they can re-orient.
  • Project layout — corrected the multi-tenant card description. Originally read "One runtime per process serves many tenants"; the use-case page actually builds the runtime per request via a buildTenantRuntime(req) factory. Updated to match — the cards descent must not misrepresent the page it lands on.
  • CLI — substantial rewrite. The page previously described pleach init as a SQL-bundle scaffolder with --target / --dry-run / --apply / --timestamped flags. That surface still exists but is now pleach schema; pleach init is an interactive wizard that scaffolds a starter project (route, page, optional plugin stub, optional schema copy) for the detected framework. The old form pleach init --apply is routed to schema for back-compat (existing scripts keep working). Cited against the upstream scripts/harness-init.mjs already pinned in the page's <SourceMeta>. The rewrite is a correction to a load-bearing claim — readers who saw the old page learned that the binary "does one thing", which is no longer true.

Added

  • CLI — pleach init wizard — the four-question flow (template, provider, plugin stub, schema scaffold), the flag table (--template, --yes, --cwd), the framework-detection matrix (8 framework values), the package-manager detection (bun / pnpm / yarn / npm), the provider env-var matrix (anthropic / openai / openrouter / google with the four env-var names), the template-to-files matrix per framework, idempotence behavior (skip-not- overwrite), CI mode behavior (--yes and non-TTY auto-yes), exit codes (0 / 1), and a verbatim worked-example transcript of the wizard running in a Next.js App Router project.
  • CLI — pleach schema — the former init flag table, now under its true subcommand name. Adds honest exit codes (0 / 2 / 3) that the previous page omitted: schema bundle missing exits 2, overwrite refusal exits 3.
  • CLI — Project layout after the wizard — matches the per-use-case layout sections added in the prior pass. Shows the baseline Next.js layout with the four wizard-written paths inlined (app/api/chat/route.ts, app/page.tsx, pleach.plugin.ts, supabase/migrations/*pleach*.sql). Closes the loop between the CLI page and the project-layout cluster.
  • Subpath exports → @pleach/core/quickstart — added under the Wire + tooling cluster. Labeled experimental (matches upstream module status). Lists the five LANDED deliverables — createPleachRoute (fetch-handler factory), useChat (Pleach-native React hook), <ChatBox /> (unstyled, accessible), defaultPlugin (empty baseline), providerDetection helpers + constants — plus the benchmark- adjacent createBenchmarkPlugin. Closes the gap flagged in the prior cli.mdx pass.
  • Getting started → The quickstart subpath — new section after the existing Shortest-path quickstart — createPleachRuntime. Five-export table with shapes and jobs; zero-config + with- options createPleachRoute examples; two failure-mode behaviors (HTTP 503 on missing provider env var, Pleach-native vs Vercel-AI-SDK event taxonomy); useChat / <ChatBox /> composition example; createBenchmarkPlugin paragraph; a three-row "which factory do I reach for?" matrix differentiating createPleachRuntime (substrate), createPleachRoute (HTTP), and the bare SessionRuntime constructor (custom transport / multi-tenant). Voice-aligned: failure modes named at mechanism, not vibes.

Changed

  • CLI — wizard-section cross-links retargeted from Shortest-path quickstart (a related but different surface) to The quickstart subpath (the actual subpath the wizard scaffolds against). Also added a paragraph noting the wizard's 4-provider list is narrower than the runtime's 7-provider detection — a missed provider in the prompt does NOT mean the deployed handler will miss it, only that the wizard's default-selection logic doesn't know to highlight it.
  • Getting started → Scaffold a new project — the second instance of the stale pleach init claim that CLI's rewrite corrected last pass. The section previously said pleach init "scaffolds a minimal example agent plus the schema-bundle SQL migrations"; it now describes the four-question interactive wizard and cross-links to CLI → pleach init for the framework matrix and walkthrough.

Fixed

  • Resolved the Known gap entry from the previous Unreleased pass: @pleach/core/quickstart is now listed in Subpath exports and documented in Getting started, with cross-links from CLI. The wizard's emitted code (createPleachRoute, ChatBox, defaultPlugin) is no longer symbol-without-a-home.

Changed

  • Pricing — the What will and won't ever cost money section rewrites to What stays free, and what doesn't. Drops the absolutist One paid product, ever and No enterprise tier. No hosted-only features. framings; replaces with the net-additive + FSL-irrevocability commitment the license posture already provides for free. New phrasing: any paid surface is net-additive and can't gate a feature already in a published release; the FSL conversion clock guarantees that for FSL releases and Apache releases are irrevocably Apache on their published tag. Keeps the load-bearing Self-host means self-host row. Adds an explicit No procurement-style enterprise tier today qualifier that scopes what the brand commitment actually means (no contact-sales, no SSO behind paywall over substrate features, no per-seat upsells layered onto runtime functionality). The rewrite is a correction to a load-bearing claim — readers who saw the old page learned that no enterprise tier · one paid product, ever was a permanent commitment, which it is not.
  • Homepage hero — closing line No enterprise tier, no hosted-only features. → No procurement-style enterprise tier; paid surfaces won't gate runtime features. Aligns the headline-scale claim with the Pricing revision.
  • FAQ → Is there a hosted version? — answer rewrites to lead with No today, name the gateway as the planned multi-tenant routing SKU, and close with the FSL-conversion-clock mechanism behind the net-additive guarantee.
  • /ai.txt — single-word fix: open-source agent-runtime → fair-source agent-runtime. Restores the labeling-discipline qualifier the rest of the site already carries.

Added

  • Security → Deployment shape — new section after Scope. Scopes the self-host means self-host promise to what the runtime actually does today; names air-gapped operation, on-prem provider endpoints, and sub-tenant routing at scale as roadmap items with typed options today + runtime guards later. Points procurement teams at the canonical inbox for current state. Closes the gap between the pricing-page commitment and what the runtime literally does today for regulated buyers.

2026-06-08 — canonical contact collapsed to a single inbox

Changed

  • Canonical contact is now getpleach@protonmail.com. The previous split — admin@getpleach.com for general inquiries and security@getpleach.com for disclosures — is retired. Both roles now route to the single ProtonMail inbox; the Security page and the security-disclosures channel on Community include a ?subject=Security%20disclosure mailto hint so the inbox can still triage the two flows. Reflected on the homepage Organization JSON-LD, Security, Privacy, Terms, License, Pricing, Community, FAQ, the docs FAQ, the contributing guide, the blog RSS feed, and /ai.txt.

2026-06-08 — chat-pipeline lift into @pleach/core + audit:domain-string-purity Pre-Merge Gate

Added

  • OrchestratorClient — new top-level page documenting OrchestratorClient, the per-turn handle the runtime threads through the stream body. Lifted from app-side into the substrate; canonical import path is @pleach/core/runtime/orchestratorClient. Page covers the six user-facing facets (config, history, context, tools, model, prompts), the _internal.graph snapshot consumer code must not touch, where a host receives the client (inside a custom strategy, inside a plugin hook, inside a custom turn body), and the imperative-vs-graph coexistence model. Slots into the "Build an agent" sidebar group between SessionRuntime and Providers. Pairs with the audit:orchestrator-facet-coverage CI gate already documented at Facets.
  • streamSingleTurn — new top-level page documenting streamSingleTurn, the canonical per-turn body. Lifted into @pleach/core/strategies/streamSingleTurn/ with a stable helpers barrel that re-exports TurnAccumulator, ToolDefinition, OrchestratorMessage, and ProviderFallbackConfig. Page documents what the body consumes (the typed strategy slots — hallucinationDetectorFactory, continuationMetaToolNames, repetitionGuard, orchestrator.providers.providerFallback, EMPTY_SINGLE_TURN_FLAGS), what it never sees (the five forbidden literal categories the domain-string purity gate enforces), and how a host wires a custom body when the linear-turn default doesn't fit. Slots into the "Plugins & strategies" sidebar group after Runtime strategies.
  • Subpath exports — adds two rows to the Runtime + composition table: @pleach/core/runtime/orchestratorClient and @pleach/core/strategies/streamSingleTurn. Both are now named subpath exports rather than wildcard-only reachable.
  • Architecture § Boundary rules — adds a sixth row to the gate table: audit:domain-string-purity forbids domain-specific literals in packages/core/src/** across five pattern families (host vocabulary, vendor backend names, sandbox tool prefixes, identity discriminators, domain phrasing; ~50 patterns; baseline-gated :strict mode). Closes the rationale section with a fourth load-bearing-invariant sentence: the gate makes plugins the only legitimate channel for consumer-specific content. Pairs with the existing lint:harness-boundary row, which forbids domain imports — the new gate covers domain strings.
  • Language-agnostic contract § How the contract stays honest — promotes the three honest-keeping mechanisms (shared fixtures, cross-runtime replay, schema gate) to four by adding the domain-string purity gate. Frames the gate as a falsification mechanism: a TS-side string leak the Go runtime would otherwise have to mirror fails CI instead of becoming a wire-shape obligation.

Why now

The Pre-Merge Gate substrate landed upstream — the audit script, the five-family blocklist, the baseline, and the npm script variants are all live. The docs side previously only enumerated lint:harness-boundary (the import-side companion); the string-side gate is a structural guarantee the docs now name alongside it.

Added

  • Platform & operations recipes — extracts four platform-team recipes from Recipes (long-running async jobs, multi-step interrupts, per-call cost reporter, OpenTelemetry wiring) into a dedicated page under the Operations sidebar group. Lets a consumer reader on /docs/recipes skip patterns a platform team owns; lets a platform reader land directly on the four ops recipes without scrolling past chat/storage/BYOK.
  • Runtime strategies — extracts the ~140-line Strategy injection section from SessionRuntime (representative slots table, fabricationGuardStrategy bundle, newer injection hooks including hallucinationDetectorFactory, continuationMetaToolNames, the repetitionGuard extensions, the orchestrator.providers.providerFallback registry-seam, and EMPTY_SINGLE_TURN_FLAGS). Lands under a new Plugins & strategies sidebar group alongside Plugin contract. Frees the runtime page to read as a clean construction + lifecycle + executeMessage reference.
  • Related shapes blocks on every use-case page. Customer support, Research, Coding, Internal knowledge, Multi-tenant SaaS, and Regulated-domain agents each open with a three-bullet pointer at sibling use-case pages a reader on this one is likely to also need (e.g., "Regulated-domain agent if the SaaS serves a regulated vertical"). Fixes the brittle cross-page navigation — a reader on Customer support whose actual case is closer to Research now sees the pointer in the lead.

Changed

  • Examples reframed and renamed to Reference apps. The duplicated Agent shapes and Recipes hub sections (word-for-word repeats of Agent shapes and Recipes cards) are dropped; the page is now focused on the two runnable examples that ship inside the @pleach/core npm package (minimal-agent, host-adapter). Slug change updates the URL from /docs/examples to /docs/reference-apps; inbound links on Getting started, @pleach/base-tools, and the prior changelog entry are repointed.
  • Sidebar reorder in the Start group: Getting started → Agent shapes → Recipes → Reference apps → Comparison. Brings the "which shape is mine" pattern lookup ahead of the catalog of wiring recipes — a reader matches their problem first, then opens the recipe that fits, then reads reference-apps only when they want a runnable starting skeleton.
  • Facets reordered so the inventory tables on SessionRuntime and OrchestratorClient lead the page, with the (now tightened) Why facets, not flat methods rationale moved to the section after. Drops the 28-line philosophical lead that buried what's actually on the runtime; rationale prose shrank from ~32 lines to ~18 while keeping the human + agent discoverability angle.
  • Prompt builder reordered so The composer signature leads directly after the lead paragraph and SourceMeta. The prior When you call it preamble (16 lines of "you usually don't") moved after the signature and tightened to a 9-line When you call it directly section. A reader who arrives wanting the API shape now sees the API shape first.
  • Recipes lead rewritten to reflect the consumer-facing split (chat, tools, storage, BYOK, moderation, multi-tenant, compliance, projections, hash chain) and to point at Platform & operations recipes for the platform-team patterns. Recipes 10–13 (multi-tenant, compliance, projection, hash-chain) renumbered to 6–9; anchor URLs for those four sections shift accordingly. No inbound docs links referenced the old #10/#11/#12/#13 anchors.
  • SessionRuntime shrunk from 472 lines to ~330. The Strategy injection section is now a one-paragraph framing + pointer at Runtime strategies; everything else (construction, SessionRuntimeConfig field table, sessions, executeMessage, abort, deletion, lifecycle methods, stream subscription, accessors, lifecycle events, facets, cacheBackend) stays.

2026-06-08 — docs de-dup + DX-ordered sidebar

Changed

2026-06-08 — sidebar + homepage label consistency

Changed

  • Homepage — renamed Four pillars section heading to Four properties. The intro paragraph already self-describes as "four properties"; the H2 now matches the body. Drops the architectural-pillars connotation that misframed the section: Cost / Audit / Compliance / Legibility are properties that fall out of the row primitive, not foundational supports.
  • Sidebar — split the Substrate group into Execution graph (graph, nodes, channels) and Routing (seams, call-classes, family-lock, model-resolution-matrix). Brings the sidebar group names into agreement with the cluster anchors the child pages point at — the execution-graph cluster on architecture, the routing cluster on family-lock. No URLs change; only the separator labels.

2026-06-08 — concept-map closeout (three more triplets + map page)

Completes the cluster-framing pattern across all sidebar groups where a clean triplet exists, and adds a dedicated concept-map landing page. Brings the total to seven cluster triplets at four depths: substrate-wide (session/turn/row) plus six cluster-level (execution-graph, routing, audit-ledger, composing-agents, runtime-lifecycle, state-and-persistence).

Added

  • Composing-agents cluster (Skill + Subagent + Agent profile). New section on Agents. Sibling openers added to Subagents and Skills.
  • Runtime-lifecycle cluster (Session lifecycle + Turn lifecycle + Event log). New section on Session lifecycle. Sibling openers added to Turn lifecycle and Event log.
  • State-and-persistence cluster (Storage adapter + Checkpoint
  • New Concept clusters landing page walking all seven cluster triplets as a navigable concept map. Opens with the substrate-wide triplet (session/turn/row), then the six cluster-level triplets in execution order. Closes with an explicit note on what lives outside the cluster pattern.
  • Sidebar entry for the new page in meta.json under "Architecture & comparison".
  • Footer extended with an Architecture link between Docs and FAQ, so readers landing on a marketing subpage have a second- level docs hook.

Changed

  • Docs index — dropped How the three concepts fit together section (now redundant with the cluster pattern propagating in the deep-dive pages) and added a one-line pointer to Concept clusters immediately after the substrate-wide triplet.
  • Docs index "Read next" cards trimmed from six to five: dropped Session lifecycle and Recipes; added Concept clusters as the new map entry.

2026-06-08 — cluster-framing pass (three triplets)

Extends the slow-ramp pattern from session/turn/row down through three more concept clusters, one layer in from the homepage. Each cluster lives on a host page that walks the three concepts in parallel-bulleted voice; the sibling concept pages each open with a one-paragraph cluster pointer that names the triplet and deep-links the host.

Added

  • Execution-graph cluster (graph + node + channel). New The execution-graph cluster section on Architecture between the TL;DR six-piece map and 1. Stage lattice, walking Graph, Node, Channel as the per-turn execution substrate that runs inside the lattice. Sibling-page openers added to Graph, Nodes, and Channels, each pointing at the new architecture anchor.
  • Routing cluster (CallClass + Seam + family-lock). New The routing cluster section on Family-locked routing, walking CallClass, Seam, and family-lock as the cluster that decides which model fires for which kind of call. Sibling-page openers added to Call classes and Seams. Reference-page pointers added to Providers (transport layer) and Model resolution matrix (the reference table), each naming the triplet and deep-linking the cluster framing.
  • Audit-ledger cluster (row + ProviderDecisionLedger + hash chain). New The audit-ledger cluster section on Audit ledger before the existing ProviderDecisionLedger deep-dive, walking the three concepts as a triplet so the row, the write interface, and the tamper-evidence layer each get one parallel bullet before the deep dive lands. Sibling-page openers added to The AuditableCall row and Tamper-evident hash chain.

Why

The slow-ramp pattern landed on the homepage + docs index for the foundational triplet (session/turn/row). Three more triplets sit one click in: execution-graph (inside a turn), routing (inside a stage), audit-ledger (after the call). Each gets the same parallel-bulleted treatment so a reader walking from the homepage into the docs hits the same shape at every depth.

2026-06-08 — slow-ramp entry-point pass

Added

  • Homepage hero: new substrate-framing paragraph between the H1 and the existing benefit paragraph. Defines Pleach as "a runtime substrate for LLM agents — the backbone an agent harness builds on, usable standalone or as the runtime layer underneath a product's agent loop" and names the three concepts inline (session, turn, row keyed by turnId). The existing benefit claims now read as the consequence of the three concepts, not the lead.
  • Homepage new section "Three concepts the substrate hangs on" between the hero and "What you can do with it," with three Pillar cards — Session, Turn, AuditableCall row — each carrying a definition and a deep-link to SessionRuntime, Turn lifecycle, and The AuditableCall row.
  • Docs index: opening rewritten to lead with "Pleach is a runtime substrate for LLM agents…", followed by a new "The three concepts" section walking session → turn → row, and a "How the three concepts fit together" section that retains the runtime + contract + ledger triangle framing. The existing "The shape, in one paragraph" remains as the next layer down.

Why

The initial entry point now opens high-level — what is a runtime substrate, what does it sit underneath, what are the three foundational primitives — before the load-bearing benefit claims land. The dense framing didn't disappear; it now reads as the consequence of the three concepts rather than the cold-open.

2026-06-08 — discovery + entry-point depth pass

Added

  • /llms.txt — lead paragraph appended with one sentence on Enterprise composition; "Migrating from other frameworks" group renamed to "Migrating & composing under enterprise contracts" with the two enterprise migration slugs added to the head so AI search retrievers see them first.
  • Homepage JSON-LD SoftwareApplication.description extended with the Enterprise composition clause for knowledge-graph entity extractors (Google AI Overviews, Gemini).
  • Root metadata.description in app/layout.tsx extended so every non-home page inherits the signal for OG / Twitter.
  • /ai.txt — new "High-signal entry points for enterprise readers" section naming both migration docs and Language-agnostic contract.
  • Overview — paragraph after the per-turn cost rollup SQL example naming tenantId as opaque (customer vs cost-center) and pointing to both migration docs.
  • Architecture §5 Audit ledger — paragraph after the identity-tuple claim connecting it to per-axis attribution inside one Workspace or Project.
  • Getting started — Enterprise callout after the server quick-start naming AnthropicSdkProvider and the AI SDK's OpenAI provider as the composition entry points.
  • FAQ — new entry "Does Pleach replace my Anthropic or OpenAI Enterprise contract?" before "Who's behind this?"
  • Core "What you get" — new bullet "Composes under an existing Enterprise contract" after the AuditableCall ledger bullet.

Changed

  • Sidebar separator Migrate & coexist renamed to Compose & migrate so the Enterprise composition story isn't mis-sold as a migration away from the lab.
  • Agent shapes Multi-tenant SaaS card blurb widened from "per-customer invoice" to "per-axis rollup (end-customer invoice, or employee / team / cost-center chargeback inside one Anthropic Workspace or OpenAI Project)." (Originally on /docs/examples; that page was reframed as Reference apps on 2026-06-08, with the agent-shapes cards moved to their canonical home on /docs/agent-shapes.)
  • Pleach + OpenAI SDK and Comparison — "per-customer monthly rollup" graduation claim widened to per-axis (per end customer in a SaaS, or per employee / team / cost-center under one Workspace or Project).
  • Homepage Enterprise section — two SKU paragraphs collapsed into one tighter paragraph naming both @pleach/coding-agent and the language-agnostic contract; load-bearing sentence "answers 'is this TypeScript-only?' before Enterprise IT asks" preserved verbatim.

2026-06-08 — sibling-SKU references

Added

  • Homepage Enterprise section — two new paragraphs after the cloud-mediated transports note. First paragraph names @pleach/coding-agent (typed CodingAgentRuntime contract at 0.2.0-alpha.0) as the sandboxed coding-agent surface for the internal dev-tools team that often sits inside the same Enterprise contract footprint — same row, same tenantId axis, same chargeback. Second paragraph names the language-agnostic contract (wire shapes: HTTP+SSE, StreamEvent, AuditableCall, checkpoint envelope, version vector) and the Go round-trip as the procurement-visible answer to "is this TypeScript-only?"
  • Migrating from Anthropic Enterprise and Migrating from OpenAI Enterprise — new "Sibling SKUs that ride alongside the contract" section before "Where to go next" on each migration doc, with one bullet for @pleach/coding-agent (Workspace or Project framing per doc) and one for the language-agnostic contract + Go round-trip.
  • Comparison Enterprise section — paragraph appended after the cloud-mediated transports note, mirroring the homepage's coding-agent + language-agnostic-contract framing for the doc-side reader.

2026-06-08 — re-settling pass

Added

  • Marketing surface. New CostRow body on Pricing for "LLM provider tokens" naming Anthropic Enterprise and OpenAI Enterprise composition, and the per-axis tenantId framing.
  • Marketing FAQ. New entry "Does this replace my Anthropic or OpenAI Enterprise contract?" on the FAQ page.
  • Docs adjacency. Enterprise-contract bridge paragraphs added to Pleach + Anthropic SDK and Pleach + OpenAI SDK, each pointing readers who graduated from a self-serve key to the right migration doc.
  • tenantId opacity paragraphs added to Multi-tenant deployments and The AuditableCall row, plus a GatewayClient-per-cost-center note on Gateway.

Changed

  • Sidebar reorder. The "Migrate & coexist" group now opens with the two enterprise migration docs (Migrating from Anthropic Enterprise, Migrating from OpenAI Enterprise) above Migrating from the AI SDK and Migrating from LangChain.
  • Agent shapes shape 04 renamed from "Per-customer cost attribution" to "Per-axis cost attribution" with body, team-shape, and sharpest-vertical lines rewritten to cover the internal-Enterprise case alongside SaaS. Anchor URL is now #04--per-axis-cost-attribution; the prior anchor was unreferenced elsewhere on the site.
  • Multi-tenant SaaS agent three-places list widened to four, naming the internal- Enterprise composition case.
  • Marketing FAQ "Who is this for?" answer on FAQ widened to name internal platform teams attributing employee, team, or cost-center spend under one Workspace or Project.
  • Homepage tightening. The FAQ entry "Already on Anthropic Enterprise or OpenAI Enterprise — what does Pleach add?" compressed since the new homepage section above it now earns the depth. The bridge sentence at the end of the comparison- table section rewritten to point forward at the Enterprise- contract section.

Fixed

  • A11y on Enterprise-card pseudo-CTAs. The "Migrating from Anthropic Enterprise →" and "Migrating from OpenAI Enterprise →" paragraphs inside the two homepage migration cards now carry aria-hidden="true" so screen readers announce each card once through its <h3>, not twice through both heading and pseudo- button text.

2026-06-08 — later

Added

  • New homepage section "Already paying the lab" between the comparison table and the four pillars, pitching Pleach as the substrate that composes underneath an Anthropic Enterprise or OpenAI Enterprise contract. Three pillars (per-axis rollup inside one Workspace / Project, hash-chained AuditableCall row in your own Postgres, replay-determinism across snapshots) and two cards linking to the migration paths below.
  • New homepage FAQ entry "Already on Anthropic Enterprise or OpenAI Enterprise — what does Pleach add?" mirrored into the JSON-LD FAQPage graph.
  • New section "If you already buy direct from Anthropic or OpenAI" on Comparison, before "Where to go next" — three load-bearing claims plus a note on cloud-mediated transports (Bedrock, Azure OpenAI, Vertex).
  • New "Already on Anthropic Enterprise or OpenAI Enterprise?" section on the docs index, immediately after "Start here," with two cards linking to Migrating from Anthropic Enterprise and Migrating from OpenAI Enterprise.
  • New paragraph on Audit ledger framing tenantId as an opaque rollup axis — end customer in a SaaS, or employee / team / cost-center in an internal-use enterprise deployment — with cross-links to both migration docs.

Changed

  • Migrating from Anthropic Enterprise opener widened from "end customers inside a Workspace" to "a meaningful axis inside a Workspace" (covering employees, teams, and cost centers in internal-use deployments), plus a shape-note paragraph that the same row, hash chain, and fingerprint cover both shapes; tenantId is opaque. Frontmatter description updated to match.
  • Migrating from OpenAI Enterprise opener and frontmatter description widened analogously for the OpenAI Projects case.
  • Homepage metadata.keywords extended with Anthropic Enterprise, OpenAI Enterprise, per-end-user cost rollup, per-employee LLM chargeback, internal AI cost attribution, Workspace tenant attribution, Project tenant attribution.

2026-06-08

Added

  • New page Runtime inspector documenting inspectRuntime() from @pleach/core/inspector — the typed read-only introspection surface, the InspectionReport / CapabilityReport / PluginReport / CapabilityDescriptor shapes, and the 38 known capabilities (29 modern + 9 deprecated).
  • definePleachPlugin() factory section in Plugin contract covering the 8-key PluginCapabilities cluster and the _raw escape hatch.
  • contributeFabricationGuard section documenting the typed FabricationGuardImpl hook (7 methods) that retires the orchestratorHotpath.fabricationGuard untyped-bag entry.
  • [Pleach:capability-not-contributed] breadcrumb section with the 5 emitting capabilities and the payload shape.
  • CreatePleachRuntimeConfig.host.{strategies, modules, raw} section in Host adapter with the 15-key HostExtensionBundle list, the 3-key host.modules list (eventLogWriter, store, interrupt), the merge precedence, and the pleach-plugin-modernize codemod invocation.
  • bag-entry-retirement-readiness audit status table — streamHelpers RETIRED, toolCoupling RETIRE-READY, fabricationGuard NEAR-READY.
  • C9 hash-chain probe section in Tamper-evident hash chain documenting [UXParity:c9-hash-chain-row-stamp] (PE-1) and [UXParity:c9-hash-chain-verify] (PE-2), payload shapes, and the 3-batch clean condition of audit:c9-hash-chain-integrity.
  • @pleach/coding-agent/runtime contract section in Coding agent with the typed CodingAgentRuntime interface and the per-method first-slice behavior.
  • @pleach/core/inspector row in Subpath exports.
  • @pleach/sandbox row in Packages (Phase A contract + in-memory fixture, version 0.1.0).
  • This changelog page.

Changed

  • Packages table corrected to real published versions (was largely stale "Reserved · placeholder" for shipping packages). New bucket framing: Published 1.x (@pleach/core 1.1.0, @pleach/tools 1.2.0, @pleach/react 1.0.0) / Pre-1.0 release (@pleach/replay 0.7.0, @pleach/base-tools 0.1.0, @pleach/sandbox 0.1.0, @pleach/langchain 0.1.0) / Pre-1.0 alpha (@pleach/compliance, @pleach/eval, @pleach/gateway all 0.8.0-alpha.0; @pleach/mcp 0.3.0-alpha.0; @pleach/coding-agent 0.2.0-alpha.0) / Reserved (@pleach/trust-pack only).
  • Plugin contract "Sibling SKUs as plugins" section retitled (was "(planned shape; not yet shipping)") and rewritten with per-row real Phase A status.
  • @pleach/replay Phase B note now distinguishes the landed replayTurn body from the still-throwing fromSnapshot / fork / multiTenantAggregate.
  • Fabrication detection plugin- supplied strategies subsection now references the typed FabricationGuardImpl hook.

Fixed

  • Runtime inspector — replaced fictional RuntimeInspection / CapabilityState types with the real InspectionReport / CapabilityReport / PluginReport / CapabilityDescriptor. Removed the invented top-level breadcrumbs field (the inspector is read-only; breadcrumbs are emitted from PluginManager, not pre-computed by the inspector). Corrected the status discriminator to "wired" | "deprecated-wired" | "unwired".
  • Plugin contract — definePleachPlugin capability fields take values, not thunks. Corrected the 8 capability keys to the real cluster (prompts, runtimeAwarePrompts, safetyPolicies, fabricationDetectors, tools, streamObservers, intentToolMap, toolCouplingHints). Corrected contributeFabricationGuard to return one FabricationGuardImpl (not the fictional FabricationGuardContribution). Corrected the 5 breadcrumb capabilities to contributeStreamObservers, contributeSafetyPolicies, contributeFabricationDetectors, contributeToolCouplingHints, contributeIntentToolMap.
  • Host adapter — host.modules corrected to { eventLogWriter, store, interrupt }. host.strategies populated with the real 15-key HostExtensionBundle list. Codemod invocation corrected to node scripts/codemods/pleach-plugin-modernize.mjs <glob> (it's an internal repo script, not a published npm binary).
  • Tamper-evident hash chain — subpath corrected from @pleach/core/event-log to @pleach/core/eventLog (camelCase is the real export). C9 probe names corrected from the fictional [Pleach:c9-hash-chain] to the real [UXParity:c9-hash-chain-row-stamp] and [UXParity:c9-hash-chain-verify].
  • Event-log projections — subpath corrected from @pleach/core/event-log/projections to @pleach/core/eventLog (projections export from the ./eventLog barrel; there is no /projections subpath).
  • Subpath exports — inspector row's type names corrected from RuntimeInspection to the real InspectionReport, CapabilityReport, PluginReport, CapabilityDescriptor.