Skip to content

Releases

v0.18.0

Choose a tag to compare

@github-actions github-actions released this 03 Nov 08:18
8aa7faf

Effect 4.1.2 runtime compatibility (1230614)

Upgrade the bundled CLI's Effect, TypeSafe AI, and platform runtime to 4.1.2. Programmatic build and audit consumers now require Effect peers compatible with 4.1.2; other library entries and the bundled CLI keep these peers optional. Preserve existing decision-cache keys and validate Effect's image-location answers, including the selected image in their cache identity.

Pull request & contributors

v0.17.1

Choose a tag to compare

@github-actions github-actions released this 26 Oct 22:55
3039a0c

Disallow only the directory of a dynamic route (eb1f905)

A disallowed route group with a dynamic route now yields a directory prefix: /s/$formKey
produces Disallow: /s/ instead of Disallow: /s. The old prefix also blocked /solutions,
/senders, and /sitemap.xml, because robots.txt rules match by prefix. Static pages such as
/signup and alwaysDisallow entries are unchanged. A dynamic route at the site root
(/$slug) in a disallowed group now fails the build, since its prefix would block every path.

pagegraph check has a new structural rule, robots-blocks-sitemap-url. It fails when the
rendered robots.txt disallows a sitemap page, /sitemap.xml, or /llms.txt for User-agent: *
and names the URL and the matching rule. Sites that currently block their own sitemap URLs will
fail the check until the Disallow is narrowed.

Pull request & contributors

v0.17.0

Choose a tag to compare

@github-actions github-actions released this 26 Oct 19:30
55a63f7

Run the CLI on Effect 4.0.6 and Pi 1.0.4 (35147b8)

Breaking: Pi renamed its Azure OpenAI provider from azure-openai-responses to azure. A workflow
model such as azure-openai-responses/gpt-4.1 in workflows.agent.defaultModel,
workflows.agent.models, or --model now fails with Unknown Pi model; write azure/gpt-4.1
instead. AZURE_OPENAI_API_KEY is unchanged.

The CLI now bundles Effect 4.0.6 and Pi 1.0.4. Committed claims answers stay valid, so
pagegraph claims check keeps replaying them without --refresh.

Pull request & contributors

v0.16.0

Choose a tag to compare

@github-actions github-actions released this 17 Oct 06:34
70aaf9b

Use OpenRouter for Jev decisions with Pagegraph attribution (5bc9f14)

Jev now prefers OPENROUTER_API_KEY and falls back to TYPESAFE_API_KEY when no OpenRouter key is set.
OpenRouter decisions and workflow agent calls identify the Pagegraph app for rankings and analytics.
Set openrouter.referer and openrouter.title in pagegraph.config.ts to override the identity.
Existing committed claims answers remain valid when switching providers.

Pull request & contributors

v0.15.1

Choose a tag to compare

@github-actions github-actions released this 10 Oct 18:47
86402c8

Capture Markdown in dev when Vite pre-bundles dependencies (5224b37)

pagegraph() now keeps pagegraph and pagegraph/react out of dependency pre-bundling, next to
the runtime entries. A pre-bundled copy gave pages their own document context and defineFacts
registry, so every dev capture (/__pagegraph/markdown.json, <page>.md, claims check --dev)
failed with recorded no <Section> or Unknown document fact.

Pull request & contributors

v0.15.0

Choose a tag to compare

@github-actions github-actions released this 05 Oct 06:50
43d2dd7

Review improve workflow edits and apply them later (0722ee1)

Improve workflows (content, metadata, schema, links) now submit structured edits instead of
writing files. Each edit names the file, the exact oldText it replaces (or none for a new file),
the newText, a reason, and evidence; reviewItems carry changes a human must make, with their
path, reason, and evidence. PageGraph rejects a submission whose edits do not apply to the current
files, so the agent corrects them in the same turn.

Every improve run writes edits.json and a human-readable review.md to its run directory. Jev
decisions that land in review, including link suggestions, appear there as review items instead of
being dropped.

