Commit Graph

4305 Commits

Author SHA1 Message Date
Jordan Ritter e32a593758 fix(cvdiag): raw-byte — re-cap head/tail to ≤16KB AFTER scrub (scrub grows bytes) in both branches + recompute elided_count post-scrub (M3 CR R5) 2026-06-19 10:05:59 -07:00
Jordan Ritter 4bd04f9ba4 fix(cvdiag): raw-byte — keep+scrub mislabeled-gzip plaintext (gzip-magic gate, no false drop), scrub full body before head/tail split to redact seam-straddling secrets (M3 CR R4) 2026-06-19 09:56:55 -07:00
Jordan Ritter 3356b90db9 fix(cvdiag): d4 probe — evict timing queue on responseless requests, preserve SSE backfill sequence order, fire probe.exit on abort path (M3 CR R3) 2026-06-19 09:44:50 -07:00
Jordan Ritter 6ca469952c fix(cvdiag): raw-byte — never store unscrubbed compressed body when gunzip throws, fix global-window clock-0 sentinel collision (M3 CR R3) 2026-06-19 09:44:49 -07:00
Jordan Ritter 77c5bedc76 fix(cvdiag): d4 probe data-correctness — per-request timing key, SSE timeout no double-emit, message.send edge-headers after response (M3 CR R1) 2026-06-19 09:29:18 -07:00
Jordan Ritter 760286646d fix(cvdiag): raw-byte decode correctness — code-point head/tail cap (≤16KB), dechunk validates CRLF/hex fail-closed, stripHtml no false dropped-flag, per-slug cap own constant (M3 CR R1) 2026-06-19 09:29:17 -07:00
Jordan Ritter 3308d732e8 fix(cvdiag): collection-gate hardening — 401≠exists (degrade), verify both collections, deny-tests assert CREATE+readback (M2 CR R4) 2026-06-19 09:05:18 -07:00
Jordan Ritter cc5b3ef6ea fix(cvdiag): complete + correct emit→PB wiring — invoke collection-check on both prod paths, typed status, raw-byte correlation test_id, writer-key test fidelity, drop dead queue (M2 CR R3) 2026-06-19 08:47:20 -07:00
Ran Shem Tov 7af24d7171 chore(showcase): label strands integration "AWS Strands (Python)" for TS parity
Now that strands-typescript ships as "AWS Strands (TypeScript)", rename the
existing Python integration's display name from "AWS Strands" to
"AWS Strands (Python)" so the two appear as a matched Python/TypeScript pair
in the docs framework selector and shell (mirrors LangGraph's
"(Python)"/"(TypeScript)" pairing). Slug, content, and behavior are
unchanged. The shared aws-strands docs language tabs already default per
framework (strands -> Python, strands-typescript -> TypeScript) via
TAB_DEFAULTS_BY_SLUG.
2026-06-19 17:45:02 +02:00
Ran Shem Tov 0e5b2189e7 feat(showcase): add strands-typescript integration with base demos
Add a new node/TypeScript-backed AWS Strands showcase integration at
showcase/integrations/strands-typescript.

Backend: a node/TS agent server (src/agent/) built on @strands-agents/sdk
`Agent`/`tool` wrapped in @ag-ui/aws-strands `StrandsAgent` and served via
@ag-ui/aws-strands/server (`createStrandsApp`/`addStrandsExpressEndpoint`),
modeled on the upstream ag-ui aws-strands TS example server and the
langgraph-typescript infra. A single shared agent at "/" serves most demos
(tools, shared state via toolBehaviors/stateContextBuilder, HITL,
sub-agents), with tool-free specialized agents mounted at /voice,
/byoc-hashbrown, /byoc-json-render. model-factory targets OpenAI chat
completions and honors OPENAI_API_KEY / OPENAI_BASE_URL so it works behind
the showcase aimock proxy. Node-based Dockerfile + entrypoint run the agent
server (:8000) alongside the Next.js frontend.

Frontend mirrors the strands (Python) sibling's demo set and the
langgraph-typescript conventions, with HttpAgent routes proxying to the TS
agent server.

Scope: base integration + standard demos only. A2UI / declarative-gen-ui /
a2ui-fixed-schema is intentionally excluded (no A2UI agents, routes, demos,
or deps) and layered on later.

