@pleach/core changelog
Release history for @pleach/core — site-docs entries that materially touched the @pleach/core surface, newest-first. Canonical runtime history lives upstream.
This page collects the site-content changelog entries that
materially touched the @pleach/core docs surface or
named a @pleach/core symbol, subpath, or audit gate. It is not
the runtime changelog — the canonical record of @pleach/core
runtime behavior lives in the upstream package
CHANGELOG.md and on
npmjs.org/package/@pleach/core.
See the combined site changelog at
/docs/changelog/combined for the
chronological unified view across every SKU.
Unreleased
Fixed
- Server samples import only from
@pleach/core/quickstart.@pleach/core/serverisn't a published subpath, and Server taught it in five samples. ThecreateHarnessServersample is now acreatePleachRoutes({ capabilities })override; thecreateInMemorySharedInterruptResolversample imports from@pleach/core/quickstartand passes the resolver ascapabilities.interruptResolver; the Next.js, Express, and Hono mounting examples useroutes.nextRouteHandlers(),routes.nodeHttp(), androutes.fetch. The bareHarnessServer/ROUTESimport 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 ascapabilities.interruptsinstead ofcapabilities.interruptResolver, and the Next.js catch-all samples on Server and API routes omittedbasePath, without which the dispatcher can't match/api/harness/...paths. Interrupts, Turn lifecycle, and SessionRuntime now point at the route factory instead ofHarnessServer.
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 bycreateProviderAdapterand 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 quickstartproviderStreammust dispatch toctx.resolvedModelwhen it is present. Multi-synthesize drops the "forward-compatible, honoured once the core widening ships" framing forcreatePerCallClassRouting: 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 reportscallCount,pricedCalls,unpricedCalls,costUsd(omitted when nothing was priced) and four token totals. The section states the limits: backgroundasync.spawntasks are excluded;callCountandcostUsdare floors when calls are unpriced;totalcan differ from the durablecost.rolluprow; retention is LRU over 32 turns, and a row arriving after release or eviction is markedtruncated. Event log documents the quickstartmessage.assistantrow'spayload.cost_rollupsnapshot (root_turn_key,snapshot,as_of,self,descendants,total,partial,truncated). The "Subagent cost attribution to the parent turn" row incontent/docs/migrating-from-anthropic-enterprise.mdxnow namesruntime.getTurnCostRollup(turnId). Upstream source, not yet published to npm.
Changed
- 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-disconnector queryon_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. DocumentsparseDisconnectIntent,bindDisconnectToTurnAbort,createTurnAborter, andDISCONNECT_INTENT; notes the intent values may be renamed before publish. Deployment replaces theabortSignal: req.signalroute example with a bound disconnect. Server documents the optional thirdrequestargument toHarnessServer.handleExecuteMessageand 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. - Edge runtimes are no longer supported.
@pleach/coreruns on Node.js (server side) or in a browser. Edge servers (Vercel Edge, Cloudflare Workers) and any server runtime withoutAsyncLocalStorageare 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 throwsToolExecutionContextUnsupportedRuntimeError(codePLEACH_TOOL_EXECUTION_CONTEXT_UNSUPPORTED_RUNTIME,runtimeof"edge"or"server-without-async-local-storage"; see Error codes), and the quickstartcreatePleachRoute()answers501before any stream starts. Move Edge routes to the Node.js runtime. The install, quickstart, deployment, and FAQ pages drop their Workers / Edge claims accordingly.
Fixed
- 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, andcompliance/gdpr-erasure.mdxsaid 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. - Drifting counts removed or labelled. The package count read 13,
14, 15, or 19 depending on the page, while the
packages.mdxtable lists 17 entries; overview cards,which-sku.mdx,license-compatibility.mdx, andorganization.jsonldnow point at the table instead of restating a number. Hook counts are labelled by what they count: 80 total (plugins/authoring.mdx), 71contribute*hooks (plugin-contract.mdx); the stale 41 inruntime-inspector.mdxis gone.nodes.mdxandgraph-node-catalog.mdxdisagreed on every node total (44 vs 42); the totals are dropped and the catalog's per-stage counts stay canonical. - Node-registry and plugin-hook counts re-derived from the
upstream contract.
NODE_STAGE_MAPcarries 42 names, not 43 — corrected on Graph, Node catalog, Audit gates, and Ownership; the catalog also drops two names that were never nodes (workspaceIndex,toolLoopStream) and re-stagesgarbledContentGuard/repetitionGuardto post-turn.HarnessPluginexposes 80 hooks (71contribute*+ 9 lifecycle), not 77 (68 + 9) — corrected on Core and Authoring, with Plugin contract now naming its narrower 70-hook audit denominator. Full detail in the combined view.
Added
-
Heartwood — the loader's two-scope resolution and shadow semantics, previously undocumented.
createFileHeartwoodLoaderresolves first-non-empty-wins across an explicitpath,./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.mdfully overrides the user-global file rather than concatenating with it. The page had named only thepathoverride. -
Prompt builder — the composition-determinism guarantee stated outright. A static or core contribution's content is a pure function of its
PromptContextand does not vary with tool-loop depth or turn recursion.contributeRuntimeAwarePromptsis the only channel that varies per turn, and static contributions are held out of theRuntimeStateSnapshoton purpose. Matching pointer added to Prompts. -
Skills — the
create_skillbase-tool for agent-authored skills. An agent can name a repeatable procedure as a reusable skill mid-session.create_skillis opt-in (list it ininclude) 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-demandskill_viewbody. -
Defensive patterns — a new Architecture page: six design rules the runtime holds itself to, each paired with the shipped
@pleach/coreAPI that embodies it. Includes the first docs coverage of the destroy-quiescence surface —AsyncTaskManager.seal(),awaitQuiescence(timeoutMs)and itsAsyncTaskQuiescenceReceipt, andSessionRuntimeConfig.destroyQuiescenceTimeoutMs(default 5 s) — landed upstream indfbbd6f239+a3ad79dce1. -
The
*_CALL_CLASSconstants from@pleach/core/graph/seams/callClassConstants. The page explained thatlint:callclass-literalsrejects 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 forbuildDefaultAgentGraph),graph/seams/callClassConstants,eventLog/durableFlush(setWaitUntilImpl/deferFlush/awaitPendingFlushes— the serverless durability seam),strategies/schemaCondensation,skillswith its two narrower entries, and the fourruntime/facets/*client-facet entries. -
audit:docs-vs-contractgains 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. -
Four new
@pleach/coresubpaths on Subpath exports —attestation/cms,crypto,context, and the corrected wildcard story.@pleach/core/cryptois carried as experimental with its DDL precondition inline: on a schema declaringwrapped_dekorivasNOT NULL,shred()raises SQLSTATE 23502 whilegetOrCreateDekstill 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/cmsemits a detached CMS (RFC 5652)SignedDataover an attestation's canonical bytes, Ed25519 per RFC 8419, alongsideAttestationV1.signaturerather than instead of it. DocumentsbuildAttestationDetachedCms, whycertificateDeris effectively required for an independently-checkable artifact, and the RFC 5652 §5.4 re-tag invariant:signedAttrsis encoded[0] IMPLICITbut signed as a universalSET, and getting it wrong yields a structure that verifies nowhere while staying self-consistent. Core re-reads the emitted DER and throws a namedsigned-attributes-mismatchat emit time. Detect withisCmsAttestationError, neverinstanceof. -
Which merkle construction built the root —
MerkleConstructionand themerkleConstructionfield onChainProofV1.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 fromchain_key_version. -
session.endedandHARNESS_EVENT_TYPES.session.endedmakes 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_TYPESis the runtime mirror of theHarnessEventunion, pinned by an exhaustiveRecord<HarnessEventType, true>in production source. Membership means emittable, never persistable. -
Auth events.
AuthEventType,AuthMethodClass,AuthEvent,AuthEventSink, andcontributeAuthEventSink. 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: nocollectAuthEventSink()collector yet and no publishedexportsentry 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-contractfor@pleach/core/rbac,@modelcontextprotocol/sdkfor MCP,@sigstore/corefor RFC 3161 receipt verification. Each fails with a named error identifying the package rather than a module-resolution stack. -
The RFC 3161 surface is now reachable from the paths consumers actually walk, not only from the primitives.
createPleachAgenttakes atimestampAuthority— before this the quickstart calledattestChainStatewithout one and exposed no way to supply it, so the default path produced claim-only attestations permanently. Both the agent and the runtime now exposeevidence(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 readstimestamped: true, and there is noclockAnchoredfield because core cannot verify that claim. -
chainAnchorSchedulerin@pleach/recipescomposes the scheduled anchor-and-verify pass that every consumer previously wrote by hand. It exposesrunOnce()and no loop: a conveniencestart()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 aprev_hashwalk — a chain that verifies is not the same as a chain that matches its witness),evaluateChainAnchorFreshness(grade liveness on staleness, never on row count;anchorCountandtimestampedAnchorCountare separate signals because damage and staleness are independent failures), andclassifyChainAnchorAlertLevel. 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 upgradeissuedAtfrom a claim to a proof; only the TSA countersignature does that. Upstream:ivybiosciences-nextRP-340. -
Comparison adds an agent-forward "usage axis" section, and the homepage "Quick answers" intro is broadened to match. The claim: Pleach's surface is built to be operated by agents — the introspectable facet API (
runtime.tenant,runtime.events,runtime.graph.*, CI-gated byaudit:facet-coverage),TechArticleJSON-LD from one controlled tag vocabulary, per-page Markdown twins, a live MCP server, and an agent-skills index — not a human console with agent access added on. Distinct from the capability differentiators; no existing value prop changed. -
Comparison adds a governance-control-plane / AI-gateway category. Frames
@pleach/coreagainst governed-proxy control planes (Portkey, Cloudflare AI Gateway, and the enterprise control planes above them) as altitude, not timing: a proxy governs the call at the HTTP boundary; core governs the agent's execution graph and writes theAuditableCallrow to a database you own. Relatedly, Landscape row 1 now notes that proxy-advertised "tamper-evident audit trails" live on the vendor's side, not as a hash-chained row you own. -
Five more
@pleach/corepublic exports documented (720a6e8a3/de4403b6a). Interrupts addsrewriteToolArguments— the natural-language → structured-args rewrite for approval-with-edit flows; it runs on theutilitycall class and never throws, resolving to the original arguments on every fallback path. Tools adds the standalonecreateDiscoverToolsTool/DISCOVER_TOOLS_TOOL_NAMEfactory for hand-rolled servers. Server addscreatePluginToolRegistry— the getter-backed registry behind/toolsand/tools/:name. Storage addscomposeDurableStore(build aDurableStorefrom adapters you already hold) plus the optionalblobmember andcreateMemoryBlobStore/MemoryBlobStore. Adoption paths names theBrownfieldRuntimeMenuoptions type; Prompts names the optionalPromptDescriptor({ title?, summary? }) surfaced byruntime.prompts.describe(). Upstream trunk, not yet published to npm. -
New Pricing math page. Documents the
@pleach/core/pricingsubpath —computeTurnCost,DEFAULT_PRICING_MATRIX,createPricingResolver, the OpenRouter fetch, andresolveCostEventUsd. -
React lab component kit documented. The full
@pleach/core/react/labsurface — PleachLab's composable panels plususeLatticeState/useEventLogCapture/useChannelSnapshot— with@pleach/core/react/labnamed as the canonical subpath. -
Three prompt- and context-management capabilities documented. Orchestrator middleware adds the optional
summaryProviderfield onSummarizationConfig— 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: thestability: "stable" | "volatile"tag onBudgetedSectionand thestableBoundaryIndexfield onComposedPrompt—composeBudgetedPrompthoistsstablesections into a contiguous prefix (untagged input stays byte-identical) and reports where the volatile suffix begins, so a consumer places its providercache_controlbreakpoint afterincluded[stableBoundaryIndex - 1]. Prompts adds "Persisting an agent's role" — put durable persona in thecore.role-templateslot viareplaceCore/prependPersonaand tag itstability: "stable". Upstream trunk, not yet published to npm. -
condenseTools.intentPriorityMapgiven its real type. Tools replaces theintentPriorityMapplaceholder withRecord<string, readonly string[]>— an intent name mapped to the tool names that keep their full schema when that intent is active. Upstream trunk, not yet published to npm. -
condenseTools+ the discovery meta-tool documented. Tools gains thecreatePleachRouteoption that trims thetools[]array above a threshold — keepingmaxSchemaToolsfull schemas and surfacing the rest as one-line names — plus the discovery meta-tool (metaToolName) the model calls to pull a dropped schema back. Distinct from the prompt-directiveweakToolSchemaBudgetPluginon the same page. Upstream trunk, not yet published to npm. -
Model-pipeline surface documented — two new pages plus eight section additions. Model hooks documents the
@pleach/core/hookspre/post-model seam (PreModelHook,PostModelHook,ModelProfile+historyTrimmerHook,lazyModelDefaultsHook,toolCallValidatorHook,repetitionDetectorHook, wired viaruntime.model.registerPreHook/registerPostHook). Orchestrator middleware documents@pleach/core/middleware(OrchestratorMiddleware,MiddlewareStack,ResultEvictionMiddleware,SummarizationMiddleware,LanguageModelMiddleware,CHARS_PER_TOKEN, wired viasetOrchestratorMiddlewareInit). Both join Subpath exports under a new "Model pipeline" category with@pleach/core/synthesis(SynthesisEmitter,enrichOffloadedToolPreviews). Sections added:finalizeAnswer+ the{ banner }return onpostSynthesisGuard(Plugin authoring);ProviderCatalogContractand theSLOW_COLD_START_PLANNER_FAMILIES/isSlowColdStartPlannerFamilygate (Providers);InterruptManager.requestApprovalWithId(Interrupts);runtime.abort(reason)/AbortCoordinator+TURN_ABORT_REASON(Session runtime); the durablesubagent.tool_usedaudit row (Subagents); theharness_event_log_owner_selectper-user RLS policy +harness_event_log_service_rolewrite bypass (Multi-tenant); andMemoryStoreas theconfig.storeship-a-default. Existing published@pleach/coresurface; upstream trunk, not yet on npm. -
Four runtime-behavior sections documented. Each mechanism shipped upstream but had no doc home. Tools gains
weakToolSchemaBudgetPlugin(@pleach/core/prompts) pluscreateWeakToolSchemaPredicate(@pleach/core/modelfamily) — the proactive tool-call budget for weak-tool-schema families (google/deepseek/moonshot, defaultsmaxBatch: 4/maxSameTool: 2), gated onPromptContext.family. Turn lifecycle documents the no-first-token dead-air hard-cut (reduceTurnDeadAir; upstreamd062ab24d5). Providers documents the stalled-rung cascade pivot, classedSYSTEM_ABORTnotUSER_ABORT(upstreame1fa3f1487). Fabrication detection documentsmetadata.uncoveredPlanStepsand the honest "not dispatched" note (upstreambb0f995fce,ca9dc86644). All from published subpaths or documented runtime behavior; upstream tree8f224cbf42on trunk, not yet published to npm. -
Standalone hosted-agent route family —
createPleachRoutes,createPleachAgent,DurableStore,MemoryEventLog.@pleach/corenow mounts the whole route family from one factory, not just the single execute leg.createPleachRoutesand the three-armcreatePleachAgent({ context, tools, db })façade (both@pleach/core/quickstart) mount sessions CRUD, execute+SSE, interrupts, checkpoints, rollback, events-recall, sync, and fork;createPleachAgentreturns{ fetch, nextRoutes(), nodeHttp(), store }.DurableStore+createMemoryDurableStore()(@pleach/core/store) unify storage, checkpointer, event-write, event-read, and recall behind one binding, andMemoryEventLog(@pleach/core/query) is the keyless in-memory recall ledger with anasQueryClient()shim — so recall works with no Supabase whendbis omitted.createHarnessServer({ runtime, storage, checkpointer?, events? })is the build-only auto-bind factory over the still- unpublished@pleach/core/serversubpath. Known limitation: the default interrupt resolver binds a per-request in-processInterruptManager; a durable multi-request deployment supplies its own viacreatePleachRoutes(...).capabilities.interrupts. Landed across API routes, Server, Quickstart, Storage, and Query. Upstream: pleachtui Track A,@pleach/core@0.1.0on trunk (Waves0b34ab8742,095d037933,add6562a15,2b20c9c4be) — on trunk, not yet published to npm. -
Runtime strategies documents the
resolveCallReasoningEfforthook. A new per-callSessionRuntimeConfigstrategy slot. The runtime consults it before every provider stream with the resolved{ callClass, family, modelId }; the returnedReasoningEffort("low" | "medium" | "high","none"to disable the budget,undefinedto leave it untouched) threads ontoStreamChatOptions.reasoningEffortand the adapter lowers it to the provider request. Capability-gated — a model that doesn't advertise reasoning control ignores the field, so an unsupported model never 400s on the param.ReasoningEffortis opaque to core: the host owns the policy of which call class on which family to cap. Unset ⇒ no field attached, request byte-identical. Fail-soft — a throwing resolver is caught and treated asundefined. Added to the "Newer injection hooks" table plus a per-call cadence note. -
Comparison gains a category for agent-memory & knowledge-graph substrates (a read-side category). Pins the read-vs-write delineation for
@pleach/core: memory layers and knowledge-graph engines (Letta, Mem0, Zep) are a read substrate — the graph exists so the agent can query it to decide;@pleach/coreis 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). Compose-not-compete — a memory graph reads the same session theAuditableCallrow writes.
Changed
-
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). -
Reasoning-only recovery documented as default-on for the packaged surface. Providers already documented the opt-in
SessionRuntimereasoningRecoveryDI; it now records thatcreatePleachRoutedefaults it on (opt out withrecoverReasoningOnly: false), so a reasoning model that emits only chain-of-thought gets one same-model re-elicitation instead of a false family-exhausted. Interrupts gains a pointer from "Cross-request approval" to theinterruptResolveroption (createInMemorySharedInterruptResolver()/ a store-backedDurableInterruptResolver).
Fixed
-
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_messagesis the exception: it is host-provided, no code in@pleach/corewrites 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.sqlfile per row and marks that oneNo — host-provided. Also recorded:ai_chat_manifestsandrefresh_chat_manifest_from_eventsship in no SKU, sogetChatManifest,getManifestJobsByStatus,getConversationStateandgetSessionReviewrequire consumer-supplied schema. -
The Graph callout said seven symbols were unreachable; it is now six. Upstream published
@pleach/core/graph/defaultAgentGraphthe day after the callout was written, givingbuildDefaultAgentGrapha 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/coresubpaths 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
@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 throwERR_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 publishedexportsmap. 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).HarnessPlugindeclares 78 members. -
AuditRecordVersioncited as 19, now 25 (CI enforcement). Six additive versions landed since:outcome.why.stats.servingProvider, sub-agent attribution (parentTurnId/subagentId/subagentDepth),decision.lockedFamily, theprovider-exhaustedstatus,decision.fallbackChainbecoming additive-optional so an omission is an admission rather than a fabricated[], anddecision.rungOrdinal. -
@pleach/core/audit-ledgeris not a subpath (Attestation) — the published path is@pleach/core/audit.@pleach/observabilityis not a package (OTel observability) — the SKU is@pleach/observeand the shape is a destination.@pleach/core/schema/postgres(Schema) corrected to@pleach/core/schema/postgres/*.sql, the published.sqlasset glob. -
Subpath exports claimed to snapshot
@pleach/core@1.x. No@pleach/*SKU has shipped past0.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-contractgained a fourth check: EXPORT-MAP DRIFT. Every@pleach/...specifier the docs teach is now resolved against a committed mirror of each package's publishedexportsmap, so a specifier that would throwERR_PACKAGE_PATH_NOT_EXPORTEDon a freshnpm installfails at the point of drift. The site-side mirror of the upstreamaudit:doc-example-import-resolutiongate. 2,348 specifiers resolved against 19 export maps; every fix above was found by it. -
Model-resolution matrix — Google's fast tier was stale. Model resolution matrix listed
gemini-3-flash-previewfor the Googleconverseandutilityrungs; the live matrix resolves both togemini-3.5-flash-lite. A reader who saw the old id would have keyed a fingerprint or cost estimate off a model that no longer fires. -
Off-policy example term scrubbed from Prompts. Two
gatedPromptexamples keyed on a"modal"tool; both now key on the neutral"sandbox"capability. Example-only — no API or claim change. -
@pleach/coredoc corrections from a ~200-commit upstream sweep. Graph node catalog: core registry corrected 44 → 43 — two domain plugin nodes were listed as core, and the core nodesyntheticExpansionDetectorwas missing. Config manifest: added a partial-coverage caveat (only the plugin surface is content-hashed today). Fabrication detection: documented the ~13-detector grounding/offloaded-data cohort the exports table omitted. Air-gapped deployment: corrected from "v2+ roadmap item" to the shipped fail-closedairGappedenforcement. Adoption paths:createBrownfieldRuntime(@pleach/core/runtime) is shipped, no longer "proposed." -
Four broken root imports corrected to their real subpath. Five code blocks imported a symbol from
@pleach/corethat the root barrel does not re-export (verified against the packageexportsmap):SupabaseAdapter/createSupabaseAdapter(Research agent) →@pleach/core/sessions;withTenantHeader(Multi-tenant SaaS agent) →@pleach/core/tenant;computeFingerprint(Testing) →@pleach/core/fingerprint;EventLogWriter(Event log and Recipes) →@pleach/core/eventLog. Each would fail to resolve on copy-paste; the subpaths are public per Subpath exports. -
Two orphaned pages wired into the sidebar — Install (Get Started) and Cycle-break contract packages (Reference) existed but were reachable only by direct URL.
-
Adoption paths "Host adapters" card corrected — it promised "implement OrchestratorAdapter / StorageAdapter", but Host adapter documents the
setHarnessModuleLoadermodule-loader seam. Reworded to match. -
Stale
AuditRecordVersionclaim corrected —18→19. CI enforcement stated the locked row shape was "currently 18"; upstream shipped the additive bump to 19. A version claim is load-bearing — a reader who saw "18" needs this row to know it moved. The package's published value is the source of truth; this tracks the shipped bump. -
Hash-chain verifier home corrected to
@pleach/core/eventLog. Audit ledger (two spots) and Recipes saidverifyChainForChat/generateProof"ship in@pleach/replay@0.1.0". They are defined in@pleach/core/eventLog;@pleach/replayconsumes them. Corrected across Audit ledger (two spots), Recipes, Which SKU, and Regulated-domain agent; now consistent with Hash chain. -
Error-code range corrected to
1xxx–11xxx. The authoritative band table in Error codes defines10xxx(caller-auth) and11xxx(runtime/infra). Stale1xxx–9xxx(frontmatter + Troubleshooting ×2) and1xxx–7xxx(Contributing, Stream events) summaries now match the table. -
maxConcurrentSubagentsclamp claim corrected. Research agent said amaxConcurrentSubagentsaboveSUBAGENT_LIMITS.maxConcurrentis clamped to it. They are separate limits on separate paths (default4caps theSubagentManager;3caps the imperative spawn path), neither clamped to the other — now consistent with Subagents. -
Unknown safety-policy ids now throw at construction — even with no plugins. Safety promises "Construction throws
UnknownSafetyPolicyErrorif the config references an id no plugin registered — operator typos surface at boot, not on the first turn." Previously the enable/validate loop was gated behind the plugin block, so a plugin-lesscreatePleachRuntime({ enabledSafetyPolicies: ["typo"] })silently no-op'd the enable and the typo surfaced (or silently didn't) only at first turn. The enable loop now runs unconditionally (coreSessionRuntime.ts); theregister()loop stays plugin-gated, so a legitimately plugin-contributed id is registered before the enable finds it and valid constructions are unaffected. The impl now matches the documented guarantee. -
The chronological error trail (
errorCodesChronological) now captures every error class. A completed tool call carrying a structured_error_code(its status looks successful, so it tripped neither the failed-status nor the schema-validation branch) and a caught async-planner throw (AsyncPlannerHandler, previously console-only) now each persist anerror.coderow. A live turn with these errors previously persisted zero rows; the durable trail is now complete. (Direct-API tool errors were already covered by the host emit path.) -
Core-concept doc snippets reconciled with shipped signatures (devharness FINDING 88, 91–93). Determinism — the ledger read used a non-existent
ledger.list({ sessionId }); the realAuditableCallQueryread is async positionalawait ledger.getSession(sessionId)(coreaudit/ProviderDecisionLedger.ts), and the "distinguishes three operating contracts" line corrected to five (theRuntimeModeunion — and the page's own table — lists five). OTel observability —executeMessageis positionalexecuteMessage(sessionId, "hello"), not the object formexecuteMessage({ sessionId, content })(coreSessionRuntime.ts). Stream events — the LangGraph"values"mapping usedruntime.sessions.get(), whichRuntimeSessionsFacet(corefacets/sessions.ts) does not expose; corrected toruntime.sessions.resume(sessionId).
Added
-
Gate failures → fixes — the failure-string lookup. Maps each gate's verbatim, greppable failure string to its meaning and the fix doc —
[graph-stages] Node "<name>" missing stageId in NODE_STAGE_MAP,[audit:c8-event-type-allowlist-coverage] FAIL,[auditable-call-version] FAIL rule 3,[audit:plugin-contract-completeness] FAIL, and others, all verified againstscripts/audit/. The agent-facing close of the self-extension loop. -
AuditRecordVersioncorrected14→18on CI enforcement to match the source (export type AuditRecordVersion = 18;) and the AuditableCall row. -
Extending Pleach — the gate-paired authoring map. Pairs each extension point with the interface, the registration call, and the audit gate that fails if the addition is wrong — nodes (
audit:graph-stages), event types viacontributeEventTypes(audit:c8-union-member-has-produceraudit:c8-event-type-allowlist-coverage), scrubbers, plugin hooks (audit:plugin-contract-completeness), prompt blocks, and a custom audit field viapluginPayloads(audit:auditable-call— the structural column set is locked). Draws the host-extension vs upstream-contribution line, and adds an "Agent-driven self-extension" section: the gates as an autonomous write →audit:*→ read-failure → fix loop, plus injecting the extension contract into the operating agent's prompt viacontributeRuntimeAwarePrompts. Nodes, channels, and scrubbers gained a "What CI checks when you add one" footer linking into it.
-
createPleachRoute({ demo })keyless first-run + demo-firstpleach initscaffold documented. Getting started, Quickstart, and Install now lead the wizard path with a keyless demo: with no provider key,createPleachRoute({ demo: process.env.NODE_ENV !== "production" })drives a real graph turn over canned model text and writes realAuditableCallrows, flaggedx-pleach-mode: demo. A resolved<PROVIDER>_API_KEYalways wins; demo never engages in a production build. The Next.js App Router scaffold adds an/auditview (app/audit/page.tsx+app/api/audit/route.ts) rendering the per-model-family rollup (family · rows · tokens · est. cost). The barecreatePleachRoute()no-key contract is unchanged (HTTP 503). -
engine/superstep scheduler named as an architecture piece +facets.mdxsynced to the shipped facet inventory (pkgclean 06 D7/D9). Architecture and Concept clusters now name theengine/scheduler (SuperstepRunner+ its primitives) as the deterministic superstep executor that runs the compiled graph. Facets gained the two shippedSessionRuntimeaccessors it omitted —runtime.observeandruntime.probes— plus the four per-stage graph introspection facetsgraph.anchor/graph.toolLoop/graph.synthesize/graph.postTurn. -
@pleach/core/skills+@pleach/core/agents/typesare real emitted subpaths. Skills updated to importSkillLoader,parseSkillFrontmatter,Skill, andSkillFrontmatterfrom the@pleach/core/skillsbarrel (the/loader,/parser,/typessub-subpaths do not exist); Agents prose corrected from "wildcard path" to a real emitted@pleach/core/agents/typessubpath.
Changed
-
@pleach/core/internal/…subpaths retired from the public docs surface (pkgclean 06 D8). streamSingleTurn and Subpath exports no longer document@pleach/core/internal/strategies/streamSingleTurn/helpers(+ its four direct helper entries) or@pleach/core/internal/tools/execution/registryResolvedToolsasstablepublic imports. Theinternal/segment marks implementation details, not a supported API; the copy-paste helper-barrel import is removed and both paths moved to a "Not a public import surface" section with their public alternatives —ToolDefinitionfrom@pleach/core/types/generic, and@pleach/core/tools/execution(which re-exports the resolved-tools registry functions). Nopackage.json:exportschange. -
core.mdxstale numbers corrected.auditRecordVersionupdated13 → 18(real value atAuditableCall.ts), and theHarnessPluginplugin-hook count updated~41 → 67contributeXhooks (derived by greppingpackages/core/src/plugins/types.ts).
Fixed
-
More SKU doc-page snippets reconciled with the shipped signatures (devharness FINDING 80–82). Fabrication detection — the custom-detector example used a non-existent
ctx.toolArgsand returned{suspect, tier}; corrected to the realFabricationDetectorContextfields + theFabricationFindingshape ({detectorId, severity, reason, evidence?}), and thetier-routing bullet corrected (routing keys on the tool'ssafetyTier, not a finding'sseverity). Multi-tenant —getAggregateUsageis 3-positional ((client, store, filters)), has nogroupBy: "tenantId"value (session/agent/model/tool/day/week), nests dates underdateRange, and requiresuserId(it's single-user scoped; tenant rollups use the raw SQL). Determinism — the fingerprint round-trip read a non-existent.fingerprintaudit field (real:fingerprintComposite, a string) and compared a string to aFingerprintobject; corrected to a like-for-like comparison over a realFingerprintInput. These are the ctor-shape / call-arity / field-name classes the newaudit:doc-import-resolutiongate doesn't cover (import-resolution only). -
Event-log read side documented as store-agnostic —
eventReader/HarnessEventReader. Event-log projections saidruntime.events.iterate/.foldreadharness_event_logrows ordered by(chat_id, sequence_number)and became live "on the Supabase backend in PA-1 Phase A.2" — store-specific claims that no longer match the shipped surface. Corrected: both accessors delegate to aHarnessEventReaderinjected as the runtime'seventReader(the read-side counterpart toeventLogWriter), so the host casts its own store into the reader at construction and@pleach/coreitself stays free of backing-store knowledge — Postgres, Supabase, SQLite/pglite, or an HTTP API back the same surface.iterate's options gaintenantId; the reader is required to read the durable log (no built-in reader, no implicit store fallback — a bare runtime yields nothing, matching theMemoryAdapterpath) and throws a typed error at the call site when absent. New Backing the reader section shows the one-method contract yieldingEventLogRow(the shapereconstructSessionStateand the shipped projections fold). Session runtime config table gainseventLogWriter+eventReaderrows; Storage grows theci:devharness-sqlvalue-prop battery from four durable properties to nine — adding the@pleach/observepostgres()destination, time-travel fork, SQL-queryable audit ledger (harness_auditable_calls), tamper-evident hash chain, and@pleach/replaydeterministic replay over the injected reader. -
SKU doc pages reconciled with the shipped import/construction surface (devharness FINDING 76–79). Four doc-site pages drifted from the (correct) package READMEs: Building a chat UI advertised a fabricated
@pleach/reactchat-hook API (useChat/HarnessProviderfrom the root,useInterruptDecision,useChatVercelCompat,sendMessage) — corrected to the real surface (useSessionRuntime/useSessionMessageStream/useInterruptUIfrom@pleach/react;useChat→submitfrom@pleach/core/quickstart;HarnessProviderfrom@pleach/react/legacy/@pleach/core/react;useVercelAISDKCompatfrom@pleach/react/adapters/vercel-ai-sdk). LangChain —LangChainProvidertakes a POSITIONAL model arg and wires via the top-levelprovider:slot (not{ model }/host.strategies.provider). Base tools — the scratchpad is per-SESSION (chatId-scoped, not per-turn), its param isoperation(notop), and its value is a string. Coding agent — the four sandbox tools register via acontributeToolsHarnessPlugininplugins:(SessionRuntimeConfighas notools/contextfield). A newpackages/core/test/docImportSurface.smoke.test.mjsregression-locks the import-path half. -
Observability + gateway-cost docs corrected to the shipped exporter/cost surface (devharness FINDING 73–75).
@pleach/coreships no@opentelemetry/*dependency and never reads the global tracer provider — the documented NodeSDK + OTLP recipe captured zero pleach spans. OTel observability and Observability now show the real path: a host-suppliedOtelExporterbridge injected vianew SessionRuntime({ otelExporter })(default isNoopOtelExporter, which drops spans).runtime.spans.snapshot()returns{ inFlightCount, isShutdown }(exporter state) — to inspect emitted spans you wire aCapturingOtelExporterand read.captured(real fieldsstartTimeNs/endTimeNs/parentId). And Gateway cost events + the gateway OTel wiring:computeCostwas readingtenantId/family/callClass/byokActive/routingDecisionoffRouteChatCompletionOutput, which carries none of them (asTenantId(undefined)threw → zero CostEvents) — the example now reads only real output fields + host-supplied observation context, and flags thatrouteChatCompletionis currently a slice-2 stub (costUsd: 0). -
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 host suppliessubagentExecutor/ drivesSubagentManager); the docs presented it as substrate-delivered. Corrected in Subagents: removed the fabricatedspawnsSubagent: trueauto-escalation flag;LightweightRuntime→ the realLightweightSessionRuntimeimported from@pleach/core/subagents(not root) with its real constructor;fetchWorkspaceContext/formatWorkspaceContextPromptmoved to the@pleach/core/subagentssubpath; the concurrency model corrected (the runtime spawn path caps on the hardSUBAGENT_LIMITSconstant and FAILS over-cap rather than queueing — theSubagentManagerqueue/DAG is host-driven);context.variablesnoted as currently inert; plus a host-completion caveat. And Async tasks: the async-task tool-loop bridge is not wired in bare core (ASYNC_TASK_BRIDGE_NOT_WIRED), and the"subagent"/"sandbox_exec"task executors are host/plugin-supplied (the in-treeSubagentTaskExecutoris server-only), not "in-tree defaults". -
Abort + resume docs synced to the shipped runtime behavior (devharness FINDING 56 + 62). Aborting an in-flight turn now records
outcome.status: "user-aborted"(not"aborted"/ not lumped intoprovider-error) at BOTH the tool-loop decision call and the synthesis terminal, so cost rollups + compliance separate caller cancellation from provider failure — corrected across session lifecycle, SessionRuntime, turn lifecycle, and API routes. And resuming a session now describes the real three-layer rebuild: storage row → version-guarded checkpoint overlay (the crash-recovery path) → server-only event-log hydration of the ephemeral card-lifecycle state (interrupts/subagents/exports/user cards) onto a transientSession.hydratedHarnessStatefield — correcting the prior claim thathydrateFromEventsrebuilt messages/channel state. -
Model-resolution-matrix path corrected — it is host-supplied, not a
@pleach/coredir (pkgclean 06 D7). The docs cited the family-lock matrix at the fictionalsrc/graph/modelfamily/(family-lock) and@pleach/core/ai/modelFamily/matrix.ts(quickstart, provider detection) — neither path exists in the package. The(family × callClass)matrix table is host-supplied and reached through theAgentAdapter.resolveModel<C>()seam; theProviderFamilyset is now pointed at the real@pleach/core/modelfamilyexport. The routing-decision seam's Ivy-internal host path was removed from routing decisions. -
Docs reconciled with the shipped
@pleach/coreruntime (value-prop-vs-impl audit, devharness FINDING 56–64). Corrected doc claims that diverged from the implementation:- Time travel —
forksetsparent_id: source.id(notnull). - Checkpointing — checkpoints write at message/event
boundaries (discriminated by
CheckpointMetadata.source), not stamped with a per-stagestageId;SupabaseSaverdurability is"replicated"; rollback writessource: "manual"+writes: ["rollback"]; theforksnippet takes a stringnewSessionId. - Session lifecycle — the checkpoint snapshot is authoritative on the live restore path; the event-log canonical reader is a flag-gated shadow today.
- Sync — interactive conflict resolution (
runtime.resolveConflict, thesync.conflictevent, the 3xxx code range) is enterprise-tier/planned; open-core usesSyncCoordinatorlast-writer-wins-on-push with a free-textlastError. - Query — dropped the non-existent
queryAuditableCalls; correctedgetChatUsage/lookupModelCost/getSessionReview/getInterruptChainsignatures + return shapes to the real@pleach/core/querysurface. - Memory — the production extraction path is the graph node
(
createMemoryExtractionNode), not thememoryExtractionHook→ queue pipeline;LearnedFact.sourceis a provenance string (+createdAt/lastConfirmedAt) on extractor facts, with the object form documented alongside. - Lineage — opt-in via
config.lineageTracker; the runtime records the session node + abranched_fromfork edge, the other relations are host-recorded;completeSessionis host-called.
- Time travel —
Added
- Opt-in tool-event preview enrichment for the manifest projection. New
runtimeQuirks.enrichToolEventPreviewsForReplayflag (default OFF) lets the host write compactargs_preview(tool.started) +output_preview(tool.completed) onto tool events;chatManifestProjectionfolds them into richer manifestparams/output, closing the projection's intentional lossiness vs. the live provider. The previews are scrub-allowlisted (the C8 redaction chain processes them). OFF by default preserves thearguments_hash-only privacy posture. This makes the projection canonical-capable; the projection-canonical flip itself stays gated. See Replay. - TimeTravel surfaces the chat manifest (
StateSnapshot.manifest).getState/getStateHistory/fork/bulkUpdatenow carry the chat-manifest ledger AS-OF a checkpoint, for inspection (it does not feed the next generation — that runs throughrollbackToCheckpoint/resumeSessioninto the live provider). The snapshot rides the checkpointmetadata(round-tripped viaSupabaseSaver.metadata_extra; Memory/IndexedDB ride free), mirroring thependingTaskspattern. See Time travel. ProviderFamilyExhaustedErrorpromoted to the top-level@pleach/coresurface. The provider-family cascade terminal (raised when every in-family rung is exhausted) + itsisProviderFamilyExhaustedErrorguard are now public on@pleach/core— previously reachable only via the deep@pleach/core/graph/seams/providerExhaustionpath. Catch + narrow it from the top-level import.@pleach/core/cache— content-hash deriver.deriveContentHashKey,canonicalizeKeyInput, andContentHashKeyInputnow have their canonical home in@pleach/core/cache(relocated from@pleach/replay/cache, which re-exports them for back-compat). The move lets@pleach/corederive + stamp acacheKeyintotool.completed/turn.completedevents without the forbiddencore → replayimport. See Subpath exports.@pleach/core/manifest— reload-durability + the manifest as a projection. The chat-manifest ledger (the[Session Manifest]prompt block) now survives a process reload:SessionRuntime.saveSessionstamps the live snapshot into the persisted session state andresumeSessionrehydrates it (complementing the existing checkpoint rollback restore). NewchatManifestProjection/foldChatManifestfold the manifest deterministically from the event log (tool.*/job.*/model.upgraded), replayable viaruntime.events.foldand the@pleach/replaystepper — intentionally lossy vs. the live provider (the log carries hashes/sizes, not full params/output), measured by a flag-gated[UXParity:manifest-projection-divergence]shadow probe. See Subpath exports.tool.completed/turn.completed— optionalcacheKeypayload slot. Lets a deterministic replay consult the provider cache on the row (consumed by@pleach/replay'sReplayHandle). Host- /createCacheMiddleware-populated; core does not derive it (thecore → replayboundary forbids importingderiveContentHashKey). See Replay.
Added
- CI enforcement of the audit contract —
new Reference page indexing the audit-gate
catalog by the auditability and replayability
clause each gate enforces. Covers the
@pleach/coreevent-log gates (audit:auditable-call,audit:auditable-call-soak,audit:event-log-manifest-hash-completeness, the threeaudit:config-manifest-*gates,audit:c8-event-type-allowlist-coverage,audit:c9-hash-chain-integrity) and the CI jobs that carry them (graphnoderef,local-clone, per-SKUconsumer-rehearsal). Cross-linked from Audit gates. - Contribution namespaces — new page
documenting the nine namespaces every
HarnessPlugincontribution hook resolves to (prompts,stream,safety,audit,intent,tools,middleware,policy,lifecycle) — the canonical,audit:plugin-hook-category-assigned-gated contract layout, with representative hooks per namespace and the rolling-out typed namespaced authoring form. Plugin contract gains a cross-link; Authoring a HarnessPlugin reframes its informal 12-bucket grouping as the scan view of these nine canonical namespaces. - 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.v1prefix,0x1Fseparator, mirroring the hash chain'spleach.c9.v1canonicalization). Per-surface child hashes, the nullablemanifest_hashforeign reference onharness_event_log, reference-counted retention (default forever), full-snapshot storage, and the canonical replay/audit query shapes. Markedin-flight— table and event-log column land as additive schema files during rollout. - What Pleach writes to your database —
new page mapping every
@pleach/coretable written to a buyer's database, what's default versus opt-in, and the destination-is-yours posture (no phone-home). manifest_hashcross-references added to Event log (stamping section +EventLogRowfield) and Schema (rolling-outharness_config_manifestsection).- OrchestratorClient — new
top-level page documenting 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. Covers the six user-facing facets (config,history,context,tools,model,prompts) and the_internal.graphsnapshot consumer code must not touch. - streamSingleTurn — new
top-level page documenting the canonical per-turn body. Lifted
into
@pleach/core/strategies/streamSingleTurn/with a stable helpers barrel re-exportingTurnAccumulator,ToolDefinition,OrchestratorMessage, andProviderFallbackConfig. - Subpath exports — adds two rows
to the Runtime + composition table:
@pleach/core/runtime/orchestratorClientand@pleach/core/strategies/streamSingleTurn. Both are now named subpath exports rather than wildcard-only reachable. - Subpath exports →
@pleach/core/quickstart— added under the Wire + tooling cluster. Lists the five LANDED deliverables —createPleachRoute(fetch-handler factory),useChat(Pleach-native React hook),<ChatBox />(unstyled, accessible),defaultPlugin(empty baseline),providerDetectionhelpers + constants — plus the benchmark-adjacentcreateBenchmarkPlugin. - Attestation — new top-level page on
the Ed25519-signed envelope substrate that sits on top of the
hash chain. Documents the
@pleach/core/attestationsubpath (signer, verifier, key-store interface), the two stub production adapters (AWS KMS, Vault Transit), and the file-backedattestation/testingadapter. - Architecture § Boundary rules —
adds a sixth row to the gate table:
audit:domain-string-purityforbids domain-specific literals inpackages/core/src/**across five pattern families. Pairs with the existinglint:harness-boundaryrow, which forbids domain imports — the new gate covers domain strings. - Core "What you get" — new bullet "Composes under an existing Enterprise contract" after the AuditableCall ledger bullet.
Changed
- Family-lock page documents the host-internal planner carve-out.
family-lock.mdxgains a "Host-internal planner calls" section. The lock governs seam calls —synthesize/converse/reasoning/utilityon the provider seam — but a host'sanchor-planplanner cold-start can run on a pinned host-configured model that never consults the(family x callClass)matrix, so it sits outside the lock by construction, not as a leak. The row is identifiable bystage: "anchor-plan",callClass: "utility",payload.kind: "planGeneration"and carries nofallbackStep/family-exhausted/providerCascade. Guidance: alert on any other non-locked-family row; allow this planner row. - The tool-loop decision call is
utility-class on its own seam, not the synthesize seam (singleton-per-call-class, D-72). Five pages carried the prior claim that the synthesizer node and the tool-loopllmDecisionnode share oneProviderSeam<"synthesize">identity (the old "D-35" statement). The tool-loop continuation decision — "call another tool or finish?" — now runs on a dedicatedutilityseam, so the synthesize cap is structural: the synthesizer (and the recovery path) are the only consumers of the synthesize seam, and the decision node can't reach theTurnSynthesizeCounter. Corrected in Seams (the singleton section + the LangGraph callout'sProviderSeam<"utility">type), Graph, Graph node catalog (thellmDecisionrow'sacceptsSeamconverse→utility, the Stage 2 intro, and the singleton-invariant wire-check), Call classes (theutilityrow + section now name the tool-loop decision as the canonical utility call), and Multi-synthesize. A reader on the old "shared seam" model would have mis-predicted which node bumps the synthesize counter. - Graph lattice docs synced to the current
@pleach/coretopology across eight pages. TheNODE_STAGE_MAPregistry is 43 names, not 48.ALLOWED_EDGE_PATTERNScarries nine rows andFORBIDDEN_EDGE_PATTERNSseven, not eight/eight — thetool-loop → post-turnrecovery-dispatch edge moved from the forbidden table into the allowed table. Recovery shaping is no longer foursynthesize-stage graph nodes (recovery,refusalHint,retryNarration,garbleRecovery) plus arecoveryDispatchPredicatederivation node and ashouldContinueWithGarbleRoutewrapper; it is four post-turn stream filters (refusalHintFilter100,retryNarrationFilter200,garbleRecoveryFilter300,standardRecoveryFilter400) dispatched viaStreamObserverRegistryand locked byaudit:recovery-dispatch-single-surface.synthesizeis now a true singleton — onlysynthesizer. Touched Graph, Node catalog, Edge catalog, Nodes, Architecture, Ownership boundaries, Plugin contract, and Audit gates. Node catalog also gains a "How the substrate source is organized" section documenting thesrc/graph/layout (nodes/one-file-per-node,wiring/registrars split by stage, thetopology.tslattice layer, concern-splitseams//predicates//strategies/), with upstream-contributor steps pointing at thewiring/register<Stage>Nodes.tsregistrar. - Config manifest foreign key corrected in
Config manifest. The
harness_event_log.manifest_hashreference is a real foreign key withON DELETE SET NULLand a load-bearingDEFERRABLE INITIALLY DEFERREDclause, not gate-only as the page previously claimed. Added thereference_countcolumn to the table DDL and cited theaudit:config-manifest-fk-constraint-appliedandaudit:config-manifest-referential-integritygates. - Schema description for
@pleach/coreamended to name the language-agnostic contract. Thedescriptionfield in the site's Organization + SoftwareApplication JSON-LD graph (inlined in<head>on every page) previously described@pleach/coreonly in TypeScript terms, contradicting both the marketing surface 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. - Cross-docs status-flip pass — rolling correction across
~55 docs pages tracking the alpha-ship of
@pleach/compliance,@pleach/gateway, and@pleach/replay. Touched pages include Audit ledger, Event log, Subpath exports, Seams, Prompts, Prompt builder, and Session runtime.
Fixed
- Family-lock lifetime claim corrected — the
page stated "switching family means a new session." The runtime
ships a sanctioned in-session re-lock path (
sessions.updateProviderModel, emitting asession-lock-resyncedevent), so switching family is an explicit operation, not a new-session requirement. The lock's real invariant is no silent mid-turn widen, not lifetime immutability. - AuditableCall row
AuditRecordVersioncorrected 13 → 14 — both the literal description and the version-log range (v8 through v14) now match the upstreamAUDIT_RECORD_VERSION_HISTORY, whose latest entry isto: 14(Cluster C: additiverewriteStatus?+tokenCost.callClass).
2026-06-08 — chat-pipeline lift into @pleach/core
Foundational lift bringing OrchestratorClient and
streamSingleTurn into the substrate. See the Unreleased section
above for the Added/Changed entries. The Pre-Merge Gate
audit:domain-string-purity landed alongside.
2026-06-08
Added
- New page Runtime inspector documenting
inspectRuntime()from@pleach/core/inspector— the typed read-only introspection surface, theInspectionReport/CapabilityReport/PluginReport/CapabilityDescriptorshapes, and the 38 known capabilities (29 modern + 9 deprecated). definePleachPlugin()factory section in Plugin contract covering the 8-keyPluginCapabilitiescluster and the_rawescape hatch.contributeFabricationGuardsection documenting the typedFabricationGuardImplhook (7 methods) that retires theorchestratorHotpath.fabricationGuarduntyped-bag entry.CreatePleachRuntimeConfig.host.{strategies, modules, raw}section in Host adapter with the 15-keyHostExtensionBundlelist and thehost.moduleslist (eventLogWriter,store,interrupt).- 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). @pleach/core/inspectorrow in Subpath exports.
Changed
- Packages table corrected to real published
version —
@pleach/core 1.1.0(was largely stale "Reserved · placeholder" framing).
Fixed
- Runtime inspector — replaced fictional
RuntimeInspection/CapabilityStatetypes with the realInspectionReport/CapabilityReport/PluginReport/CapabilityDescriptor. Corrected thestatusdiscriminator to"wired" | "deprecated-wired" | "unwired". - Plugin contract —
definePleachPlugincapability fields take values, not thunks. Corrected to the real 8 capability keys (prompts,runtimeAwarePrompts,safetyPolicies,fabricationDetectors,tools,streamObservers,intentToolMap,toolCouplingHints). - Host adapter —
host.modulescorrected to{ eventLogWriter, store, interrupt }.host.strategiespopulated with the real 15-keyHostExtensionBundlelist. - Tamper-evident hash chain — subpath corrected
from
@pleach/core/event-logto@pleach/core/eventLog(camelCase is the real export). - Event-log projections — subpath
corrected from
@pleach/core/event-log/projectionsto@pleach/core/eventLog(projections export from the./eventLogbarrel; there is no/projectionssubpath).
@pleach/compliance changelog
Release history for @pleach/compliance — site-docs entries that materially touched the @pleach/compliance surface, newest-first. Canonical runtime history lives upstream.
@pleach/eval changelog
Release history for @pleach/eval — site-docs entries that materially touched the @pleach/eval surface, newest-first. Canonical runtime history lives upstream.