--dry-run records the edits without changing source files. The new pagegraph apply <run> applies
them later, skipping and reporting any edit whose target text no longer matches; --only <ids>
applies a subset and --check reports without writing. Write mode applies the same recorded edits
during the run.

Breaking: the edit_file and write_file agent tools are removed, along with the action result's
files and outcome fields; run.json reports outcome, edits, and reviewItems for improve
runs. Custom presets that mention those tools should describe structured edits instead.

Pull request & contributors

Resolve and check per-page social images (0674a86)

Declare staticData.seo.head.image: { url, width?, height?, alt? } or a collection entry's
image. Existing article.image remains supported. Share an ogImage(node) resolver between
pagegraph() and createSeo to supply images when a page has no declared image. Page images
win over article images, then the resolver supplies the fallback. Resolved images are absolute
URLs in node.head.image and pageHeads, and render Open Graph image metadata and Twitter
large-image cards.

pagegraph check now fails sitemap-eligible pages without an image or whose same-origin image
asset is missing under public/. Configure ogImage.severity (structural, editorial, or
off) and ogImage.publicDirectory in pagegraph.config.ts. Remote images are not fetched.
Consumers own image rendering and must generate local assets before running the check.

Pull request & contributors

Make agent workflow runs recoverable and bounded (35703a6)

Large executor_execute results are saved in JSON under each run's tool-results/ directory, and
truncated previews tell the agent how to read the full result. Agent presets now guide workflows to
return only needed fields and rows and to read large artifacts in chunks.

workflows.repositoryRoot optionally sets the read boundary for repository tools and context.files.
It defaults to the config directory's Git top level, falling back to the config directory. Context
file paths resolve from this read root, so existing app-relative paths may need a repository-relative
prefix. Writes remain bounded to the application root. Run artifacts under runsDirectory are
readable to support recovery.

Workflow commands accept --from <run-dir|run-id> to resume recorded agent session and research
state while skipping recorded completed calls. Resume verifies that repository HEAD and file
contents still match the checkpoint; completed runs return their recorded output without provider
calls. An action that started without recording completion is refused because replay could repeat
edits. Incomplete runs from before progress checkpoints were recorded cannot be resumed. Missing
model-provider credentials, TYPESAFE_API_KEY, or required Executor configuration are reported
before the first paid model turn.

After three rejected submissions, valid items are retained; rejected items and their indices and
validation reasons are recorded in research.json and run.json.

Pull request & contributors

v0.14.1

Choose a tag to compare

@github-actions github-actions released this 04 Oct 11:41
62d45eb

Show Executor tool types for every search hit (c47b996)

executor_search with details no longer fails when a hit is an MCP-backed tool whose schema has no
TypeScript definitions. A hit whose schema cannot be loaded keeps its search result and reports
types unavailable: <reason>, while the other hits still return their input and result types.

Pull request & contributors

v0.14.0

Choose a tag to compare

@github-actions github-actions released this 04 Oct 09:50
ba21407

Run read-only workflows on Pi (e788a51)

Breaking: Replace workflows.opencode with workflows.agent in pagegraph.config.ts.
Rename configDirectory to presetDirectory; keep defaultModel, optional per-workflow models,
and optional timeoutMs under workflows.agent. Model IDs use provider/id, and Pi reads model
credentials from its provider-specific environment variables. Use --preset-directory in place
of --opencode-config for CLI overrides.

Breaking: Workflow runs, research checkpoints, and failure artifacts use schemaVersion: 2.
Update artifact readers to use agent in place of opencode and inspect agent.runtime:
pi records contain the model, messages, and usage with total cost; opencode records contain
the model, session ID, and transcript.

research.*, analyze.*, and plan.architecture run in-process on Pi 1.0.0. Pi composes the SEO
agent instructions, AGENTS.md, and each workflow's skill and Executor reference from the configured
preset directory. Missing preset files fail with their paths. Repository tools are read-only and
reject paths outside the project root, including symlink escapes. improve.* workflows use OpenCode
with the same preset directory.