Platform wiring (mirrors langgraph-typescript): docker-compose local/dev
services on host port 3119, local-ports.json, packages.json, slug-map.ts
(born-in-showcase), showcase_build.yml matrix + path filter + metadata,
shell-docs/dashboard registries, and a logo asset. The python strands
integration is untouched.
2026-06-19 17:38:02 +02:00
Jordan Ritter 3468198ba8 fix(showcase): un-fence ms-agent-harness-dotnet probing (#5577)
## Summary
Un-fences the `ms-agent-harness-dotnet` showcase column from per-cell
probe enumeration. The exclude was a placeholder added 2026-06-07
(commit f0edcd5d) before the column existed; the column shipped (PR
#5569) and its d6/d4 aimock fixtures landed today (e10df0b4), so the
fence is stale. Removed the slug from all 8 SSOT exclude sites
(catalog-enumerator.ts nameExcludes, 5 probe YAMLs, aimock-wiring.ts,
baseline-types.ts) + updated 3 stale comments/tests.

## Red-green proof (local, real control-plane surface)
- **RED** (origin/main): `enumerated services: [langgraph-python,
ms-agent-dotnet]` — slug present-in-nameExcludes:true → **0 d6 cells**.
- **GREEN (enumeration)**: after the edits, `enumerated services: [...,
ms-agent-harness-dotnet]` → slug enumerates (via the real
`railwayServicesSource.enumerate` + real `D6_DISCOVERY_FILTER`).
- **GREEN (value-test)**: live local control-plane D6 stack (aimock
fixtures) → **35 passed, 1 failed, 3 skipped, 3 incapable**.
- The single fail (`gen-ui-declarative` / sales-dashboard pie+bar charts
not rendering) is **at parity with the gold-standard sibling**:
PocketBase `d6:ms-agent-dotnet/gen-ui-declarative` is RED with the
byte-identical error (fail_count 92, since 2026-06-15) and is the
sibling's sole tolerated `1✗`. Shared sales-dashboard chart gap in the
ms-agent-dotnet family — not a regression from the AsHarnessAgent port.
Harness lands 35✓/1✗, matching the sibling.

## Test plan
- [ ] CI green
- [ ] After deploy, staging dashboard shows ms-agent-harness-dotnet
cells populating (BE✓, D6 filling) on the next probe tick
2026-06-19 08:37:44 -07:00
Alem Tuzlak f91f5d6968 Merge remote-tracking branch 'origin/main' into feat/bot-whatsapp
# Conflicts:
#	docs/model-allowlist.json
#	docs~origin_main
#	examples/slack/package.json
2026-06-19 17:26:54 +02:00
Jordan Ritter c786bf8846 fix(showcase): un-fence ms-agent-harness-dotnet probing
The ms-agent-harness-dotnet slug was excluded from per-cell D6/BE/smoke
probe enumeration by a placeholder fence added 2026-06-07, before the
real column existed. The column shipped in PR #5569 and its d6/d4 aimock
fixtures landed on main today (e10df0b4), so the fence is now stale.
Remove the slug from all 8 exclude SSOT sites so the column populates.
2026-06-19 08:04:54 -07:00
Jordan Ritter cbb5239b7d fix(cvdiag): wire emit→PocketBase persistence seam (writeBatch + inject pbWriter into production emitters) (cvdiag CR cross-cutting) 2026-06-19 07:56:09 -07:00
Jordan Ritter 7335d58359 fix(showcase): promote pins staging's running digest + verify serving + drift alarm (#5566)
## Summary

Fixes two correctness bugs in the showcase staging→prod promote path
(`showcase/bin/railway`), discovered + live-validated while promoting
the full 19-service cluster.

**Bug #1 — promote pinned the wrong digest.** `resolved_prod_image`
re-resolved the mutable `:latest` tag against *current* GHCR instead of
pinning the digest staging is actually *running*
(`latestDeployment.meta.imageDigest`). When `:latest` drifted after
staging deployed, promote pushed an unvalidated (and once, regressed)
image to prod. Now pins staging's running digest. Adds a loud `⚠️
STAGING DRIFT` warning (promote stdout + `STAGING_DRIFT_MARKER:` →
`promote-fleet.sh` aggregation → both Slack payloads) when staging's
running digest ≠ current `:latest`, so the gap is visible without
blocking the promote.

**Bug #2 — the pin never activated.** `pin_and_verify` used
`serviceInstanceRedeploy`, which replays the *existing* deployment's old
image rather than the just-pinned `source.image`. Config showed the new
digest while prod kept serving the old one (this is why earlier promotes
"succeeded" while prod stayed broken). Switched to
`serviceInstanceDeployV2` + a new `verify_serving_digest!` gate that
polls the new deployment to SUCCESS and **fails loud** if the running
digest ≠ pinned.

Plus CR-round hardening: P2 in-flight race check now reads
`meta.imageDigest` (was dead on tag-form staging) and skips on
`--digest` override; `detect_staging_drift` fails loud (WARN) on
GHCR-resolve failure instead of swallowing; `--digest` override
suppresses spurious drift; `drift_line` LF-stripped at the
`GITHUB_OUTPUT` boundary; multi-service drift join fixed; fallback-log
drift preserved.

## Commits
1. `fix(showcase): pin prod to staging's running digest + loud
staging-drift warning`
2. `fix(showcase): activate prod pin via serviceInstanceDeployV2 +
verify running==pinned`
3. `fix(showcase): harden promote P2 race check + refresh ivar-lint
allowlist`

## Validation
- Live red-green on real Railway: claude-sdk-python prod flipped from
stale → pinned digest via the fixed CLI; all 19 cluster services
promoted green; 5 previously-degraded backends (ag2, llamaindex,
pydantic-ai, ms-agent-python, strands) recovered.
- 15/15 Ruby specs + 15/15 bats green; ruby -c, shellcheck (CI
invocation), actionlint clean.
- 3-round cr-loop (7 agents/round) converged to zero bucket-(a).

## Follow-ups (not in this PR)
- Defensive `.to_s.empty?` on `meta.imageDigest` extraction
(can't-happen on real Railway).
- Test-quality nits (capture_io scoping, weak bats glob, shared mock
fixture).
- Pre-existing verify-prod `succeeded_csv`/`GITHUB_OUTPUT` coupling
(graceful-degraded, audited STAY_IN_C).
- `deploy-to-railway.ts` births prod on `:latest` (the root provisioning
gap); CLI↔workflow notify equivalence (PR2).

## Test plan
- [ ] CI green on PR HEAD
- [ ] (post-merge) a real `gh workflow run showcase_promote.yml` shows
the drift line in the #team-showcase notification when staging is behind
:latest
2026-06-19 07:55:46 -07:00
Alem Tuzlak 59773505eb feat(bot-slack): modernize native streaming (task chunks, feedback, single-message) (#5532)
## What

Brings `@copilotkit/bot-slack` up to the **current** Slack native
streaming API surface (`chat.startStream` / `appendStream` /
`stopStream`, GA Oct 2025; structured chunks + AI feedback elements) and
removes the type-erasure workarounds. Result of an audit
cross-referencing the live `@slack/web-api@7.16.0` /
`@slack/types@2.21.1` types and Vercel's `vercel/chat` Slack adapter.

## Changes

- **No more `as unknown as Parameters<…>` casts** — every
streaming/post/update call uses the SDK's typed args.
- **One streamed message per turn** — dropped the per-message
continuation splitting (Slack documents only a 12k-per-append limit, no
cumulative cap; matches `vercel/chat`), keeping ≤12k per-append
chunking.
- **Native `task_update` tool-progress chunks** (`task_display_mode:
"timeline"`) interleaved into the streamed reply, replacing the separate
`🔧` status messages — with automatic degradation back to
`🔧` rows where structured chunks aren't supported.
- **Opt-in AI feedback buttons** via `slack({ feedback })` — a typed
`context_actions` + `feedback_buttons` row attached at `stopStream`;
clicks are routed adapter-locally (bypassing the engine's interaction
dispatch). No handler ⇒ no buttons.
- **Recipient scoping** — `recipient_user_id` / `recipient_team_id` only
for channel targets.
- **Cadence** — native flush floor lowered to ~600ms (appendStream
Tier-4); legacy `chat.update` stays 800ms.

### Engine (`@copilotkit/bot`)
One small, backward-compatible addition: optional
`RunRenderer.finish?()`, called after `runAgentLoop` resolves, so a
turn-scoped renderer can finalize its single stream. No-op for existing
adapters.

## Verification

- `bot-slack`: type-check (both tsconfigs) clean, **208 tests pass**,
oxfmt + oxlint clean.
- `bot`: type-check clean, **33 tests pass** (incl. a new `finish()`
test).
- Reviewed for correctness (stream lifecycle, finish/interrupt
interaction, delta tracking, degradation) — no high-confidence bugs;
feedback-on-interrupt and missing-ref-logging were tightened.

### Not verifiable without a live workspace (flagged in-code)
- That a >12k reply truly streams into one message (the
no-cumulative-cap assumption).
- `startStream` with no initial content.
2026-06-19 16:50:03 +02:00
Jordan Ritter 61440691f2 fix(showcase): provision prod digest-pinned + image-drift prod-neutral (#5571)
## Summary

Two follow-up fixes that complete the pinned-prod / floating-staging
contract for the showcase fleet (the contract enforced by the promote
CLI in #5566). Prod services must be digest-pinned (`@sha256`), staging
floats `:latest`.

**Fix 1 — `showcase/scripts/deploy-to-railway.ts`: provision prod
digest-pinned, not `:latest`.**
Prod services were being *born* on the mutable `:latest` tag, then later
pinned only at promote time. Now they are born pinned to a resolved
`@sha256` digest at create time, via a new TS GHCR resolver that mirrors
the Ruby promote CLI (`/token` exchange → manifest HEAD →
`Docker-Content-Digest`). Resolution failure is **fail-loud**
(`process.exit(1)`, never a `:latest` fallback). `goLive` asserts the
prod `source.image` is digest-pinned (`assertProdDigestPinned`,
refactored to be dependency-injectable and to throw a typed
`ProdPinError` instead of exiting inline).

**Fix 2 — `showcase/harness/.../image-drift.ts`: stop flagging pinned
prod red.**
Under the pinned-prod contract, prod is intentionally digest-pinned
behind `:latest`, so the image-drift probe was firing false-red on every
prod service. It now renders such prod services **green**
(`pinnedExpected`) while a genuinely missing digest stays **red**.
Staging behaviour is unchanged.

## Verification

- **Red-green proven locally** for both new test surfaces:
- `assertProdDigestPinned` guard: RED = 5 tests `assertProdDigestPinned
is not a function` (untestable inline-exit) → GREEN = 13 passed after DI
refactor; env-mismatch branch: RED = `promise resolved undefined instead
of rejecting` → GREEN after wiring the test's env control.
- Suites: `deploy-to-railway.digest-pin.test.ts` **14 passed**;
`image-drift.test.ts` **26 passed**. Typecheck (scripts + harness) 0
errors; oxfmt + oxlint clean; harness build green.
- **Empirical 6b against live prod** (settled two reviewer
masking-concerns as can't-happen under current config):
- prod harness `SHOWCASE_ENV` is *unset* (not `""`) and
`RAILWAY_ENVIRONMENT_NAME="production"`, so `isProductionEnv()`'s `??`
correctly resolves true → the prod-neutral fix **fires** in prod.
- prod image-drift is discovery-only; all 19 prod `showcase-*` services
are digest-pinned and tag-less, so `expectedTag` resolves to `latest`
for every prod service → a fixed tag cannot reach prod image-drift (no
false-green).

## Review

3-round cr-loop (7 agents/round) converged to zero actionable findings.
One fix-introduced test-scaffolding defect (dead `envId` helper option)
was caught in the confirmation round and fixed. Remaining reviewer notes
are pre-existing issues in untouched goLive/probe code or
theoretical-but-can't-happen-under-live-config items, tracked as
follow-ups (not in scope for this PR).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-19 07:44:29 -07:00
Jordan Ritter bce93f1e5e fix(cvdiag): pb-writer collection-existence check + forbid API updates (updateRule=null) + correct collision layer (M2 CR R2) 2026-06-19 07:44:16 -07:00
Sam Julien 3ae761a966 chore(docs): remove retired docs app (#5548)
## 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
2026-06-19 07:33:51 -07:00
Nathan 🔶 Tarbert fc2acea6db docs(shell-docs): update useRenderToolCall reference + schema-free tool-render opt-out (#5504)
## What

Updates the v2 `useRenderToolCall` reference page and makes opting a
tool out of the default rendering a single, schema-free call.

## Why

The reference page had drifted out of sync with the hook implementation
(`packages/react-core/src/v2/hooks/use-render-tool-call.tsx`) — most
notably `toolCallId` in the render props, added after the doc was last
touched. While documenting how to opt out of rendering, the natural
example (`useRenderTool({ name: "...", render: () => <></> })`) only
type-checked for the wildcard `"*"`; a named tool required a
`parameters` schema, forcing a throwaway `z.any()`. This PR re-aligns
the doc and removes that rough edge.

## Changes

### Docs (`showcase/shell-docs`)
- `useRenderToolCall.mdx`:
- Document `toolCallId` in the render-prop shape (previously
undocumented).
- Describe agentId-scoped lookup priority: agent-specific → unscoped →
wildcard `"*"` → built-in `DefaultToolCallRenderer`.
- Note args are parsed with `partialJSONParse` (streaming), not strict
`JSON.parse`.
- Correct `toolCall` prop to `toolCall.function.name` /
`toolCall.function.arguments`.
- Rewrite the Status Resolution table to match real logic (`toolMessage`
presence + provider executing set).
- New **"Disable default tool rendering"** section, ordered least→most
specific: wildcard first (all tools), then a **"For specific tools"**
subsection. Both use a schema-free `useRenderTool` call; dropped the old
`useFrontendTool` handler/schema boilerplate.
- `useRenderTool.mdx`: document the render-only (no-schema) named
overload.

### react-core
- Make `parameters` optional on the named `useRenderTool` overload,
mirroring the existing wildcard path; `defineToolCallRenderer` defaults
the args schema to `z.any()` when none is given.
- This lets `useRenderTool({ name: "myTool", render: () => <></> }, [])`
type-check with no Zod schema. Typed `parameters` behavior is unchanged.
- Added a test for the named render-only registration.

## Verification

- `@copilotkit/react-core` tests pass (1280) including the new case;
`build` (tsc) passes.
- Opt-out snippets type-checked in-package (`tsc`): wildcard,
specific-name (no schema), and named-with-schema all compile.
- `oxlint` (shell-docs) passes — 0 errors.
- Previewed locally at `/reference/hooks/useRenderToolCall`.
2026-06-19 10:32:20 -04:00
Alem Tuzlak d92959e68d Merge remote-tracking branch 'origin/main' into feat/bot-whatsapp
# Conflicts:
#	.github/workflows/canary.yml
#	.github/workflows/publish-release.yml
#	.github/workflows/stable-release.yml
#	examples/slack/README.md
#	examples/slack/app/index.ts
#	examples/slack/app/sender-context.ts
#	release.config.json
2026-06-19 16:17:16 +02:00
Alem Tuzlak c55dad5cc5 Merge branch 'main' into feat/bot-slack-native-streaming
Resolve event-renderer.ts onRunFinishedEvent: keep the native turn stream open
(finalized in finish()) AND retain the legacy per-message stream drain from main
(#5573) as a no-op-in-native safety net. app/index.ts (telegram adapter from
#5520 + showToolStatus:false) and create-bot.test.ts auto-merged.
2026-06-19 15:57:20 +02:00
Jordan Ritter 3458927f87 fix(showcase): stop image-drift flagging pinned prod red
Under the pinned-prod contract, prod is intentionally digest-pinned behind
:latest. image-drift now renders such prod services green (pinnedExpected)
instead of red; a genuinely missing digest stays red. Staging unchanged.
2026-06-19 03:50:40 -07:00
Jordan Ritter 3b02ee90a5 fix(showcase): provision prod services digest-pinned with go-live pin guard
Prod services are now born pinned to a resolved @sha256 digest (mirroring
the Ruby promote CLI's GHCR resolver) instead of the mutable :latest tag,
fail-loud on resolve failure, and goLive asserts the prod source.image is
digest-pinned. Adds DI-testable assertProdDigestPinned + coverage.
2026-06-19 03:50:40 -07:00
Jordan Ritter a3655a44f4 test(showcase): bump calculator-fixture integration pin to 19 for ms-agent-harness-dotnet 2026-06-19 03:05:20 -07:00
Jordan Ritter a755ab6c70 fix(cvdiag): gate DEBUG raw-byte capture to allow-listed slugs + mark raw-byte capture experimental/non-prod (M1 CR R9) 2026-06-19 02:49:51 -07:00
github-actions[bot] 45424333f0 style: auto-fix formatting 2026-06-19 09:32:19 +00:00
Jordan Ritter bc57302742 feat(showcase): thread not_supported_features into local control-plane roster for LOCAL==STAGING NSF skip parity 2026-06-19 02:28:34 -07:00
Jordan Ritter e10df0b489 feat(showcase): add ms-agent-harness-dotnet d6/d4 aimock fixtures 2026-06-19 02:28:33 -07:00
Jordan Ritter 87702c34b3 fix(cvdiag): DEBUG prod-fail-closed via trimmed safe-env allow-list (no fail-open on padded/aliased/unknown prod labels) (M1 CR R8) 2026-06-19 02:28:30 -07:00
Jordan Ritter 49d2ac16ff feat(showcase): port ms-agent-harness-dotnet frontend (demos, shared components, API routes) 2026-06-19 02:28:27 -07:00
Jordan Ritter 6ddc85f7ee feat(showcase): port ms-agent-harness-dotnet backend agents on the AsHarnessAgent construction surface 2026-06-19 02:28:22 -07:00
Jordan Ritter 4c1ed975c7 chore(showcase): register ms-agent-harness-dotnet column (manifest, csproj, slug-map, compose, dashboard, smoke) 2026-06-19 02:28:18 -07:00
Alem Tuzlak 340722f597 Merge remote-tracking branch 'origin/main' into feat/bot-whatsapp
# Conflicts:
#	examples/slack/package.json
#	pnpm-lock.yaml
#	showcase/shell-docs/src/content/docs/meta.json
2026-06-19 11:22:56 +02:00
Jordan Ritter d6915589d7 fix(cvdiag): raw-byte scrubs the entire retained head/tail (budget=segment length) so no sample region is unscanned, any body size (M1 CR R7 raw-byte-segment) 2026-06-19 02:17:49 -07:00
Jordan Ritter b0a2689970 fix(cvdiag): raw-byte captures+scrubs the REAL head+tail for >32KB bodies (scan-guard no longer truncates pre-cap) (M1 CR R6 A2)
Approach (A) reorder: decode -> html-strip -> headTailCap -> scrub(head)+scrub(tail).
The prior order scrubbed the FULL decoded body before the cap, so a body >32KB hit
scrubSecrets' bounded-prefix path: it truncated to a ...[unscanned:N] prefix BEFORE
headTailCap, which (1) lost the real tail, (2) never scanned the real tail for secrets,
and (3) zeroed elided_count. Reordering scrubs each retained <=16KB segment AFTER the
cap: input is bounded per-segment (linear regex x bounded length = ReDoS-impossible, no
scan-budget truncation), the captured head AND tail are the REAL ends of the body, and
elided_count comes from headTailCap on the FULL body. The unrelated 2KB metadata-hot-path
scan guard (SCRUB_MAX_SCAN_LEN) is untouched; the now-unneeded RAW_BYTE_SCAN_MAX export
is removed.
2026-06-18 23:48:53 -07:00
Jordan Ritter 6a0bee288e fix(cvdiag): applyByteCap byte-clamps edge_headers so the tier-cap post-condition holds for any header encoding (M1 CR R6 A1) 2026-06-18 23:48:47 -07:00
Jordan Ritter 0fb264f435 fix(cvdiag): raw-byte scrub uses its own scan budget, not the 2KB metadata guard (restores head+tail elision) (emit-hardening C-rawbyte)
The emit-hardening redesign added a 2KB SCRUB_MAX_SCAN_LEN guard inside
scrubSecrets, correct for the DEFAULT-tier metadata hot path (legit values
<=512B). But raw-byte-capture.ts also calls scrubSecrets on the DECODED wire
body, which is legitimately large (<=16KB head + <=16KB tail = up to 32KB).
The 2KB guard truncated the body to ~2KB before headTailCap ran, so for an
>32KB body elided_count became 0 and the head+tail elision never triggered.

Approach: parameterize the scan cap (chosen over the reorder-and-scrub-segments
alternative because it is a minimal, local change that preserves the documented
decode->scrub->html-strip->headtail pipeline order and keeps the metadata
default behavior byte-identical for all existing callers).

- scrub.ts: scrubSecrets gains an optional maxScanLen param defaulting to the
  exported SCRUB_MAX_SCAN_LEN (2KB). Metadata/validateMetadata callers are
  unchanged; the ReDoS guard on the hot path is untouched.
- raw-byte-capture.ts: passes RAW_BYTE_SCAN_MAX (head+tail cap = 32KB) so the
  full retained sample is scanned (no secret in the kept head/tail escapes) and
  headTailCap sees the un-truncated body. The three scrub regexes are linear at
  any bounded length, so the larger bound stays ReDoS-safe.
- scrub.test.ts: asserts the default param still applies the 2KB guard AND an
  explicit larger cap does not truncate, proving both contexts.
2026-06-18 23:33:11 -07:00
Jordan Ritter b296acb926 test(cvdiag): nested-secret sweep across all boundaries + scrub back-compat/re-export verification (emit-hardening C-sweep) 2026-06-18 23:28:06 -07:00
Jordan Ritter fc3feb3069 fix(cvdiag): applyByteCap clamps only metadata+demo, never structurally-invalidates fields (emit-hardening C-bytecap) 2026-06-18 23:17:21 -07:00
Jordan Ritter e1f9715ddc fix(cvdiag): validateMetadata calls scrubDeep directly, drops structuredClone wrapper (emit-hardening C-validate) 2026-06-18 23:13:22 -07:00
Jordan Ritter 5efcaa0763 fix(cvdiag): bound scrub worst-case scan (SCRUB_MAX_SCAN_LEN=2KB) + robust linearity-based ReDoS test (emit-hardening C-scrub-timing) 2026-06-18 22:24:13 -07:00
Jordan Ritter 243327ffaa Revert "test(cvdiag): make scrub ReDoS timing assertions robust (warm-up + 500ms ceiling)"
This reverts commit b2da571cd6.
2026-06-18 22:24:11 -07:00
Jordan Ritter b2da571cd6 test(cvdiag): make scrub ReDoS timing assertions robust (warm-up + 500ms ceiling)
The redesigned scrub regexes are linear, but the previous hard <50ms bound
flaked under JIT warm-up and shared-runner load (observed 77ms on a loaded
machine). Add a timeScrub helper that discards a warm-up call before timing
and assert against a 500ms ReDoS ceiling — wide enough to be jitter-immune,
still ~3x under the legacy ~1.4s catastrophic-backtracking blowup it guards
against.
2026-06-18 22:11:28 -07:00
Jordan Ritter 57bd8fe56f fix(cvdiag): boundEntryFields — sanitize caller slug/demo/parent_span_id/test_id at emit entry (emit-hardening C-entry) 2026-06-18 22:03:17 -07:00
Jordan Ritter 19215ca7dd fix(cvdiag): bound edge-header values at capture (EDGE_HEADER_MAX_LEN=256) (emit-hardening C-edge) 2026-06-18 22:03:14 -07:00
Jordan Ritter e1caabc0fc fix(cvdiag): ReDoS-safe + complete + non-mutating secret-scrub redesign (emit-hardening C-scrub) 2026-06-18 22:03:13 -07:00
Ben Taylor 14dda3d6f9 fix: ignore CopilotKit local state in starters (#5565)
## Summary
- add .copilotkit to newly scaffolded integration .gitignore files
- ensure extracted standalone starters also include .copilotkit in
.gitignore
- add regression coverage for scaffolded and extracted starter outputs

## Tests
- pnpm nx run @copilotkit/showcase-scripts:test --skip-nx-cache --
__tests__/extract-starter.test.ts __tests__/create-integration.test.ts
- pnpm exec oxfmt --check showcase/scripts/extract-starter.ts
showcase/scripts/create-integration/index.ts
showcase/scripts/__tests__/create-integration.test.ts
showcase/scripts/__tests__/extract-starter.test.ts
2026-06-18 21:57:21 -05:00
Jerel Velarde 37466ecff5 docs(cookbook): inline memory-ownership diagram as data-URI (drops broken CDN image dependency) 2026-06-18 18:52:11 -07:00
Jerel Velarde 1df235d93d Merge branch 'main' into cookbook/oracle-agent-spec-memory 2026-06-19 08:00:07 +08:00