CR-loop final polish (non-behavioral):
- tsdown-exports.test.ts: the "maps over fallback-array targets" case left an
unspied console.warn (b.mjs has no adjacent declaration) leaking to stderr.
Wrap it in withWarnSpy and assert the warning fired — the declaration-less
element is reported, not silently dropped.
- tsdown-exports.d.mts / validate-package-exports-types.ts: cross-reference the
two hand-mirrored ExportsEntry definitions so they cannot drift silently.
No source behavior change; 36 tests pass, validate:exports exits 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CR-loop confirmation-round #4 findings:
- validator: `resolvesForMode` (renamed from `typesCoversMode`) now applies to
EVERY condition, not just `types`. A partial object under `node`/`default`
(active in both modes) no longer silently covers the mode it lacks —
resolution falls through to the sibling, catching the untyped-JS #3324 shape
there. This completes the per-mode model.
- helper: `withTypesConditions` throws on a non-object `exports` (bare string /
array) instead of iterating it into a corrupt map; `typedTarget` now warns
loudly when a JS target has no adjacent declaration (was silent, contradicting
the helper's own fail-loud contract); idempotency skips only the helper's own
`{ types: <string>, ... }` output, so a hand-authored types-first PARTIAL
object is normalized (its untyped sibling gets a `types`). UMD / `.d.mts` docs
corrected; `ctx.pkg: unknown` documented as intentional (weak-type constraint).
- tests: node/default partial fall-through regression; types-first-partial
normalization; a helper->validator round-trip; a console.warn assertion for
the missing-declaration path; split the untouched-target test into silent
(non-JS) and warning (JS) cases.
- react-native: dropped a pre-existing duplicate `@ag-ui/client` external.
Call sites: resolvesForMode (internal, walk + recursion; grep-confirmed no
`typesCoversMode` refs); withTypesConditions signature unchanged, and the new
throw/warn never fire on tsdown's real input (object map, packageJsonPath
present, dts:true).
36 tests pass; validator typechecks; validate:exports exits 0; native-loader
builds of react-core + react-native unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CR-loop confirmation-round #3 findings:
- validator: a `types` condition now "wins" a resolution mode only when it
actually covers that mode (new `typesCoversMode`). A partial object `types`
(e.g. only `import`) no longer silently covers `require` — resolution falls
through to the sibling, catching a real #3324 shape the checker previously
missed. normalizeExports doc + a "read or parse" message tidied.
- helper: idempotency now keys on the FIRST condition being `types` (its own
output shape) rather than mere presence, so a hand-authored `types`-last
entry is normalized instead of passed through — keeping helper output
consistent with what the validator accepts. JSDoc corrected (acts on every
condition target, requires a subpath map, only ADDS a missing `types`).
- tests: made the runtime-only test discriminating (a `browser`-only target
must not be flagged — the prior fixture couldn't catch a regression);
exercised `node`; added partial/well-formed object-`types`, top-level
fallback array, and types-last normalization cases.
Call sites: typesCoversMode (new internal, called by walk); walk/withTypes
signatures unchanged; isActiveCondition now also used by typesCoversMode.
32 tests pass; validator typechecks; real 25-package validate:exports exits 0;
native-loader react-core build unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CR-loop confirmation-round findings on the #3324 guard:
- validator: replace the single-`typesIndex` model with per-mode resolution.
import- and require-mode resolve independently (each picks the first present
of {types, <mode>, node, default} in object order), so a trailing
`default`/`node` shadowed by a typed `import` + `require` is no longer a false
positive, while a genuinely misordered/absent `types` is still flagged.
- helper: make `withTypesConditions` idempotent (skip an object that already
carries a `types` key, so re-application never re-nests `default`) and
optional-chain `ctx` so a missing context hits the fail-loud message.
- CI: run scripts/__tests__/tsdown-exports.test.ts in the guard workflow (the
helper is the mechanism that injects the types conditions, and its test ran
in NO workflow) and add it to the trigger `paths`; note the standalone gate
validates committed artifacts, not build output.
- tests: assert `types` is emitted FIRST via serialization (toEqual is
key-order-insensitive and missed a types-last regression); add idempotency and
trailing-default regression cases.
- react-native: document why its exports map is hand-maintained (no tsdown
`exports` hook) and guarded by validate:exports.
Call sites enumerated:
- walk / findExportsTypeViolations — internal to the validator + its tests;
signatures unchanged. JS_CONDITIONS removed (grep-confirmed no refs); replaced
by RESOLUTION_MODES + isActiveCondition.
- withTypesConditions — 13 tsdown configs via customExports; signature
unchanged, tsdown always supplies ctx.pkg.packageJsonPath and never re-applies
or emits null/array, so the new guards never fire on current input.
28 tests pass; validator typechecks; real 25-package validate:exports exits 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CR-loop findings on the #3324 regression guard:
- validator: normalize bare-string and conditions-only `exports` sugar to the
"." subpath (previously a false negative / false positive); flag a `types`
condition shadowed by an earlier import/require/node/default — a misordered
`types` is the exact #3324 failure a strict resolver hits; recurse into
object-valued `types`; ignore runtime-only conditions (browser/deno/...) so a
typed import/require sibling is not falsely flagged; attach the file path and
`cause` when a package.json fails to parse.
- helper: guard `null` (blocked subpath) and array (fallback) targets — the old
code crashed on null and corrupted arrays into objects; fail loud if
`packageJsonPath` is missing rather than silently emitting a types-less map.
- tests: hermetic fixture coverage for package discovery/filtering + the new
exports shapes, and a new tsdown-exports.test.ts covering the previously
untested `withTypesConditions` helper.
Call sites enumerated:
- withTypesConditions — 13 tsdown configs via customExports. tsdown always
supplies packageJsonPath and generates no null/array targets, so the new
throw/guards never fire on current input (verified: native-loader build of
react-core unchanged, exports byte-identical).
- findExportsTypeViolations / validateAllPackages — signature unchanged;
callers are the validator CLI and the tests. Real 25-package
`validate:exports` still exits 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Under moduleResolution bundler/node16/nodenext, TypeScript ignores the
top-level "types" field once an "exports" map exists, so strict-exports
tooling (e.g. the Backstage CLI) resolves no type declarations and reports
every named export as "has no exported member". tsdown does not emit a
types condition in the exports map it generates.
Add one — first, per import/require, ESM to .d.mts and CJS to .d.cts — via
a shared withTypesConditions helper (scripts/tsdown-exports.ts) wired into
each tsdown config, and directly in the hand-maintained react-native map.
Add a regression guard, since attw and publint do NOT catch this (TS's
adjacent-file fallback masks it): scripts/validate-package-exports-types.ts,
unit + all-package tests, a validate:exports npm script, and a CI workflow
that fail if any publishable package's exports map lacks a types condition.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Summary
- remove the retired top-level `docs/` Next app and the disabled
docs-sync workflow/script
- add `docs -> showcase/shell-docs` as a top-level symlink for `cd docs`
muscle memory without restoring the old docs tree
- move the docs model allowlist into `showcase/shell-docs/` and retarget
docs validation/doctest extraction to shell-docs content
- update docs/agent guidance and CI path filters so `docs/` is treated
as an alias, not an active separate docs surface
- tighten the pre-commit package check so non-package docs/tooling
changes do not fan out into the full package matrix
## Validation
- `pnpm exec tsx scripts/validate-doc-model-names.ts`
- `pnpm exec tsx scripts/doc-tests/extract.ts`
- `pnpm exec vitest run
scripts/__tests__/validate-doc-model-names.test.ts
scripts/doc-tests/__tests__/extract.test.ts
showcase/harness/src/cli/eval/scope.test.ts`
- `pnpm exec oxlint showcase/harness/src/cli/eval/scope.test.ts
scripts/doc-tests/extract.ts`
- `git diff --cached --check` before follow-up commit
- `test "$(readlink docs)" = "showcase/shell-docs"`
- `test -f docs/package.json`
- `pnpm exec oxfmt --check .claude/docs/documentation.md
.claude/docs/hooks.md AGENTS.md CLAUDE.md CONTRIBUTING.md
showcase/shell-docs/README.md`
- commit hooks passed
## Notes
- historical docs remain recoverable from
`archive/docs-save-do-not-prune` and `archive/docs-retired-2026-06-17`
- I intentionally left Vercel/project teardown out of this PR; this is
repo cleanup only
The plugin version pins to packages/runtime/package.json, but plugin.json
(1.60.0) and marketplace.json (plugins[0] 1.60.0, metadata 1.57.3) had
rotted behind the runtime package (1.60.2), so check:plugin-skills was
failing on main.
handleVersionSync previously managed only plugin.json.version and
marketplace plugins[0].version, leaving marketplace metadata.version
unmanaged and free to drift independently. Extend it to track
metadata.version against the runtime version too, and re-run the sync to
bring all three fields to 1.60.2.
Conflict resolutions:
- contract test: keep the rollout's parameterized version and add
strands-python to migratedIntegrations/appRoots (60/60 passing) in
place of her bespoke MIGRATED_INSTANCES file
- parity manifest: rollout's version with strands' three threads-shield
allowances removed (mirrors the langgraph-fastapi migration); parity
verify green — strands now 88 tracked files, zero drift
- package-lock: regenerated at 1.59.3 (a2ui-renderer stays 1.56.5,
the family-wide pin shared with the north-star)
Also rides: her react-core A2UIMessageRenderer test flake fix
(act -> waitFor), kept intentionally.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Conflict resolution: take the rollout's contract test and append the
agentcore describe block (CDK lambda runtime gate, Vite frontend with
import.meta.env gate, docker env wiring). Bump both agentcore
package.jsons 1.59.1 -> 1.59.3 + regen lockfiles. 54/54.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Conflict resolution: take the rollout's parameterized contract test and
append the a2a-a2ui bespoke tests (namespaced helper, 1.59.3 pins).
Bump a2a-a2ui @copilotkit/* 1.59.1 -> 1.59.3 + regen lockfile. 49/49.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- bump a2a-middleware, mcp-apps, agent-spec from 1.59.1 (their verified
pre-revert state) to 1.59.3 to match the starters
- regenerate package-lock.json for the 11 examples whose package.json
changed (drawer deps re-added on starters, version bumps on the three)
- update the migration contract test's version assertions to 1.59.3
(43/43 passing); oxfmt pass
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Restores #5151 (north-star + batch 1 + crewai-flows + llamaindex),
#5196 (pydantic-ai), #5205 (a2a-middleware), #5211 (mcp-apps), reconciled
onto the current main baseline rather than the pre-revert tree:
- keep main's 1.59.3 pins, AGENT_URL normalization, default agent keys,
useConfigureSuggestions, available:false, useRenderTool
status/parameters API, call-time agent.state reads, and crewai-crews'
rebuilt page (not yet threads-migrated)
- graft the threads layer (drawer/gate/provider, env-gated route
intelligence block, next.config gate, env docs, drawer deps) on top
- drop threads-era sidebar suggestions props where main now registers
suggestions via useConfigureSuggestions (or omits them)
- fix the stale pydantic-ai doc link main reintroduced in ms-af-dotnet
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Post-merge fix: add the missing examples/integrations/mcp-apps/.env.example
(+ .gitignore negation, crewai-flows precedent) — the contract test
'mcp-apps documents the local Intelligence environment' was failing
because the file was never added. 37/37 passing on the merged tree.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Conflict resolution: take main's 4-entry migratedIntegrations array and
keep the a2a-middleware-specific contract tests + helper (a2a-middleware
uses app/ root + custom chat, so it doesn't fit the parameterized
src/app contract). 31/31 passing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Conflict + post-merge resolutions:
- integration test (add/add): fold into the parameterized batch-2 contract
test; migratedIntegrations now includes langgraph-fastapi (24/24 pass).
- _parity/manifest.json: keep her langgraph-fastapi allowance removals
(threads-drawer/page.tsx/next.config now fully tracked), but drop the
stale strands-python shielding her branch added (example-layout +
docker-route-override divergence, @copilotkit 1.56.5 packageJsonOverrides)
— strands is already parity-synced at 1.59.1 on main; those overrides
would have made the next parity:sync rewrite it back to 1.56.5.
- parity verify on the merged tree: langgraph-js 82 ok / langgraph-fastapi
91 ok / strands-python 83 ok, zero drift.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Conflict resolutions:
- page.tsx: keep the threads layout; swap the dead v1 sidebar labels
(title/initial) for the v2 keys (modalHeaderTitle 'Popup Assistant' +
welcomeMessageText) the starter smoke asserts, and carry over main's
disableSystemMessage + clickOutsideToClose. Keep her useRenderTool
render({ parameters }) — that is the actual v2 RenderToolProps shape;
main's render({ args }) was a latent runtime bug (args is not a prop).
- package.json: keep the drawer UI deps (class-variance-authority, clsx).
- integration test: fold into the parameterized batch-2 contract test;
migratedIntegrations now crewai-flows + llamaindex + pydantic-ai (18/18).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Conflict resolutions:
- page.tsx: keep the threads layout (drawer + gate + provider) and restore
the v2 sidebar labels (modalHeaderTitle 'Popup Assistant' +
welcomeMessageText) the starter smoke asserts, plus clickOutsideToClose.
- layout.tsx: keep the REST-transport explainer comment.
- integration test: keep the parameterized batch-2 contract test from
crewai-flows and add llamaindex to migratedIntegrations (12/12 pass).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reverts the 14 other framework bumps and 2 lockfile regens. Each
framework needs per-framework QA against 1.56.4 before being shipped
in a sweep — too risky for the demo timeline to bump them all at once.
The validator now uses an explicit ENFORCED allowlist (currently just
adk) with an inline comment documenting the scope decision. Other
integrations get added to ENFORCED as QA clears each framework. The
structural fix (release-please automation that bumps integrations in
lockstep on each release) is tracked in CPK-7534.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The CLI scaffolder (npx copilotkit create -f <fw>) clones from
examples/integrations/<fw>/ on main. The @copilotkit/* deps in those
package.json files are bumped manually on release; 14 of 17 integrations
fell behind. Notable: ADK pinned 1.55.2 (missing useFrontendTool), mcp-apps
at 1.52.1, a2a-middleware floating on "latest". Issue #4253.
Adds scripts/validate-integration-pins.ts + a vitest live-tree check that
fails when any integration pins lag the monorepo release version, so the
gap can't reopen silently on the next release.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Allowlist-based CI lint that extracts model names from docs MDX code
blocks and validates against docs/model-allowlist.json. Catches stale
model references (gpt-5.2 after gpt-5.4 ships) before they reach users.
- Regex extraction from model="...", model: "...", provider/model patterns
- Provider prefix stripping (openai/, anthropic/, google/, etc.)
- 20 unit tests