Pi submits structured state through submit_result. Acceptance requires valid workflow state,
at least one Executor catalog search, and a completed relevant Executor call. Invalid submissions
receive validation or evidence guidance in the agent loop; three rejected submissions fail the run.
Research declines Executor approval requests and respects the per-run deadline.

Research connects to Executor through @pi-ext/executor: set EXECUTOR_BASE_URL, plus
EXECUTOR_CLIENT_ID[_FILE] and EXECUTOR_CLIENT_SECRET[_FILE] when Cloudflare Access fronts the
server. Only provider calls that succeeded count as evidence.

Pull request & contributors

Run improve workflows on Pi (394dd5b)

Breaking: Every workflow now runs on Pi. Improve workflows continue the research conversation
and apply source changes with guarded edit_file and write_file tools. Dry-run actions expose
only read tools and describe intended changes. Writes stay inside the repository and exclude
.git, node_modules, workflow runs, and agent presets. There is no shell tool.

OpenCode, its SDK install, patched client, preset JSON, and permission rules are removed.
Schema-version-2 artifacts now record agent.runtime as the literal pi.

Breaking: pagegraph init writes .pagegraph/agent. To migrate an existing preset, move
.pagegraph/opencode to .pagegraph/agent, delete opencode.jsonc, and set
workflows.agent.presetDirectory: ".pagegraph/agent" in pagegraph.config.ts.
The preset uses executor_search and executor_execute for live tools and submit_result
for structured workflow results.

improve links can read served target-page sentences with fetch_page, restricted to
suggestion-report origins and subject to robots rules and response size limits.

Together with the Pi research runner, these changes make up release 0.14.0.

Pull request & contributors

v0.13.0

Choose a tag to compare

@github-actions github-actions released this 03 Oct 08:38
62c4855

Capture rendered Markdown through TanStack Start (07e86e3)

Declare staticData.markdown: "rendered" to publish Markdown twins from authored React pages,
with optional staticData.llms groups. Collection instances inherit their route's declarations.
The pagegraph() plugin accepts a canonical Markdown origin and a facts module, and exposes
prerenderPages for Start. The non-deployed pagegraph/tanstack-start/prerender-worker captures
pages through the compiled Start server and writes public twins plus private documents and heads.

Use markdownRequest from pagegraph/tanstack-start/markdown before the Start handler for dev
and prerender capture. Private paths return 404 in production. pagegraph/tanstack-start/react
exports a capture-aware Link; llmsTxt and llmsSection on the server entry compose graph-derived
links without rendering pages. Development rendering catches missing route opt-ins.

Pull request & contributors

Author page documents alongside React markup (ce2a366)

pagegraph/react adds DocumentProvider, T, Title, Section (including Section.Item
and Section.Item.Link), Fact, Visual, ForAgents, and ForHumans. Normal rendering preserves
layout; a collector records authored messages, sections, linked items, resolved facts, and audience
from completed HTML. CaptureAnchor supplies the anchor boundary for router integrations, and
messageText extracts static text for head metadata without executing components.

pagegraph adds plain document types, fact definitions, section kinds, markdown writers, pure
llms.txt string builders, and createMarkdownLock. Content and document hashes preserve the
original authored-document format. Both runtime entries remain Effect-free and Node-free.
Augment the root Register interface with facts: typeof facts to check Fact ids.

pagegraph/oxlint adds the pagegraph plugin's no-bare-text and t-children rules for imports
from pagegraph/react. It is a build-only entry with throwing Worker and browser stubs.

Pull request & contributors

Gate claims and inspect captured Markdown (e3d8643)

Breaking: Rename seo.config.ts to pagegraph.config.ts (also .js and .mjs).
The CLI rejects the old filename with migration guidance. Keep CLI policies and the graph loader
in this file; configure site identity, robots, Markdown, and claims through the Vite plugin.
Remove top-level origin, disallow, contentSignal, and directives from the CLI config.
tanstackStartGraph supplies the plugin's site; a generic viteGraphLoader requires a site
option, and custom graph loaders return site: { origin, indexable, robots } with the graph.

