Releases: robmclarty/fascicle
Releases · robmclarty/fascicle
Release list
v0.9.10
Added
- Bedrock guardrails are documented and pinned by a wire contract test.
provider_options.bedrock.guardrailConfigreaches the top level of the Converse command through a seam@ai-sdk/amazon-bedrockdoes not document: its provider-options schema omits the key, and the request builder rest-spreads unknown keys into the command body, so a peer upgrade that tightens that spread would drop guardrails silently.bedrock_guardrail_wire.test.tsdrives the real peer over a stubbed fetch and asserts the key lands top-level, survives the effort-translation merge, and that aguardrail_intervenedstop surfaces asfinish_reason: 'content_filter'. The bedrock section ofdocs/providers.mdgains the matching recipe. No runtime changes.
v0.9.9
No library behavior changes in this release. Every src/ edit in this range is
a documentation comment, so the published runtime is unchanged from v0.9.8; the
work is in the docs surface, the example apps, and the check suite.
Changed
- The public docs surface is now written for the public.
research/and the internal build trees are untracked, and the adoption and comparison pages are back in sync with the native transports: the AI SDK is the default path for seven of the eight providers rather than the only path, and both pages' AI-SDK-backed versus native counts are corrected. - Every example app now matches docs/blueprint.md.
pr-improve, the canonical reference, moved its four system prompts into markdown files with frontmatter, renamed its schemas tosnake_case, and moved the field-level output rules out of prose and into.describe()on the schemas, where they travel to the model as part of the JSON schema.red-green-refactor,swebench, andamplifypredated the blueprint and were translated: onecreate_enginecall site each, markdown prompts, andstate/stages/servicessplits.amplify's round loop was awhileover mutable parent state driving anensemblewhose score callback populated a captured map; it is nowloop+map+branchover immutable carry-state, withfallbackreplacing a buried try/catch, so the stop rule, the fan-out, and the accept/reject decision are all visible in the trajectory.
Fixed
docs/blueprint.md'sstate.tssnippet did not compile. It declared its scope-state readers overReadonlyMapand called.get(), butuse(keys, fn)handsfna plain object projection of the requested keys. The snippet now shows the real shape, with theReadonlyMapvariant documented for readers that go throughctx.stateinside a step body instead.examples/pr-improvecould not run on its own default provider. It defaulted every role to'sonnet'/'opus'and claimed in comments that the engine expands those per provider. It does not —modelis passed to the provider verbatim — so the documented default path (FASCICLE_PROVIDER=anthropic) sent a literal"sonnet"and got a not-found error. There is now one per-provider model table, resolved once and threaded as data, which also removes a second copy of that table and makes theFASCICLE_MODEL_*overrides reach the flow; they were previously parsed and discarded.
Internal
- The check suite is now checkride 0.6.0, replacing the hand-rolled orchestrator.
scripts/check.mjs,check-links.mjs,check-doc-snippets.mjs, andcheck-publish.mjsare deleted (~960 lines) in favour of built-in slots;scripts/check-deps.mjsstays as the one custom check, since the core/engine dependency invariant is fascicle-specific. Thepnpm check/check:all/check:json/check:bailcontract is unchanged andpnpm check --changedis new. - Existing debt is grandfathered in
checkride.baseline.json(308 diagnostics across lint, struct, dead, dupes, health, spell). The gate ratchets: frozen debt passes, new findings fail. Thedupesandhealthslots are now enforced rather than folded into a single fallow invocation that could not fail on them. - The packaging gate gains
publintand splits the old monolithicpublishstep intopack,smoke, andattw(pinned to theesm-onlyprofile). Doc snippets are typechecked against the built.d.tsas part ofpnpm check:publish, rather than as a separate CI step. - The blueprint is machine-checked on the examples. All six composition apps carry its ast-grep rules, run for every app by a new
examplescheck slot;check:ruleswas previously invoked by no CI job and no slot, and the library's own rules never matched the example apps because theirfiles:globs are anchored at the repo root.vitestnow globsexamples/*/src/**/__tests__, soswebench's andamplify's suites, which had never executed, run in CI: 13 example tests became 51. - Every module-level function in
src/now carries a doc block, enforced byrules/function-comment-required.yml, and the comments are written in the present tense with no design-history references. - Tooling: fallow 3.6.0,
publintadded, and the marketing site dropped from analysis (it reported every file as unused and its DOM handlers as complexity findings).
v0.9.8
Added
define_agentcall-shaping config.DefineAgentConfigacceptsmodelandschema_repair_attempts, closing the gap where the blueprint's "models are threaded as data" rule could not be followed on thefascicle/agentssurface (and where schema repair — set on every model call observed in production consumers — required dropping to a stage factory). Precedence:config.model> frontmattermodel> engine default; the blueprint's stage-factory section now states the same rule.- Two blueprint reference apps translated from production consumers, workspace-wired with stub-engine tests and the blueprint's ast-grep rules:
examples/change-triage/(deterministic detectors + one schema-mode model call, a score floor the model cannot undercut, a privacy screen on the model's view) andexamples/docs-concierge/(grounded Q&A with number-based citations, adefine_agentstage, and a one-way gate that prefers abstaining over confidently wrong).
Changed
docs/blueprint.mdandsite/blueprint.htmlnow state model precedence consistently (threaded model wins, frontmatter is the role default, engine default is the last resort), and the stage-factory snippet no longer implies frontmatter overrides a threaded model.
v0.9.6
Added
docs/blueprint.md: a standard app architecture for building on fascicle — one composition layer, three adoption tiers, markdown prompts, normalized module shapes, stub-engine testing, and field-observed anti-patterns distilled from the example apps and production consumers.- Three ast-grep boundary rules wired into
examples/pr-improve(runnable viacheck:rules):create_engineconfined toengine.ts, no imperative loops inflow.ts, and fascicle value imports confined to the files allowed to know about it.
v0.9.5
Fixed
claude_cliprovider structured output.compile_schemanow strips the top-level$schema(draft-2020-12 URI) and$idkeys thatz.toJSONSchema(zod v4) stamps, whichclaude --json-schemarejects. Anymodel_callon theclaude_cliprovider that passed a zodschemapreviously errored out of the box; structured output now works end-to-end.
v0.9.4
Internal
- Hardened mutation-test coverage for the shared engine orchestration core:
generate.ts(77.6% -> 95.79%) andtool_loop.ts(83.7% -> 94.59%), via new test suites for streaming dispatch, HITL approval, schema repair, cost/finish accounting, and the timeout/retry machinery. - Ratcheted the Stryker break/low thresholds from 83 to 84 (full-repo score now 88.33%); documented the remaining equivalent/unreachable mutants inline with
Stryker disableannotations rather than adding runtime guards.
v0.9.2
Added
- Native provider transport. Model calls now flow through a neutral native provider contract instead of routing exclusively through the AI SDK. This release lands native Anthropic (mapping, streaming, capabilities, auth), a native OpenAI-compatible core that backs
openai,openrouter, andlmstudio, and native Ollama on its/api/chatendpoint. The AI SDK becomes one transport behind the seam rather than the only path, andprovider_optionspass straight through to the native transport. - Open provider registry.
custom_providersonEngineConfiglets callers register their own providers, and the native provider contract is exported from the package barrel so those providers can be built against a stable type. - Loop knobs. Per-turn timeout budgets and a
prepare_stephook give callers control over each step of the tool loop. - OpenTelemetry surface. A trajectory-to-otel bridge plus AI SDK telemetry passthrough emit spans for runs and model calls, with the agent-layer boundary ADR amended to record the seam.
Changed
- Breaking: the
subprocessprovider is renamed toexternal. Update anyprovider: "subprocess"configuration toprovider: "external". - The native provider seam is now the default dispatch path; the AI SDK transport is selected behind it rather than assumed.
Internal
- Mutation coverage hardened across the native providers (
openai_compatible_native,ollama_native), the otel surface, andwith_providersincreate_engine, with the Stryker break gate ratcheted up at the final gate. - Transport parity golden tests plus an OpenRouter live smoke lock the native and AI SDK transports to identical observable behavior.
- The release skill now detects the previous release from the most recent git tag rather than the last
vX.Y.Zcommit message.
v0.9.1
Internal
- Re-pinned every GitHub Actions dependency to its Node 24 runtime major (
actions/checkoutv7,actions/setup-nodev6,pnpm/action-setupv6,actions/cachev6,actions/deploy-pagesv5), clearing GitHub's Node 20 runtime deprecation warning that surfaced on the v0.9.0 publish run. Workflow-only change; the published package is byte-identical to v0.9.0.
v0.9.0
Changed
- Breaking (peer dependencies): AI SDK v7. The
aipeer floor is now^7.0.0with no v6 compatibility window, and every AI SDK provider peer moves to its v7-line major:@ai-sdk/anthropic^4,@ai-sdk/openai^4,@ai-sdk/google^4,@ai-sdk/amazon-bedrock^5,@ai-sdk/openai-compatible^3,@openrouter/ai-sdk-provider^3,ai-sdk-ollama^4. Upgrade the whole set together. Fascicle's own API is unchanged: the v7 renames (systemtoinstructions,fullStreamtostream,experimental_outputtooutput,stepCountIstoisStepCount) land at the SDK boundary only, sogenerate({ system })and friends keep their names. - Usage and cost accounting is verified against v7's nested token-detail shape (
inputTokenDetails/outputTokenDetails, cache-inclusiveinputTokens, reasoning-inclusiveoutputTokens) with concrete-value tests per provider. On@ai-sdk/anthropicv4, cache read and write tokens now fold intoinputTokensupstream, which makes fascicle's cost subtraction formula exact instead of skewed for cache-heavy Anthropic calls.
Fixed
- Streamed
step_finishchunks now carry the same cached-input/cache-write/reasoning usage granularity as the non-streamed step record (default_usage_from_sdkdelegates to the provider usage normalizer). - The
lmstudio(OpenAI-compatible) provider opts into streaming usage (stream_options.include_usage), so streamed calls report real token counts instead of zeros on spec-strict OpenAI-compatible servers such as Ollama's/v1endpoint.
Internal
- Releases are now published from CI with npm Trusted Publishing (OIDC) and a signed provenance attestation, gated by a required-reviewer GitHub Environment (
.github/workflows/publish.yaml). No long-lived npm token exists anywhere; verify a release withnpm audit signatures. This makes v0.9.0 the first provenance-attested fascicle publish (seeresearch/provenance-publish-spec.md). - Agent-layer boundary ADR: fascicle stays on the single-turn seam (
generateText/streamText) and declines the v7 agent layer (ToolLoopAgent,WorkflowAgent,HarnessAgent,toolApproval,@ai-sdk/otel), recorded inresearch/explorations/2026-07-ai-sdk-agent-layer-boundary.mdand linked fromdocs/providers.md. examples/live_smoke.ts: a manual release smoke gate that runs one tool-loop flow streamed and non-streamed against OpenRouter and an OpenAI-compatible backend, checking the tool round trip, stream/record text parity, and usage/cost accounting. Live network, so it stays out of the test suite by design.- Dev toolchain sweep: vitest 4.1.10, oxlint 1.73, oxlint-tsgolint 0.24, tsdown 0.22.3, zod 4.4.3,
@types/node26, fallow 3, and friends.
v0.8.16
Added
fascicle/uisubpath for streaming a run into an AI SDKuseChatUI:to_ui_message_response,pipe_ui_message_stream_to_response, andto_ui_message_chunkstranslate trajectorymodel_chunkevents onto the AI SDK UI message wire. Ships withdocs/human-in-the-loop.mdandexamples/hitl_http.tscovering suspend/confirm/resume over HTTP.
Changed
model_callnow recordsmodel_chunkon the trajectory (viatrajectory.record) instead of routing it throughctx.emit, so consumers see a clean top-levelmodel_chunkevent carrying theStreamChunkrather than one wrapped in a genericemit.
Fixed
- Disabled the AI SDK's built-in retry (
maxRetries: 0) on the generate and stream calls. The engine already owns retry via its retry policy; the SDK's default of 2 nested a second retry loop inside every attempt, inflating provider round-trips and distorting backoff.