Commit Graph

12110 Commits

Author SHA1 Message Date
Jordan Ritter e4b3ae25f8 fix(showcase): unblock promote — skip oxfmt on ephemeral SSOT emit (#5593)
## Summary

Every `showcase_promote.yml` dispatch has failed at the
`resolve-targets` job's "Generate SSOT artifact" step since 2026-06-18
(last green run `27790968900`), blocking ALL promotes including the
team's regular `shell-docs` promote.

**Root cause:** `emit-railway-envs-json.ts` (`oxfmtCanonical`, ~L212)
does `execFileSync(<repo-root>/node_modules/.bin/oxfmt, ...)`. The
`resolve-targets` step's `npm ci` runs in `showcase/scripts` only and
never installs the repo-root oxfmt binary → `spawnSync
.../node_modules/.bin/oxfmt ENOENT` → exit 1.

**Fix (approach a — explicit opt-out, fail-loud-correct):** The JSON
emitted on the `resolve-targets` / `promote` path is **ephemeral** —
`resolve-promote-targets.sh` parses it with jq and `bin/railway` reads
it in-memory to pick the promote target; it is **never committed**, so
oxfmt-canonical formatting is irrelevant there. Added an explicit
`EMIT_SKIP_OXFMT=1` env opt-out that returns the raw `JSON.stringify`
form, and set it on both ephemeral workflow steps. The
**committed-artifact path stays unchanged**: oxfmt is REQUIRED and fails
loud if absent (the committed `railway-envs.generated.json` must stay
oxfmt-canonical or `static_quality.yml`'s `oxfmt --check` auto-format
bot fires). This is opt-IN-to-skip, never silent-on-absence — the
fail-loud-discipline-correct shape.

Approach (b) (read the committed JSON) was rejected to preserve the
existing regenerate-from-SSOT-at-runtime guarantee; approach (c)
(install root oxfmt in that job) is heavier and unnecessary for an
ephemeral consumer.

## RED-GREEN proof (real failure surface, oxfmt binary absent)

**RED — reproduce the production failure** (`npm ci` in
`showcase/scripts` only; repo-root oxfmt absent, exactly as CI's
resolve-targets):
```
$ npx tsx emit-railway-envs-json.ts
Error: spawnSync /private/tmp/cpk-oxfmt/node_modules/.bin/oxfmt ENOENT
    at oxfmtCanonical (.../emit-railway-envs-json.ts:212:5)
    at serialize (.../emit-railway-envs-json.ts:221:10)
    at main (.../emit-railway-envs-json.ts:241:16)
EXIT=1
```

**GREEN — ephemeral path now works** (oxfmt still absent):
```
$ EMIT_SKIP_OXFMT=1 npx tsx emit-railway-envs-json.ts --out=/tmp/ephemeral-out.json
wrote /tmp/ephemeral-out.json
EXIT=0
$ jq '.services | length' /tmp/ephemeral-out.json        → 41
$ jq -r '.services[]|select(.probe.prod==true)|.name' ... → aimock, dashboard, docs, ...
$ jq '.closure.services | length' ...                     → 39
```
And the actual downstream consumer parses it and resolves the team's
`shell-docs` promote:
```
$ INPUT=shell-docs GENERATED=/tmp/ephemeral-out.json ... resolve-promote-targets.sh
services_csv=docs
closure_csv=pocketbase,dashboard,harness,docs
closure_plan=0:pocketbase,1:dashboard,1:harness,2:docs
EXIT=0
```

**GREEN — committed path still canonical AND still fail-loud** (oxfmt
PRESENT, default path, no env var):
```
$ npx tsx emit-railway-envs-json.ts            # regenerate committed artifact
wrote .../railway-envs.generated.json
$ git diff --quiet showcase/scripts/railway-envs.generated.json; echo $?   → 0  (byte-identical)
$ npx tsx emit-railway-envs-json.ts --check    → railway-envs.generated.json is up to date.  EXIT=0
```
Committed/default path STILL fails loud when oxfmt absent (NOT
weakened):
```
# oxfmt removed, NO env var:
$ npx tsx emit-railway-envs-json.ts --out=/tmp/x.json
Error: spawnSync .../node_modules/.bin/oxfmt ENOENT   (exit 1, nothing written)
```

## Call-site enumeration

- `showcase_promote.yml` **resolve-targets** — `EMIT_SKIP_OXFMT=1` (this
fix). ✓
- `showcase_promote.yml` **promote** — `EMIT_SKIP_OXFMT=1` (this fix;
same ephemeral regen). ✓
- `static_quality.yml` committed-artifact `--check` — unset → oxfmt
REQUIRED, canonical guarantee preserved. ✓
- `resolve-verify-matrix.ts` (`showcase_deploy.yml`) — invokes the
emitter only `if (!existsSync(SSOT_JSON))`; the checkout always carries
the committed JSON, so the default (oxfmt) path is correct and
unchanged. ✓

## Test plan

- [x] RED reproduced on the real surface (ENOENT at
oxfmtCanonical←serialize←main).
- [x] GREEN: ephemeral path emits valid JSON + downstream resolve script
works.
- [x] GREEN: committed path regenerates byte-identical (empty git diff,
`--check` passes).
- [x] GREEN: committed/default path still fails loud when oxfmt absent.
- [x] 2 new `EMIT_SKIP_OXFMT` unit tests; full showcase/scripts suite
2037 passing.
- [x] Pre-push: oxfmt --check, oxlint, actionlint all clean on changed
files.
- [ ] CI green.
2026-06-19 14:41:43 -07:00
Jordan Ritter 6f50bebf0e fix(cvdiag): materialize _shared into integration build-check Docker context (symlink escaped context → 'too many symlinks') (M6) 2026-06-19 14:37:08 -07:00
Jordan Ritter bf6933a436 fix(showcase): unblock promote — skip oxfmt on ephemeral SSOT emit
The showcase_promote.yml resolve-targets job runs
`emit-railway-envs-json.ts`, which shells out to the repo-root
`node_modules/.bin/oxfmt` to produce oxfmt-canonical JSON. That job's
`npm ci` runs in showcase/scripts only and never installs the root oxfmt
binary, so every promote dispatch died at "Generate SSOT artifact" with
`spawnSync .../node_modules/.bin/oxfmt ENOENT` (exit 1) — blocking ALL
promotes, including the team's regular shell-docs promote, since the last
green run on 2026-06-18.

The emitted JSON on the resolve-targets / promote path is EPHEMERAL: it
is parsed in-memory by jq (resolve-promote-targets.sh) and bin/railway to
pick the promote target and is NEVER committed, so oxfmt-canonical
formatting is irrelevant there. Add an explicit `EMIT_SKIP_OXFMT=1`
opt-out that returns the raw `JSON.stringify` form, and set it on both
ephemeral workflow steps.

The DEFAULT (committed-artifact) path is unchanged: oxfmt stays REQUIRED
and fails loud if the binary is absent, because the committed
railway-envs.generated.json must stay oxfmt-canonical or CI's
static_quality.yml `oxfmt --check` auto-format bot fires on the drift.
This is opt-IN-to-skip, never silent-on-absence.

Call sites of emit-railway-envs-json.ts:
- showcase_promote.yml resolve-targets — EMIT_SKIP_OXFMT=1 (this fix).
- showcase_promote.yml promote — EMIT_SKIP_OXFMT=1 (this fix).
- static_quality.yml committed-artifact `--check` — unset, oxfmt required.
- resolve-verify-matrix.ts (showcase_deploy.yml) — only invokes the
  emitter when the committed JSON is absent; the checkout always has it,
  so the default (oxfmt) path is correct and unchanged.

Tests: 2037 showcase/scripts tests pass; 2 new EMIT_SKIP_OXFMT unit tests
assert the skip path emits valid (raw) JSON; the existing oxfmt-canonical
golden tests still gate the committed path.
2026-06-19 14:32:46 -07:00
Jordan Ritter 478afc0f78 fix(showcase): declarative-gen-ui D6 completes on surface-mount, not text-stability (#5590)
> **DRAFT / WIP — not reviewed, not ready to merge.** Checkpoint per
request. The mandatory 7-agent cr-loop + CI-green gate runs before this
leaves draft. LGP and ADK ship together in this PR.

## Problem (a false-D6 in both directions)
Declarative A2UI demos wire `a2ui.injectA2UITool: true`, so the response
is a rendered `render_a2ui` surface with **no assistant text bubble**.
The D6 conversation-runner's turn-completion gate required the assistant
**text** to stabilize — so on a working declarative demo the run
finished and the dashboard painted, but text never settled →
`waitForTurnComplete` timed out (`reason=text-unstable`) **before the
render assertion ran**.

Result: `langgraph-python:declarative-gen-ui` (the gold standard)
reported **false-RED while rendering correctly** (all 4 pills verified
live on staging), while `google-adk` reported **false-GREEN**.

## Fix
Opt-in `ConversationTurn.completeOnMount` (set only by
`d5-gen-ui-declarative.ts`). For those turns the text-stability
completion conjunct is **replaced** by a surface-mount predicate:
run-finished (sseOk) + a new assistant bubble + the expected declarative
testids **newly mounting**. A non-rendering surface now yields a new
`surface-missing` failure reason (truthful RED). Text-based demos are
byte-for-byte unchanged (opt-in, per-turn).

## Proof (both directions, live D6)
- RED (before): `text-unstable` timeout; dashboard text painted.
- GREEN (after): passes in ~5s; `buildDeclarativeAssertion` actually
runs and verifies testids mount for all 4 pills.
- INTEGRITY: forced a broken render (renamed testids) → test goes
**red** (`surface-missing`). Not "always green now."
- Unit: 89/89 + 3 new (green-on-mount, red-on-surface-missing).

## Scope: LGP + ADK (ship together) — both truthful GREEN
- **LGP** gold-standard cell: false-RED → truthful GREEN (all 4 pills
assert).
- **ADK** realignment: **test-only, complete.** The shared-script fix
auto-applies; verified all 4 ADK pills truthfully GREEN (each surface
mounts from baseline 0 via surface-mount completion). Prior false-green
closed; **no ADK backend gap**.

## Out of scope (someone else's problem)
This shared-script change re-evaluates **every** declarative-gen-ui cell
truthfully. Integrations beyond LGP/ADK that don't actually render will
flip to **truthful RED** — e.g. `langgraph-typescript` pill 2
(team-performance `declarative-data-table` doesn't mount). Those are
real per-demo render gaps for their owners; **not fixed here.**

## Follow-up (not in this PR)
The `render_a2ui` call returns a ~5.9 MB SSE for a ~2 KB surface (LGT
worse) — a separate runtime amplification concern in the
`injectA2UITool:true` middleware path.

## Before ready/merge
- [x] ADK empirical verdict — all 4 pills truthful GREEN, realignment
test-only, no backend gap
- [ ] mandatory cr-loop → zero findings
- [ ] CI green
2026-06-19 14:19:10 -07:00
Austin Merrick 4c71ea1138 fix(core): allow clearing headers via setHeaders with null/undefined
setHeaders typed headers as Record<string, string>, so there was no
type-safe way to clear a header (e.g. Authorization on logout) — passing
an empty string left the header present with a blank value.

Widen the signature to Record<string, string | null | undefined> and drop
any entry whose value is null/undefined. setHeaders remains a full overwrite,
so clearing one header while keeping the rest is the spread pattern:
setHeaders({ ...copilotkit.headers, Authorization: null }). A shared
normalizeHeaders helper enforces the same string-only invariant at both
write paths (constructor and setHeaders).

Update the react-core AuthTokenSync skill example to show the logout/clear
path and warn that a header must not be managed via both the headers prop and
imperative setHeaders (the provider re-applies prop-derived headers as a full
overwrite when its inputs change). Also update the setHeaders reference
signature docs. Tests cover null/undefined stripping, empty-string
preservation, overwrite-not-merge semantics, single-header clear via spread,
subscriber notification, and propagation to local and remote
(ProxiedCopilotRuntimeAgent) agents.

Fixes #5535
2026-06-19 14:13:02 -07:00
Jordan Ritter 679282570b fix(cvdiag): resolve staged cvdiag .js imports in integration next build (extensionAlias / stage rewrite) — unbreaks build-check across all integrations (M6) 2026-06-19 14:09:14 -07:00
Jordan Ritter 3f9d8a4826 fix(showcase/harness): opt declarative-gen-ui pills into surface-mount completion
Opts each declarative-gen-ui pill into the new `completeOnMount` turn
completion so these surface-rendering demos are gated on their expected
declarative testids mounting rather than assistant-text stability.
2026-06-19 14:08:47 -07:00
Jordan Ritter 93a65dbb5b fix(showcase/harness): complete tool-rendered turns on surface-mount, not text-stability
Declarative A2UI demos render a surface (mounted testids) with no assistant
text bubble, so the assistant-text-stability completion gate never settled and
timed out on working demos — a false-RED.

This adds an opt-in `completeOnMount` turn-completion path that replaces the
assistant-text-stability conjunct with a surface-mount predicate: run-finished
+ a new assistant bubble + the expected declarative testids newly mounting.
A new `surface-missing` failure reason reports when the run finishes but the
expected surface never mounts. Turns that do not opt in keep the existing
text-stability behavior unchanged.
2026-06-19 14:08:40 -07:00
Austin Merrick 43cb8a69a5 docs: add Angular quick-start guide
Add the Angular frontend quick-start at content/docs/frontends/angular.mdx
and wire it into the frontend picker (options, logo, page content, search
hrefs, search-index generation).
2026-06-19 14:05:19 -07:00
Jordan Ritter b585b33947 fix(showcase): include 12 starters in promote dropdown + regression guard (#5588)
## Summary

Fixes the showcase promote dropdown so the 12 `starter-*` services are
dispatchable. The committed `.github/workflows/showcase_promote.yml`
`service` choice list was never regenerated after the starters landed in
the SSOT, so `gh workflow run showcase_promote.yml -f service=starter-*`
was rejected by GitHub with `HTTP 422: not in the list of allowed
values` (GitHub validates the `choice` enum server-side against the
default branch). This left main's "Showcase: Build & Push" red via
`verify-railway-image-refs`.

## Changes

- Regenerated `showcase_promote.yml` — the `service` dropdown now
includes all 12 starters plus `shell-docs` and every previously-listed
target (nothing dropped). 41 options total.
- `isProdPromotable` reads the canonical env-map shape
(`environments.prod.probe`), equivalent to the workflow resolve
predicate (`select(.probe.prod==true)` against the emitted JSON).
- Added a durable regression test asserting `shell-docs` AND all 12
starters are present in both the generator output and the committed
dropdown, so a future generator regression can't silently drop a promote
target.

## Test plan

- [x] `--check` exits 0 (committed dropdown in sync with SSOT)
- [x] vitest 24/24 pass; regression guard asserts shell-docs + 12
starters
- [x] every emitted token resolves to exactly one prod-eligible service
under the real resolve predicate
- [x] oxfmt/oxlint/typecheck clean on the diff
2026-06-19 14:05:14 -07:00
github-actions[bot] 691c036789 style: auto-fix formatting 2026-06-19 20:54:20 +00:00
Jordan Ritter 4a4c0d12b8 fix(showcase): include 12 starters in promote dropdown + regression guard
Regenerated the stale committed showcase_promote.yml so the 12 starter-*
services (+ shell-docs and all existing targets) appear in the service
dispatch choice list (fixes HTTP 422 on
gh workflow run -f service=starter-*). Reverted isProdPromotable to
env-map-only (environments.prod.probe), equivalent to the workflow resolve
predicate. Added a regression test asserting shell-docs + all 12 starters
remain in the generated AND committed dropdown.
2026-06-19 13:53:25 -07:00
Jordan Ritter fada109b72 Merge remote-tracking branch 'origin/main' into blitz/cvdiag-observability/integration
# Conflicts:
#	showcase/integrations/ms-agent-harness-dotnet/agent/BeautifulChatAgent.csproj
2026-06-19 13:51:02 -07:00
Tyler Slaton ad22f03be1 docs: update Enterprise Intelligence Platform docs (#5587)
## Summary

- Add a top-level Enterprise Intelligence Platform overview that
clarifies platform features, hosting options, plans/access, and the path
from cloud-hosted to self-hosted.
- Add Cloud-Hosted Enterprise Intelligence documentation covering
dashboard login, organization/workspace flow, projects, project API
keys, thread history/detail, and plan management.
- Refresh the Enterprise Intelligence Architecture and Threads &
Persistence Architecture pages so they are architecture-focused instead
of overlapping self-hosting/how-to content.
- Update self-hosting documentation to use the current product taxonomy,
call out Team self-hosted/custom Enterprise availability, and use a
tracked Enterprise-styled CTA for talking to an engineer.
- Add the CopilotKit CLI doc plus shared CLI content across root docs
and all visible authored/generated integration routes.
- Add CLI sidebar entries for authored framework docs and test that CLI
appears in both generated and authored framework nav.
- Add dashboard screenshots for ready, projects, thread list, API keys,
thread detail, and plan management/pricing.
- Update Threads, useThreads reference, multi-conversation tutorial,
architecture/concepts pages, and runtime snippets to point at the new
Enterprise Intelligence docs and remove early-access language from
Threads.
- Retire legacy Observability docs, remove observability references from
quickstarts/runtime docs/nav, and add SEO redirects from root,
troubleshooting, and framework observability URLs to the Intelligence
overview.
- Instrument Enterprise Intelligence CTAs with PostHog: signup CTAs fire
`try_for_free_clicked`, self-hosting engineer CTA fires
`talk_to_us_clicked`, and CLI command copying continues through
`cli_command_copied`.
- Rebase the PR branch onto current `origin/main` and fix the
integration docs doctest by adding LangGraph quickstart Python
dependencies plus clearer server-start diagnostics.

## Commits

- `docs(shell-docs): instrument intelligence ctas`
- `docs(shell-docs): add copilotkit cli docs`
- `docs(shell-docs): refresh intelligence platform docs`
- `docs(shell-docs): retire observability docs`
- `test(doc-tests): fix langgraph quickstart doctest`

## Validation

- `pnpm tsx scripts/doc-tests/extract.ts && pnpm tsx
scripts/doc-tests/run.ts`
- `pnpm exec vitest run scripts/doc-tests/__tests__/extract.test.ts`
- `pnpm exec oxfmt --check scripts/doc-tests/run.ts
showcase/shell-docs/src/content/docs/integrations/langgraph/doctest.json`
- `npm run test` in `showcase/shell-docs`
- `npm run typecheck` in `showcase/shell-docs`
- `npm run build` in `showcase/shell-docs`
- `pnpm run lint` at the repo root (0 errors; existing repo warnings
remain)
- `pnpm exec oxfmt --check` against PR-changed text files
- Local route checks for `/cli`, `/mastra/cli`, `/langgraph-python/cli`,
`/premium/managed-intelligence-platform`, `/premium/self-hosting`
- Local redirect checks for `/premium/observability`,
`/troubleshooting/observability-connectors`,
`/mastra/premium/observability`

Notes: build still reports the existing Next/Turbopack warnings about
deprecated middleware and NFT tracing in `next.config.ts`, but completes
successfully. Full repo `pnpm run check-format` currently fails on
pre-existing files outside this PR:
`examples/v2/react/demo/tsconfig.json`, `migrations.json`, and
`nx.json`; the PR-changed text files pass `oxfmt --check`.
2026-06-19 13:44:26 -07:00
Austin Merrick fb246ebbd7 docs(angular): add @copilotkit/angular reference documentation
Add an Angular SDK section to the reference docs (OSS-251), mirroring the
React and Vue references. Registers Angular in the reference infrastructure
(new Services and Directives categories, version selector label, subdir map,
overview card) and adds an index plus 17 pages covering provideCopilotKit and
the config/label functions, the CopilotKit service, injectAgentStore and
context APIs, tool registration (frontend, render, human-in-the-loop), the
CopilotKitAgentContext directive, and the prebuilt chat components.

All pages are written against the actual @copilotkit/angular source, use the
correct package name and top-level imports, and surface in llms.txt and
llms-full.txt.
2026-06-19 13:36:34 -07:00
Tyler Slaton 722000b58b docs(cookbook): add Oracle Agent Spec × Memory recipe (#5521)
## What

Adds the **"Build an Agentic Travel App with Oracle Agent Memory, Agent
Spec, and CopilotKit"** cookbook recipe, alongside `daytona.mdx` and
following the same section pattern (Try it live → Prerequisites → setup
→ Try it → key code → Going further → coding-agent prompt).

It wires together:
- **Oracle Agent Spec** — define the agent once as portable JSON
(`pyagentspec`)
- **LangGraph + AG-UI** — run that spec via the `ag_ui_agentspec`
adapter, served over AG-UI (SSE)
- **Oracle AI Database** — long-term memory (`oracleagentmemory`) so the
agent remembers across sessions
- **CopilotKit V2** — the chat frontend (generative UI +
human-in-the-loop), consuming the AG-UI endpoint with `HttpAgent`

The example is a travel concierge that recalls your preferences across
sessions, searches flights, and books them with a human-in-the-loop
confirmation card that stamps into a boarding pass.

## Try it live

Embeds the hosted demo as a live `<iframe>` — **cross-session recall
verified working end-to-end** (teach a preference in one thread, open a
new thread, it recalls from Oracle AI Database).

## Files
- `cookbook/oracle-agent-spec-memory.mdx` (new)
- `cookbook/meta.json` — sidebar entry
- `cookbook/index.mdx` — overview card

## Companion code
**#5563** adds the runnable demo at
`examples/showcases/oracle-agent-memory` (Python agent + Next.js
frontend + Oracle AI Database), beside `daytona-runcode`. The recipe's
"Get the code" links point there.

## No external asset dependencies
- "Try it live" is a live `<iframe>` — no CDN video to upload.
- The architecture diagram is an inline base64 data-URI SVG — no CDN
image to upload.

## Caveat kept honest in the doc
- **Recall is eventually consistent** — memory is
extracted/embedded/indexed asynchronously, so a just-taught fact becomes
recallable after a short delay.

## Verified
- `book_flight` is a CopilotKit **ClientTool** (`useHumanInTheLoop`) —
the confirm→book HITL resolves in a single agent run. Multi-turn
follow-ups work via a server-side full-history replace that sidesteps an
upstream Agent Spec × AG-UI `tool_call_id` correlation bug (documented
inline + in #5563's known-issues).
- Playwright E2E covers cross-session recall, flight search, and the
booking HITL (3/3 green).
- All CI green; ready for review.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-19 13:20:26 -07:00
Sam Julien 75e397049b test(doc-tests): fix langgraph quickstart doctest 2026-06-19 13:11:05 -07:00
Sam Julien c641f33d38 docs(shell-docs): retire observability docs 2026-06-19 13:11:05 -07:00
Sam Julien f34eb6e528 docs(shell-docs): refresh intelligence platform docs 2026-06-19 13:11:04 -07:00
Sam Julien 7bb3141024 docs(shell-docs): add copilotkit cli docs 2026-06-19 13:11:04 -07:00
Sam Julien b5c9b0d3c4 docs(shell-docs): instrument intelligence ctas 2026-06-19 13:11:03 -07:00
Tyler Slaton 2688ce4c32 docs(frontends): improve picker and language for non-react frontends (#5586)
## Summary
- Fix frontend selection, logo, and docs navigation behavior in shell
docs
- Update link rewriting, search href generation, SEO redirects, and
sitemap handling for frontend docs paths
- Refresh related docs pages and tests across framework and frontend
routes

## Testing
- Added and updated unit tests for frontend options, link rewriting,
search hrefs, SEO redirects, and framework shell layout
- Added route-level coverage for the llms-mdx endpoint
2026-06-19 12:51:33 -07:00
Jordan Ritter a7c9e8eaa2 feat(showcase): dependency/env/verification-complete cluster promote (#5584)
## Summary

Makes showcase cluster promotion **dependency-, env-, and
verification-complete** so prod matches staging after a full promote —
and folds the **starter template apps into the same cluster** so they
get identical treatment. (Design spec: Notion
`3843aa38185281629803fd926b793018`.) One PR.

### Engine (the 19 showcase-* integrations + infra)
- **Dependency-complete:** promote-closure SSOT
(`promoteTier`/`runtimeDeps`/`serviceRefs`) + pure
`computePromoteClosure` (tier-ordered 0→1→2, skip-with-reason, fail-loud
`assertClosureValid`); tier-ordered dependency-gated promote (tier-0
failure blocks 1+2 as NOT-ATTEMPTED, `--digest` escape retained);
`lint-prod` pinned-ness gate.
- **Env-complete:** Ruby preflight — service-ref assertion (REFUSE on
prod→staging host), replicate-class env-write mechanism (opt-in, empty
today), prod-specific assert-never-copy (R-A guard); resource
detect-and-WARN. (`limitOverride` WARN dropped — Railway exposes no
readable limit field, introspection-verified.)
- **Verification-complete:** cross-env pin-drift probe (prod-pinned vs
last-promoted digest — the real prod drift signal); dashboard folds
harness `driver-error`/`abort` + stale cells to gray (genuine failures
stay red — masks-real-red guard verified); prod↔staging equivalence gate
(ChipColor compare, gray-excluded, one-directional) fed by a verify-prod
re-sweep + freshness wait.

### Starters (the 12 starter-* template apps) — "one whole cluster"
- 12 starter SSOT entries (tier 2, `runtimeDeps:["aimock"]`,
`serviceRefs:OPENAI_BASE_URL→aimock`); reversed the 3 decoupling fences
(drift whitelist, `lint-prod` exemption, provisioner) so **`lint-prod`
now covers starters** (flags any prod `:latest`).
- Equivalence + re-sweep run starters on their **starter-smoke axis**
(`probeAxis:"starter"`): enqueue fires `starter_smoke:starter-<slug>`
triggers and the gate reads `starter:<col>/<level>` rows — agent axis
unchanged.
- **F1 value-tested:** all 12 starters carry prod
`OPENAI_BASE_URL`→prod-aimock (mirror showcase-* wiring), so the
service-ref assertion does NOT brick the promote.

### Verification
- 4-round 7-agent cr-loop converged to zero actionable findings (caught
+ fixed a verify-prod always-REFUSE cell-derivation bug, a dead
`limitOverride` WARN, and an incomplete starter enqueue axis). Red-green
on every unit; cross-env probe proven against live Railway.
- Pre-push CLEAN: oxfmt/oxlint, tsc 0 (scripts/harness/dashboard),
suites green (scripts 257, harness 194, dashboard 1118, ruby 160, bats
103), builds 0, actionlint clean.

### Out-of-band prod hotfix (already live)
Prod `aimock` was stale (06-16) and lacked the google-adk
`gen-ui-declarative` fixture → prod served a hallucinated dashboard.
Promoted prod aimock to staging's digest; **value-tested live** — prod
now serves the curated `$4.2M` fixture. This is the exact
dependency-incomplete-promote failure the redesign prevents.

### Phase-2 activation (to switch the new guarantees ON — not in this
PR)
The tier-closure + verify-prod gate ship **dormant/config-gated** (low
blast radius). To activate: (1) wire `CLOSURE_PLAN` into the live
promote step (currently feeds the leaf `SERVICES_CSV`); (2) provision
prod `harness-workers` + set `SHOWCASE_PROD/STAGING_POCKETBASE_URL`,
`SHOWCASE_RAILWAY_ENV_ID_PROD`, `SHOWCASE_RAILWAY_PROJECT_ID`; (3) set
`PROD_HARNESS_BASE_URL`/`PROD_HARNESS_TRIGGER_TOKEN` for the starter
re-sweep.

### Follow-ups (ledgered, non-blocking)
GHCR token-exchange for harness drivers; closure dual-impl imageOf
divergence (latent); discriminated-union type-hardening for
GateCell/CellComparison; misc defensive-branch coverage.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-19 12:44:06 -07:00
Jordan Ritter 32d851a290 fix(cvdiag): .NET scrubber redacts URL userinfo (scheme://user:pass@host + colon-less) matching scrubSecrets (M6) 2026-06-19 12:33:06 -07:00
Jordan Ritter a5678c118f fix(cvdiag): Java MessageScrubber parity with scrubSecrets — sk- base64url tails, Bearer \S+, colon-less URL userinfo + size-guard (M6) 2026-06-19 12:33:03 -07:00
Jordan Ritter 0a826bf17f fix(cvdiag): re-stage TS cvdiag emitter from canonical — staged copies were stale (leaked sk-ant-/colon-less URL userinfo + half-missing emit.ts) (M6) 2026-06-19 12:33:00 -07:00
Jordan Ritter c3c7b7908b feat(showcase): cross-env pin-drift probe + Ops routing + bring starters under the image-ref gate 2026-06-19 12:23:23 -07:00
Jordan Ritter 59b18d1bde feat(showcase): prod-staging equivalence gate + verify-prod re-sweep (agent + starter_smoke axes) 2026-06-19 12:23:23 -07:00
Jordan Ritter 43fedfdb55 fix(showcase): fold driver-error/abort + stale dashboard cells to gray (agent + starter axes) 2026-06-19 12:23:23 -07:00
Jordan Ritter a5186c50c2 feat(showcase): ruby promote preflight (service-ref/replicate/resource) + lint-prod starter coverage 2026-06-19 12:23:23 -07:00
Jordan Ritter 73b5c5a798 feat(showcase): tier-ordered dependency-gated cluster promote + lint-prod gate 2026-06-19 12:23:23 -07:00
Jordan Ritter 808bc4741d feat(showcase): promote-closure SSOT (tiers/runtimeDeps/serviceRefs) + computePromoteClosure + 12 starter entries + oxfmt-canonical emit 2026-06-19 12:23:22 -07:00
Tyler Slaton e2f742dd27 fix(docs): add langgraph doctest dependencies 2026-06-19 12:21:56 -07:00
Tyler Slaton d1fb02bcd6 fix(shell-docs): canonicalize react guidance redirects 2026-06-19 12:09:30 -07:00
Jordan Ritter 802ffbbcc9 fix(cvdiag): _shared logging setup is inert when disabled — no host root-handler teardown at import; capture-when-enabled preserved + inert lever test (M5 CR R4)
setup() ran logging.basicConfig(force=True) unconditionally at import (module
calls setup() at the bottom), tearing down the host app's root-logger handlers
on every backend even when cvdiag was disabled (CVDIAG_BACKEND_EMITTER off,
canary-safe default) — violating the byte-for-byte-inert contract. Replaced the
root basicConfig(force=True) with a scoped StreamHandler attached to the
"agents" logger, installed ONLY on the ENABLED path (after _ENABLED=True), so a
disabled/degraded setup performs zero logging mutation and the host root
handlers survive. capture-when-enabled (agents.* → stdout) preserved.

Call sites: setup() defined cvdiag_bootstrap.py:133, invoked at import-time
:273 (now no longer touches root). is_enabled() :206 unchanged (gates emit).
basicConfig() call REMOVED from :128; only doc references remain. New scoped
_install_agents_log_capture() runs on the enabled path; reset_for_test() now
detaches the handler.
2026-06-19 12:02:55 -07:00
Jordan Ritter 530649864e fix(cvdiag): LGP gates request.ingress/llm.call.*/sse.first_byte to VERBOSE tier matching canonical _BOUNDARY_TIER (M5 CR R3)
The four §6-VERBOSE-only backend boundaries (request.ingress, llm.call.start,
llm.call.response, sse.first_byte) called _emit with no tier_gate, so they
over-emitted at DEFAULT tier — 4 extra events/request vs the middleware family,
breaking the §7 tier budget and cross-backend apples-to-apples parity. Gate
them with tier_gate=_VERBOSE_TIERS, matching emit.ts:58-63 and the agno
_BOUNDARY_TIER. langgraph-fastapi received the identical change (the two LGP
files differ only by docstring/plan-unit/_SLUG). Adds default-suppressed +
verbose-emits red-green coverage; updates the pre-existing first_byte
correlation test to drive at VERBOSE tier (the boundary is VERBOSE-only).
2026-06-19 11:42:52 -07:00
Jordan Ritter 75e2c53286 fix(cvdiag): _shared emit gate consults _ENABLED so the fail-closed DEBUG degrade actually suppresses emission (M5 CR R3)
emit_cvdiag now early-returns when not is_enabled(), in addition to the
per-integration CVDIAG_BACKEND_EMITTER env check, so a degraded setup()
(_ENABLED=False) emits nothing — the degrade wins over the live env toggle.

Call sites: shared emit_cvdiag (this file, the single chokepoint) now gates on
is_enabled() (the previously-dead _ENABLED flag, set False by setup()'s
fail-closed degrade). Per-integration emitter_enabled() (langgraph-python,
langgraph-fastapi) and cvdiag_backend_enabled() (10 other _cvdiag_backend.py
modules) remain env-only and call into emit_cvdiag — out of scope here; the
shared gate is the defense-in-depth backstop for all of them.
2026-06-19 11:42:52 -07:00
github-actions[bot] 861148ff38 style: auto-fix formatting 2026-06-19 18:41:49 +00:00
Tyler Slaton eb000d034e Fix frontend picker and docs routing 2026-06-19 11:38:17 -07:00
Jordan Ritter a9d2dd342e fix(cvdiag): backend scrub URL-userinfo+Bearer-tail parity + size-guard, live-tier consistency, stop_heartbeat cooperative-cancel across 12 emitters (M5 CR R1) 2026-06-19 11:23:35 -07:00
Jordan Ritter 2f2302cb65 fix(cvdiag): _shared pb_writer never-propagate drain + bootstrap degrade-not-crash + idempotent setup (M5 CR R1) 2026-06-19 11:23:31 -07:00
Jordan Ritter ec9923217f fix(cvdiag): d4 isMessagePost matches the agent-message POST specifically so messageSendEdge/edge_interference_signal/raw-byte aren't sourced from an unrelated POST (M7 CR R2) 2026-06-19 10:53:47 -07:00
Jordan Ritter dd25df8edd fix(cvdiag): cli-replay/cli-pb validateRow type-checks envelope fields (reject non-string ts/test_id, non-number mono_ns) instead of silently admitting → NaN sort (M7 CR R2) 2026-06-19 10:53:47 -07:00
Jordan Ritter 8b4ad2380b fix(cvdiag): A/B report — edge_interference_suspected is edge-arm-only + succeeding-pairs-only; mis-correlated pair does not present one arm's identity as authoritative (M7 CR R2) 2026-06-19 10:53:46 -07:00
Alem Tuzlak 588a2fb405 Merge branch 'main' into feat/bot-whatsapp 2026-06-19 19:45:21 +02:00
Jordan Ritter d4c660d44d fix(cvdiag): d4 A/B arm passes real L3 edge headers (edge_interference_signal no longer pinned false) + no orphan half-pair when internal arm absent (M7 CR R1) 2026-06-19 10:44:31 -07:00
Jordan Ritter ee575441cd fix(cvdiag): cli-classify test fixtures model genuine empty-200 (ruleH success-outcome), cli-replay asserts rows match queried test_id + hard-errors on empty/mismatch (M7 CR R1) 2026-06-19 10:44:31 -07:00
Jordan Ritter e2b08acae2 fix(cvdiag): A/B report — info is non-failure, detect slug/demo mis-correlation, consume edge_interference_signal, validate ab_pair_id (M7 CR R1) 2026-06-19 10:44:31 -07:00
Jordan Ritter d6573e7e7d fix(cvdiag): classifier — rule-h guarded to genuine empty-200 (no longer steals slow/err null-token cases from rule-a), truthful rule-f/g/h reason strings (M4 CR R2) 2026-06-19 10:27:42 -07:00
Jordan Ritter 74a976f4b2 fix(cvdiag): classifier rule accuracy — cross-layer tolerance sign, rule-f crash detection both signals, rule-g/h null normalization, mono_ns-ordered fact selection (M4 CR R1) 2026-06-19 10:19:52 -07:00