Add claims: { rules, model, cutoff?, context?, excludeHeads? } to pagegraph() with probability
rules built against claimsInput from pagegraph/claims. Run pagegraph claims check to ask for
missing answers, review them, and commit .pagegraph/decisions/claims/. --refresh replaces answers;
--dev <origin> checks live captured documents. Builds and pagegraph check replay committed
answers without model calls and fail on missing answers or violations.

Use pagegraph markdown show <path> to print a twin and pagegraph markdown find <text> to search
pages and sections. pagegraph markdown lock writes .pagegraph/markdown.lock.json;
--check verifies it without writing.

Pull request & contributors

v0.12.0

Choose a tag to compare

@github-actions github-actions released this 02 Oct 22:22
8ffe5e5

Build the graph inside a TanStack Start app with pagegraph() (3281dc5)

pagegraph/tanstack-start adds a Vite plugin that builds the SEO graph in the app's own Vite
pipeline — aliases, defines, and content plugins such as Fumadocs apply — and ships it to the
server runtime as data. robots.txt and sitemap.xml are one line each:

// vite.config.ts
pagegraph({ origin, indexable, robots: { contentSignal }, collections: "src/lib/seo/collections.ts", routeConfig });

// src/routes/robots[.]txt.ts
import { robotsTxt } from "pagegraph/tanstack-start/server";
export const Route = createFileRoute("/robots.txt")({ server: { handlers: { GET: robotsTxt } } });

The plugin evaluates each route file that declares staticData, never the generated route tree, so
a route that imports server-only modules no longer needs a stub; an app-only route that cannot
evaluate in Node fails with its file name and goes in exclude. routeConfig takes the
seoRouteConfig options and adds the derived robots exclusions. tanstackStartGraph({ root })
gives seo.config.ts and loadPageHeads the same graph, and contentCollection maps any pages
with a url (Fumadocs getPages()) to a collection.

Declare a page's head once (3281dc5)

A static route declares its head in staticData.seo.head and renders it with head: seo.head; the
graph, pageHeads, and pagegraph check read the same title, description, and FAQs. A route's
titleTemplate ("%s | Example Blog") applies to the title seoHead renders and to the route's
collection pages. createSeo({ transformHead }) post-processes every rendered head.

Fail loud when a runtime bundle imports build code (3281dc5)

pagegraph/config, pagegraph/vite, pagegraph/audit, and pagegraph/tanstack-start resolve to a
stub under the workerd, worker, and browser export conditions that throws at import with the
entry's name, instead of crashing on a native binding when a request first runs. The README opens
with what runs where.

Keep every workflow failure (3281dc5)

Workflows drop null from model JSON before decoding, give the repair turn every schema issue at
once, and write failure.json with the stage, OpenCode session id, transcript, and cause chain for
every error after a run starts. The error message ends with the artifact path and a next step.

Breaking changes (3281dc5)

  • selectPageHeadNodes, pageHeads, PageHead, and PageHeadsOptions are exported from
    pagegraph, not pagegraph/config. loadPageHeads stays in pagegraph/config.
  • pageHeads reads node.head (a declared staticData.seo.head, or a collection page through its
    route's titleTemplate) instead of node.instance.
  • PageSeoInstance is SeoPageHead and FAQItem is SeoFaq.
  • @tanstack/router-generator is an optional peer: install it with pagegraph/vite or
    pagegraph/tanstack-start.
  • research-failure.json is replaced by failure.json.
  • seo.config.ts disallow is optional; with tanstackStartGraph the robots policy comes from the
    plugin and must not be repeated.

Migrating a TanStack Start app: replace the hand-written graph module and viteGraphLoader with
pagegraph() plus a collections module, move seoRouteConfig options to routeConfig, serve
robots and sitemap with robotsTxt/sitemapXml, move static heads into staticData.seo.head with
head: seo.head, and move hand-appended title suffixes into titleTemplate. The
TanStack Start cookbook
has before/after snippets for each step.

Pull request & contributors