Commit Graph

1356 Commits

Author SHA1 Message Date
github-actions[bot] d1a040c9ed Version Packages (beta) (#2688)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
workflow@5.0.0-beta.26
2026-06-28 17:15:25 -07:00
Pranay Prakash 603ad97615 Redrive on transient workflow-server transport failures instead of failing the run (#2445)
* Redrive on transient workflow-server transport failures instead of failing the run

A firewall in front of workflow-server shedding load with sustained 429/503
makes undici's shared RetryAgent exhaust its retries and throw
UND_ERR_REQ_RETRY. That raw error was rethrown unwrapped, so it was
classified as USER_ERROR and the replay terminal branch wrote run_failed —
permanently failing a run on a transient blip (or, in an outage, falling back
to the ~5min queue visibility-timeout redrive).

- world-vercel: map exhausted-retry / socket / connect / DNS / timeout
  failures to a typed WorkflowWorldError (code TRANSPORT/TIMEOUT) by walking
  the fetch() cause chain.
- core: add isRetryableWorldError (429 / 5xx / TRANSPORT / TIMEOUT) and
  rethrow such errors from the replay terminal branch so the queue redrives
  quickly (1s->60s backoff) instead of failing the run. Reuse it in start()
  and step_started handling.
- world-vercel: surface the Vercel firewall x-vercel-mitigated
  (challenge/deny) header alongside x-vercel-id in error diagnostics and logs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Address review: back off + cap on every retry path; fix mock; refine scope

Revises the transport-error handling per PR review (VaguelySerious,
karthikscale3).

Blocking fix — step_started no longer self-enqueues a throttled defer for
transient world errors. Returning `{ type: 'throttled', timeoutSeconds: 1 }`
acked the delivery and enqueued a fresh message, resetting the delivery count
so the path never backed off and never reached MAX_QUEUE_DELIVERIES — an
unbounded flat-1s loop if step_started kept failing. It now throws, so the
error flows through the replay loop's retryable-world-error rethrow and earns
both the delivery-count backoff and the max-delivery cap. Throwing is safe on
step_started (the body hasn't run; a write that landed dedupes to skipped).

Also in this revision:
- Backoff that lasts: raise the queue handler-error retry ceiling 60s -> 900s.
  VQS clamps each redelivery to its 900s SQS limit and adds its own post-32
  exponential, so ramping our base toward 900s stretches survival from ~3.7h to
  most of the 24h message-visibility window. Corrected the stale
  MAX_QUEUE_DELIVERIES comment to match the real VQS schedule.
- Stop amplifying firewall challenges: the undici RetryAgent no longer retries
  429 in-process (a challenge is a 429 the client can't solve). 429s surface
  immediately as ThrottleError carrying x-vercel-mitigated / x-vercel-id, so
  the diagnostic header now reaches us for the challenge case too.
- Track world faults as WORLD_CONTRACT_ERROR (not USER_ERROR) in
  classifyRunError so an outage isn't attributed to user code.
- Fix queue.test.ts mock that `biome check --write` had rewritten from a
  newable `function` into an arrow (broke `new QueueClient`); pin with a
  biome-ignore.

All Vercel-specific logic stays in @workflow/world-vercel; @workflow/core
operates only on the generic WorkflowWorldError abstraction.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Update .changeset/transport-error-redrive.md

Signed-off-by: Peter Wielander <mittgfu@gmail.com>

* Trim changeset to a single sentence per review

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Route firewall-challenge 429s to the retryable transport path, not ThrottleError

A 429 carrying `x-vercel-mitigated: challenge` is a firewall challenge our
server-to-server client cannot solve, so it recurs for the life of the
incident. Mapping it to `ThrottleError` meant the `step_started` write deferred
it as `{ type: 'throttled' }`, which self-enqueues a FRESH queue message and
resets the delivery count — so it never backed off past `retryAfter` and never
reached `MAX_QUEUE_DELIVERIES`, hot-looping against an already-overloaded
firewall (the exact amplification this PR set out to remove, and contrary to
the "step_started can't loop unbounded" invariant, which only held for 5xx).

Map a challenge to a retryable transport `WorkflowWorldError` (`code:
'TRANSPORT'`) in both the v3 `makeRequest` and v4 `throwForErrorResponse`
(the hot event-write path) error mappings, via a shared `isFirewallChallenge429`
helper. It then propagates through the V1/V2 step paths and the replay loop's
retryable-world-error rethrow, earning the delivery-count backoff AND the
delivery cap. A genuine application-level 429 (no `challenge` mitigation) stays
a `ThrottleError` and keeps its `Retry-After`-paced defer.

Also correct the survival-window comments: with the 900s ceiling,
MAX_QUEUE_DELIVERIES=48 spans ~9-10h (~35,000s), not "the better part of 24h";
reaching 24h would need a higher delivery cap, not a higher per-hop ceiling.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: Peter Wielander <mittgfu@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Wielander <mittgfu@gmail.com>
Co-authored-by: Peter Wielander <peter.wielander@vercel.com>
2026-06-28 17:05:03 -07:00
Peter Wielander 2477ad85a7 [core] Gate turbo end-of-run drain writes on the run-ready barrier (#2685) 2026-06-28 16:33:15 -07:00
Pranay Prakash 897aac979f fix(world-vercel): retry idempotent event POSTs in-process to avoid step re-execution (#2675)
* fix(world-vercel): retry idempotent event POSTs in-process to avoid step re-execution

undici's RetryAgent never retries a POST, so a transient transport blip (UND_ERR_REQ_RETRY, ECONNRESET, socket/headers timeout, transient 5xx) when committing a step's terminal event bubbles out, the queue redelivers, and the step's user code re-executes with attempt++ even though it already ran to completion.

workflow-server makes these writes idempotent in outcome: entity handlers run before the event-log row is inserted and state transitions are conditional writes excluding terminal states, so a retry whose original landed throws before any row is written and surfaces as a 409 the SDK already handles. This adds a bounded in-process retry (new event-retry.ts) gated by a validated per-event EVENT_RETRY_ELIGIBILITY map, excluding step_started (double-increments attempt), step_retrying (appends a duplicate row), and hook_received (no server guard).

Complements #2666, which routes completion-persistence failures to queue redelivery instead of recording them as user failures; this avoids the redelivery (and re-execution) for transient blips.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(world-vercel): address review on event-POST retry

- Don't retry external cancellation: drop AbortError from the transient set (keep self-timeout TimeoutError), so a caller-requested abort isn't re-issued or stalled by the backoff budget.

- Add DEBUG-gated logging on each retry and on retry exhaustion so an in-process retry vs. a fall-through to queue redelivery is distinguishable in logs.

- Clarify docs: a landed retry surfaces as 409 for most types, but run_started/attr_set return 200 success (not a 409).

- Add createWorkflowRunEvent integration tests (events-retry.test.ts): eventType is threaded into the retry wrapper, and the 404->HookNotFoundError mapping still fires after the retry loop.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Wielander <mittgfu@gmail.com>
2026-06-28 16:05:23 -07:00
Peter Wielander 1dcdafd422 [world-vercel] Unify HTTP request handling into a shared core (#2631) 2026-06-28 14:59:05 -07:00
github-actions[bot] 4f0fb639cb Version Packages (beta) (#2610) workflow@5.0.0-beta.25 2026-06-27 03:21:47 +00:00
Karthik Kalyan 148d4743e5 Use and show event occurredAt (#2613) 2026-06-26 20:00:30 -07:00
Peter Wielander 59776946a0 [world-local] Retry transport-level queue delivery failures (#2679) 2026-06-27 00:47:48 +00:00
Peter Wielander d5803265d4 [ai] Expose totalUsage and finishReason on DurableAgent stream result (#1863) 2026-06-27 00:23:49 +00:00
Peter Wielander 0f76cec493 [ai] Fix WorkflowChatTransport reconnect test stale after framing normalizer (#2681) 2026-06-26 16:49:52 -07:00
Peter Wielander 096faf0ff6 [ai] Reduce doStreamStep step boundary payload (#1932) 2026-06-26 15:20:37 -07:00
Nathan Colosimo b1802700e4 fix: retry inline completion persistence failures (#2666) 2026-06-26 15:00:42 -07:00
Peter Wielander 8cdfd85914 [ai] Fix "missing text part" stream crash by repairing UI message framing (#2537) 2026-06-26 14:44:08 -07:00
Peter Wielander 7f04d87358 [ci] Fix release "Premature close" by bounding changelog GraphQL batch size (#2669) 2026-06-26 14:42:14 -07:00
Peter Wielander eff215ceec [ai] Drop orphan UI chunks after negative-index reconnect (#2082) 2026-06-26 14:22:29 -07:00
Mitul Shah 8393716687 Fix trace detail panel Input/Output flicker (selection-driven state machine) (#2637)
* Add selection-driven span-detail primitives

Extract the run/step/hook/sleep fetch+hydrate core out of useWorkflowResourceData
into a plain async fetchSpanDetailResource (no React state), and add a
selection-driven state machine in web-shared:

- deriveSpanDetailView / resourceNeedsFetchedDetail: pure view-model deriver
  whose status (idle/loading/ready/error) is a function of (selection, fetched
  detail), so it can never lag the selection.
- useSelectedSpanDetail: fetches a selected span's detail directly with a
  request-token to drop stale/out-of-order responses.

* Drive trace detail panel from the span-detail state machine

Replace the cross-package selection round-trip (EntityDetailPanel useEffect ->
onSpanSelect -> page spanSelection state -> useWorkflowResourceData -> context)
with a single injected fetchSpanDetail capability:

- EntityDetailPanel consumes useSelectedSpanDetail; its loading state now stays
  in phase with the selected span, so Input/Output no longer vanish and pop back
  in while navigating.
- SidebarDataContext drops spanDetailData/Loading/Error + onSpanSelect for a
  single fetchSpanDetail; RunDetailView injects it and drops the duplicate
  spanSelection state.
- WorkflowTraceViewer / RunTraceView take fetchSpanDetail too.

* Test span-detail view-model transitions; add changeset

Cover deriveSpanDetailView (idle/loading/ready/error, stale-detail rejection,
hooks ready inline) and resourceNeedsFetchedDetail.

* Trim redundant/narrative comments in span-detail state machine

Comment-only cleanup: drop PR-narration and cross-file duplication from the
deriveSpanDetailView / useSelectedSpanDetail / EntityDetailPanel / fetchSpanDetail
doc comments, keeping the non-obvious intent (request-token, error scoping,
decrypt closure).

* delete pointless coments

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-06-26 16:42:47 -04:00
Peter Wielander d4e6c5ba34 [world-local] Scope untagged startup recovery to untagged runs (#2667) 2026-06-26 20:37:37 +00:00
Nathan Colosimo 5718df8721 fix(world-postgres): defer loopback worker startup (#2657)
* fix(world-postgres): defer loopback worker startup

* add changeset
2026-06-26 12:04:28 -07:00
Pranay Prakash 92cb05505f docs: deprecate DurableAgent and WorkflowChatTransport, point to AI SDK WorkflowAgent (#2616)
- Add deprecation banners (with migration-guide link) to the DurableAgent and
  WorkflowChatTransport API references in v4 and v5; keep the full API surface intact
- Bring v4 headline guides to parity with v5's WorkflowAgent migration (ai/index,
  foundations/streaming, the cookbook recipe + index)
- Convert standard agent examples (defining-tools, message-queueing) to WorkflowAgent
  and reframe the streamText-vs comparison page
- Banner + repoint the deep recipes that stream custom UIMessageChunk data parts
  (chat-session-modeling, human-in-the-loop, agent-cancellation, serializable-steps) —
  that pattern doesn't map to WorkflowAgent's ModelCallStreamPart model, so their
  legacy DurableAgent examples are kept behind a clear deprecation banner
- Point all WorkflowChatTransport examples at the @ai-sdk/workflow 1:1 port
- Rename the cookbook agent-patterns recipe to WorkflowAgent

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 21:59:45 -07:00
Peter Wielander 7c1e2a2c7e [web] Fix HTTP/2 in bundled server build so observability reads work (#2632) 2026-06-25 17:42:08 -07:00
Peter Wielander 1ea2b4ef77 [core] Fix turbo-mode step-body writes racing run_started (#2629) 2026-06-25 17:41:45 -07:00
Nathan Colosimo 361ce23b0f fix(world-postgres): rename setup command (#2644) 2026-06-25 23:32:50 +00:00
Nathan Colosimo 68d225d510 chore: ignore workflow swc caches (#2640) 2026-06-25 23:02:02 +00:00
Nathan Colosimo aa71766bc9 fix(ai): ignore intentional stream aborts (#2635) 2026-06-25 13:53:26 -07:00
Nathan Colosimo 6f4dd0e716 fix(nitro): reload steps during Vite HMR (#2572)
* test(nitro): reproduce stale steps after HMR

* fix(nitro): reload steps during Vite HMR
2026-06-25 20:37:51 +00:00
Karthik Kalyan 48e6bbfcc3 [world] Make @workflow/world own its Zod dependency (#2622)
* Make world own zod dependency

* Relax zod catalog range
2026-06-24 21:46:51 -07:00
Mitul Shah 8c12132d73 feat(web-shared): extend cn with custom tailwind-merge class groups (#2619)
Move cn to its own lib/cn module that teaches tailwind-merge about the
design-system text-heading/text-label/text-copy/text-button/material
utilities, and import it directly from lib/cn.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-06-25 03:02:04 +00:00
Peter Wielander a1cbc8b776 [world-vercel] Enable HTTP/2 for the events API and stream writes (#2573) 2026-06-24 18:19:52 +00:00
Mitul Shah a9a1d99177 Remove shadow from off-screen marker indicator button (#2614)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-06-24 11:00:19 -07:00
JJ Kasper 55e211086d Fix discovery of dotted JS workflow imports (#2594) 2026-06-23 18:25:05 -07:00
github-actions[bot] 99444d69e8 Version Packages (beta) (#2597)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
workflow@5.0.0-beta.24
2026-06-23 18:23:01 -07:00
Karthik Kalyan b9a10d87e1 Thread occurredAt into web-shared entities (#2608) 2026-06-23 17:47:40 -07:00
Pranay Prakash 3859d338e3 Propagate trace context to vercel-workflow.com in workbench instrumentation (#2601)
* Propagate trace context to vercel-workflow.com in workbench instrumentation

@vercel/otel only propagates W3C trace context to Vercel deployment URLs
by default, so outgoing requests to the workflow-server
(vercel-workflow.com) got a client span with no `traceparent` header —
breaking the APM trace link to workflow-server's spans. Add
`instrumentationConfig.fetch.propagateContextUrls` for the workflow-server
domain in every workbench that uses @vercel/otel: example,
nextjs-turbopack, nextjs-webpack, and sveltekit. The Next.js and SvelteKit
apps already declared @vercel/otel but weren't registering it at all; they
now do.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Also propagate trace context to the Vercel Queue Service (vercel-queue.com)

The workflow-server queue path (@vercel/queue) sends to regional
vercel-queue.com subdomains (e.g. iad1.vercel-queue.com) when not using the
queues proxy, which were missing a `traceparent` header for the same reason
as vercel-workflow.com. Add `/vercel-queue\.com/` to propagateContextUrls in
all four workbench instrumentation configs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 16:13:55 -07:00
JJ Kasper 3fd4cc5f3a Reduce workflow build log noise (#2565)
* Reduce workflow build log noise

* Label subsequent workflow builds as rebuilds

* apply suggestions from review
2026-06-23 21:59:40 +00:00
github-actions[bot] 3017546e9f Version Packages (beta) (#2596)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
workflow@5.0.0-beta.23
2026-06-23 14:38:10 -07:00
Mitul Shah 5a57547512 Use text-gray-900 for trace shortcut helper text (#2595)
* Use text-gray-900 for trace shortcut helper text

Co-authored-by: Mitul Shah <mitulxshah@gmail.com>

* Add changeset for trace shortcut helper text color

Co-authored-by: Mitul Shah <mitulxshah@gmail.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-06-23 21:35:07 +00:00
Karthik Kalyan 2bf5257f97 Trace /flow route initialization (#2592)
* Trace flow route initialization

* Add flow route module timing markers

* Address flow route tracing review feedback
2026-06-23 14:28:24 -07:00
github-actions[bot] 73ee3eb085 Version Packages (beta) (#2591)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
workflow@5.0.0-beta.22
2026-06-23 13:41:20 -07:00
Mitul Shah 685528259d feat(web): add trace step shortcut helper (#2582)
* feat(web): add trace step shortcut helper

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(web): compact trace shortcut helper

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(web): reuse kbd for shortcut helper

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(web): add kbd variants

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(web): animate shortcut helper copy

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): smooth shortcut helper transition

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): space shortcut helper keys

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): polish shortcut helper animation

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(web): move shortcut helper into trace viewer

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(web-shared): extract trace shortcut helper into own module

Move the rotating shortcut helper out of trace-viewer.tsx into a
dedicated component with a CSS-driven crossfade, center it over the
whole viewer, and always rotate both hints.

Co-authored-by: Cursor <cursoragent@cursor.com>

* ship

* deslop

* Update trace step shortcut helper text

Add helper text to indicate keyboard shortcuts for trace step.

Signed-off-by: Mitul Shah <mitulxshah@gmail.com>

---------

Signed-off-by: Mitul Shah <mitulxshah@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 19:45:39 +00:00
Mitul Shah 6512d38df5 [web-shared] reskin json viewer (no duplicates, better colours and navigation) (#2434)
* fix(web-shared): stop data inspector duplicating expanded objects

Expanded objects/arrays now render bracket delimiters ({ … } / [ … ])
instead of repeating the inline preview alongside the child tree.

Co-authored-by: Cursor <cursoragent@cursor.com>

* nice

* fix: sync lockfile after dropping react-inspector

The react-inspector removal landed in package.json but the lockfile was
reverted during cleanup, breaking frozen-lockfile installs in CI.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web-shared): keep data inspector colors theme-aware

Drop the dark-mode color overrides (and the data-theme/useDarkMode
wiring) and rely on the theme-aware --ds-* tokens, matching front:
strings stay green in both light and dark instead of turning blue.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(web-shared): add data inspector tests; tidy comments

Cover collapseRefs ref/typed-array/Map/Set handling and the rendered
tree (keys, value colors, brackets, commas, collapse/expand, empties,
dates, class/Map/Set prefixes) via jsdom + testing-library.

Co-authored-by: Cursor <cursoragent@cursor.com>

* revert(web-shared): drop data inspector tests

Remove the test suite and its jsdom/@testing-library devDependencies to
avoid adding new packages. Keeps the data inspector code unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(web-shared): extract data inspector styles to a sibling module

Move the class-name map and CSS string out of the component into
data-inspector.styles.ts for readability. Still injected via the
hoistable <style>; no behavior or dependency change.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web-shared): restore ARIA tree semantics for the data inspector

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web-shared): render RegExp values as /source/flags

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(web-shared): add unit tests for CopyableDataBlock JSON viewer (#2584)

Export serializeForClipboard and cover its clipboard formatting (strings, primitives, pretty-printed JSON, circular/BigInt fallbacks) plus CopyableDataBlock/EncryptedDataBlock rendering.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 14:54:15 -04:00
Karthik Kalyan 25c3df74f8 Send occurredAt with workflow events (#2580)
* Send occurredAt with workflow events

* Fix occurredAt detail typing
2026-06-23 11:50:38 -07:00
christopherkindl 04ee1ce31d docs: use actual eve logo and tidy OSS nav dropdown (#2586)
Swap the text-based eve placeholder for the real eve wordmark (hard-copied
SVG from @vercel/geistcn-assets, themed via currentColor) and drop Streamdown
so AI Elements is last.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Pranay Prakash <pranay.gp@gmail.com>
2026-06-23 11:31:34 -07:00
Karthik Kalyan 0964b831d3 Display occurredAt in trace details (#2581) 2026-06-23 10:48:57 -07:00
Nathan Colosimo 332c63ce3c fix(next): discover root entrypoints (#2564) 2026-06-22 23:31:12 +00:00
Peter Wielander d108ba32a7 [core] Turbo: skip the unused run_started event-log preload (#2569) 2026-06-22 15:53:00 -07:00
Nathan Colosimo 22b2728394 fix(next): prewarm SWC plugin cache (#2538) 2026-06-22 15:27:49 -07:00
Peter Wielander d476d7aaf6 [world-vercel] Use v3 stream endpoint (supports transparent reconnect on timeout) (#2424) 2026-06-22 15:18:03 -07:00
Peter Wielander cfafdddd79 [core] Retry stream reopen against the reconnect budget (#2334) 2026-06-22 21:52:28 +00:00
Marco 2bb4164c9c Add Platformatic World to worlds-manifest.json (#1450)
* Add Platformatic World to worlds-manifest.json

Signed-off-by: marcopiraccini <marco.piraccini@gmail.com>

* ci fixup

Signed-off-by: marcopiraccini <marco.piraccini@gmail.com>

* ci: pin platformatic world image to 0.8.1 and harden community-world runner

Signed-off-by: marcopiraccini <marco.piraccini@gmail.com>

* platforamtic-world version

Signed-off-by: marcopiraccini <marco.piraccini@gmail.com>

* ci: wire generic docker service-type into community benchmark workflow

The shared community-worlds matrix now emits service-type "docker" for any
world with non-builtin or multiple services (e.g. Platformatic, which needs
postgres + the platformatic/workflow image). tests.yml's e2e-community path
already handles it, but benchmarks.yml's benchmark-community path
(label-gated, non-blocking) did not — so a "community-benchmarks" run would
start no services and fail.

Mirror the e2e "Start Docker services" step, package-version pin, and docker
cleanup into benchmark-community-world.yml, and pass `services`/`version`
through from benchmarks.yml.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Signed-off-by: marcopiraccini <marco.piraccini@gmail.com>
Co-authored-by: Pranay Prakash <pranay.gp@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 14:39:11 -07:00
Pranay Prakash 6fad87b2a4 docs: derive section landing-page cards from the page tree + lint drift (#2567)
Section index card grids (e.g. foundations) were hand-written and drifted
from the sidebar (meta.json) and the actual pages. Make them derive from
the fumadocs page tree (single source of truth) and add CI lint so the
card grid and navigation can't fall out of sync again.

- resolveSectionChildren + <AutoCards/>, bound in both v4 and v5 docs
  routes (correct /docs vs /v5/docs URL spaces)
- getLLMText expands <AutoCards/> so llms.txt/.md/copy-page keep child links
- manualCards frontmatter opt-out for curated pages (source.config.ts)
- checkSectionCards (card<->nav completeness) + checkMetaEntriesResolve
  (dangling meta entries) in scripts/lint.ts
- convert foundations + errors (drift fixes) and v5 observability to AutoCards
- mark deploying + ai as manualCards (intentionally curated)
- remove dangling meta entries: v4 cancellation (x2), root introduction
  (x2), v4/internal serializable-abort-controller

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 14:37:35 -07:00