Commit Graph

1341 Commits

Author SHA1 Message Date
github-actions[bot] 1cf6eefba9 style: auto-fix formatting 2026-07-08 13:27:35 -05:00
Benjamin Taylor b394f06fdc refactor(channels): rename @copilotkit/bot* packages to @copilotkit/channels* (OSS-438)
Renames the Bots SDK to the Channels SDK. Names only — no behavior change.

- 8 packages @copilotkit/bot* -> @copilotkit/channels* (git mv dirs, names,
  workspace: cross-deps). Now includes @copilotkit/bot-intelligence ->
  @copilotkit/channels-intelligence (landed on main via #5761; unpublished, so
  renamed fresh with the family).
- release.config.json scope keys + versionSource; ReleaseScope union;
  canary/stable-release/publish-release scope dropdowns; verify script
- examples/slack (Kite) + examples/teams: deps, jsxImportSource, imports
- showcase/shell-docs: content dirs docs/bots->docs/channels and
  reference/bot->reference/channels, nav registry, redirects

createBot and other API names unchanged. Old @copilotkit/bot* to be deprecated
after the new packages publish (bot-intelligence was never published).

Re-derived onto latest main (was conflicting after #5761 landed).

Refs OSS-438
2026-07-08 13:27:35 -05:00
Ben Taylor 9fa925bd95 feat(bot,runtime): managed bots SDK — run the bot SDK from Intelligence-delivered events (OSS-360/361) (#5761)
## Summary

Lets the `@copilotkit/bot` SDK run from **Intelligence-delivered
events** without a second programming model, and adds the runtime `bots`
declaration API. A managed event (delivered by Intelligence) runs the
*same* customer handlers, tools, context, commands, Bot UI, and agents
as local/custom adapters — the managed path is "just another
`PlatformAdapter`," fed by injected transports.

This is the **OSS / SDK slice** of the Hosted Managed Bots work. The
credentialed transports (Realtime Gateway, Connector Outbox) and the
frozen shared contracts live elsewhere (see *Out of scope*); this PR
ships the seams they plug into, fully runnable headless.

Relates to **OSS-360** (runtime bots API), **OSS-361** (run the SDK from
Intelligence events), **OSS-363** (Slack render/codec reuse).

## What's in here

- **`intelligenceAdapter()` bridge** (`@internal`, not publicly
documented) — implements `PlatformAdapter` over two injected transports:
`DeliverySource` (inbound) + `EgressSink` (outbound). Ingress →
`onTurn`/`onCommand`/`onInteraction`/`onThreadStarted`/`onReaction`; ack
on success / nack on throw (at-least-once). Egress emits generic
operations carrying `BotNode[]` IR with **deterministic ids**
(`turnId:seq`, reset per turn) so a redelivered turn reproduces the same
ids for the Connector Outbox to dedupe. Idempotency lives at egress, so
the managed path skips ingress dedup (`skipIngressDedup`) — a redelivery
re-runs rather than being dropped.
- **Runtime `bots` API** — `new CopilotRuntime({ intelligence, bots })`,
accepted by TypeScript **only when `intelligence` is configured**
(discriminated union). `createBot({ name })`; `startManagedBots()`
validates names (required, identifier-style, unique — fail-loud), builds
activation metadata, and wires each bot to its resolved transport.
- **`PlatformCodec` seam** + Slack egress codec (`slackCodec`) composing
the existing pure `renderSlackMessage`, so IR→native rendering is shared
(no Bolt/creds) instead of duplicated.
- **Backwards-compatible SDK foundations**: `bot.addAdapter()` +
optional `adapters`, deferred backend resolution at `start()` with
`stateStore`-provider precedence (+ multi-provider warning),
`bot.transcripts` throws pre-start, optional
`eventId`/`turnId`/`deliveryId` on ingress + handler context. Existing
`createBot` callers and every `PlatformAdapter` implementer are
unaffected.
- **In-memory transports + fixture tests** — the full dispatch path
(envelope in → handler runs → egress op out) runs with zero
Slack/Intelligence/network.

## Out of scope (external / separate tickets)

- **Realtime Gateway + Connector Outbox transports** — implemented in
the closed-source repo against the `DeliverySource`/`EgressSink`
interfaces shipped here.
- **Shared contracts freeze (OSS-377)** — consumed here via a minimal,
isolated placeholder (`managed/contracts.ts`, marked `TODO(OSS-377)`);
swaps in via one import change.
- **OSS-363 ingress normalization** — the egress codec is done;
extracting the pure Slack event→neutral mapping out of the Bolt listener
(so local + Intelligence ingress share it) is the remaining, higher-risk
half and is left to that ticket (`TODO(OSS-363)`).

## Testing

TDD throughout (RED→GREEN per behavior). New: managed adapter
dispatch/ack-nack/ids/run-renderer/exclusivity, all-kinds routing, name
validation + metadata + lifecycle, runtime `bots` option, Slack codec.
Full suites green: `bot` 147, `bot-slack` 256, `runtime` 1574. All
builds typecheck (`bot`/`bot-slack`/`bot-discord`/`runtime`);
oxlint/oxfmt clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-08 12:49:17 -05:00
Benjamin Taylor 654389aa9e chore(examples): bump @copilotkit deps to 1.62.3 [ENT-1051]
The 1.62.3 release publishes the CopilotThreadsDrawer redesign (web-components +
react-core wrapper) and the stateless /suggest feature. Bump the 15 integration
examples that consume the drawer from 1.62.2 -> 1.62.3 (package.json + lockfiles)
so they pick up the released packages alongside this branch's example CSS.

Validated: langgraph-js runs on the published 1.62.3 (no local links) — the
redesigned drawer renders (New Conversation, Recent Conversations, filter funnel,
desktop collapse toggle, per-row kebab), threads are licensed, and a real agent
message round-trips.
2026-07-08 12:23:35 -05:00
Benjamin Taylor 5e0727359f fix(examples): unify header controls + even toggle padding [ENT-1051]
- ModeToggle: one style on both breakpoints (top-4/right-4 = 16px gutter,
  46px min-height, 4px corners); symmetric p-1.5 + fixed 20px button leading
  so the selected pill has an even gap on all four sides (was tight L/R vs T/B).
- Launcher: uniform 16px gutter (top + left) on both breakpoints so it mirrors
  the toggle; drop the mobile-only 7px override.
- Logo: centered on the launcher/toggle middle line (pt-[23px]); wordmark
  padding normalized so its height matches on both breakpoints.
- Inspector FAB: sits beneath the toggle, gap = the 16px top gutter (one rule,
  no media query, since the toggle is identical across breakpoints).

Net: launcher, logo, toggle share center-y; launcher + toggle are both 46px;
the FAB tucks under the toggle with a matching gap; the selected toggle pill is
evenly inset.
2026-07-08 12:23:35 -05:00
Benjamin Taylor 14fa89a674 fix(examples): align header controls — toggle clears inspector, launcher left matches right gutter, logo/toggle on one line [ENT-1051]
- ModeToggle: move left (right-[72px]) so the top-right inspector FAB no longer
  covers the App segment; grow to 46px (lg:min-h) + center on the logo line
  (top-6) to match the launcher; keep the 4px corners.
- Launcher: left gutter -> 16px to match the right-side controls' inset.
- Logo: pt-7 so it centers on the same line as the launcher + toggle.
2026-07-08 12:23:35 -05:00
Benjamin Taylor b69ae43989 fix(examples): mobile header boundary + square the Chat/App toggle to match the drawer [ENT-1051]
- Mobile header: max-lg:pb-0 -> pb-4 so chat content clears the fixed launcher/
  toggle strip instead of butting right under it (no boundary).
- Chat/App ModeToggle: rounded-full -> rounded-[4px] container + rounded-[2px]
  buttons, matching the drawer's 4px radius cap so the header controls are
  visually consistent.
2026-07-08 12:23:35 -05:00
Benjamin Taylor dcec3cb8c4 fix(examples): scope the drawer launcher position override to mobile [ENT-1051]
The 7px/16px launcher inset was tuned for the mobile off-canvas launcher; on
desktop it leaked onto the collapsed cluster. Move it into the mobile media
query so desktop-collapse uses the element's own 24px gutter default.
2026-07-08 12:23:35 -05:00
Benjamin Taylor 115439afca fix(examples): add a gap between the collapsed cluster and the app logo (6rem->7rem) [ENT-1051] 2026-07-08 12:23:35 -05:00
Benjamin Taylor 43e9793cf2 fix(examples): clear the drawer's collapsed cluster from the app header on desktop [ENT-1051]
The floating launcher/collapsed cluster is fixed at the top-left corner. Below
1024px it always shows (already cleared via max-lg:pl-24); on desktop it appears
only when the drawer is COLLAPSED. Drive the header's left padding off
--cpk-drawer-reserved-width (0px when collapsed, 320px default otherwise) so the
logo starts at ~6rem when collapsed and pl-6 when expanded — no overlap. No-op
on current packages (var never set → stays pl-6).
2026-07-08 12:23:34 -05:00
Benjamin Taylor 8344a90475 feat(examples): reclaim the drawer column on desktop-collapse via --cpk-drawer-reserved-width [ENT-1051]
Read grid-template-columns' first track from var(--cpk-drawer-reserved-width, 320px)
so when the drawer collapses on desktop (it sets the var to 0) the reserved
column collapses and the chat reclaims the space — instead of leaving an empty
placeholder column. Mobile (single-column) is unchanged.
2026-07-08 12:23:34 -05:00
Maxim 95430de51a chore(banking): add stop-demo.sh teardown companion to run-demo.sh
run-demo.sh detaches everything except the Next.js dev server (docker
compose up -d, native Metal TEI via nohup/disown, then exec pnpm dev), so
Ctrl-C on the dev server leaves the docker stack and the host embedder
running. stop-demo.sh brings those leftovers down in one command.

Tears down, idempotently:
  - the Next.js dev server on :3000 (defensive; usually gone via Ctrl-C)
  - the docker compose stack (project banking-memory), containers only by
    default so a re-run reuses the built image + seeded data
  - the native Metal TEI on :7067 (Apple Silicon; the host process docker
    doesn't manage), SIGTERM then SIGKILL

Flags: --purge also drops volumes for a clean slate; --keep-tei leaves the
slow-to-warm embedder running when only bouncing the stack.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 18:49:34 +02:00
Benjamin Taylor 71a4ac42e4 Merge origin/main into alem/oss-360-sdk-foundations
Brings the 499-commit-stale foundations branch up to date with main so #5761
has a clean diff and no stale reverts (e.g. forwardHeaders). Conflicts:
- CopilotThreadsDrawer.tsx: took main's (main renamed CopilotDrawer -> ThreadsDrawer
  + added the collapse feature; the branch's edit was a no-op import-type split).
- pnpm-lock.yaml: regenerated with the pinned pnpm 10.33.4 (adds @copilotkit/bot-intelligence).
2026-07-08 11:01:58 -05:00
QA Agent e743c28df7 docs(deepagents): add complete TypeScript state streaming examples
- Add full StateGraph + Annotation setup with CopilotKitStateAnnotation.spec
- Show complete tool implementation with proper ToolMessage handling
- Include graph compilation with nodes, edges, and routing logic
- Pattern examples after working shared-state-streaming.ts reference
- Fix both Deep Agents and LangGraph docs versions
- Include formatter fixes for JSON files

Fixes FAC-101
2026-07-07 13:41:03 -07:00
Maxim 258820e4ce fix(banking-demo): cap native TEI warmup batch to survive Metal fault
The self-hosted `run-demo.sh` path launches a native Metal
`text-embeddings-router` on :7067 for the durable-memory demo. TEI's
default `--max-batch-tokens` (16384) can fault the Metal backend during
its warmup forward pass on some Apple Silicon machines. The process then
either deadlocks (every thread parked in a pthread cond wait at 0% CPU)
or dies silently with no panic — a GPU-level abort — so it never binds
:7067 and the 300s health wait times out. The demo appears to "crash"
with no actionable error.

Pass `--max-batch-tokens 512` so warmup uses a small forward pass, which
clears reliably. This only bounds per-request tokens (memory texts are
short), not the embedding vectors, so recall stays byte-identical to the
docker/CI embedder.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 16:18:35 +02:00
David McKay ad89876df1 Merge branch 'main' into feat/banking-durable-memory 2026-07-06 10:12:52 -05:00
github-actions[bot] 57ec68ecf9 style: auto-fix formatting 2026-07-06 14:22:05 +00:00
Maxim 6d5d407624 fix(banking): make fresh setup work on Apple Silicon (native TEI + run-demo.sh)
The bundled tei embedder image is amd64-only; under arm64 emulation the Candle
backend is unavailable and TEI falls back to the ONNX/ORT backend, which needs
onnx/model.onnx files Qwen3-Embedding-0.6B doesn't publish (404) -> crash-loop.
A fresh clone on Apple Silicon therefore couldn't stand up the embedder, so
memory save/recall were dead. Ports the proven pattern from the Intelligence
repo's docker-compose.deps.yml + demos/splat-demo/run-demo.sh into this demo:

- docker-compose.yml: gate the bundled `tei` behind the `cpu-fallback` profile,
  so a bare `docker compose up` skips the crash-looping emulated image. amd64/CI
  opt back in with `--profile cpu-fallback`. (intelligence's tei dep is
  required:false, so it starts fine without it, using MEMORY_EMBEDDINGS_URL.)
- run-demo.sh: one-command cold start. On Apple Silicon it runs a native Metal
  TEI on :7067 (same 1.9.3 + Qwen3-Embedding-0.6B => byte-identical embeddings,
  ~20x faster) and points app-api at it; on amd64/CI it uses the docker tei via
  the profile. Mints a dev license if .env lacks one, then starts `pnpm dev`.
- README: correct the failure description (emulation->ONNX crash-loop, not OOM),
  document run-demo.sh as the recommended start, and the profile-gated manual path.

All CopilotKit-repo-only (banking's compose is standalone); no Intelligence
changes. Validated: shellcheck clean, compose valid, bare `up` skips tei and
keeps intelligence healthy, memory save/recall verified through the native TEI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 16:20:03 +02:00
Maxim 771f78c095 docs(banking): document PRESENTER_RESET_ENABLED 2026-07-06 16:20:03 +02:00
Maxim bfb91085e4 feat(banking): add env-gated presenter reset button to sidebar 2026-07-06 16:20:03 +02:00
Maxim 86ef09cdb3 feat(banking): thread resetEnabled flag to the layout 2026-07-06 16:20:02 +02:00
Maxim 271928249d fix(banking): report partial progress on reset memory failure 2026-07-06 16:20:02 +02:00
Maxim 7cbbaef5a9 feat(banking): gate reset endpoint on flag, forget all personas 2026-07-06 16:20:02 +02:00
Maxim 8be514df0b feat(banking): export SEEDED_USER_IDS for full-slate reset 2026-07-06 16:20:01 +02:00
Maxim 9744c104e2 feat(banking): add presenterResetEnabled env flag 2026-07-06 16:20:01 +02:00
Maxim 157d9fc723 feat(banking): reproducible dev-license mint helper (self-hosted memory)
Phase 3 of the banking->Intelligence-main migration. Self-hosted Intelligence
gates the paid `memory` feature behind a signed offline license; a locally-built
(unbaked) app-api trusts a runtime BAKED_LICENSE_KEYS_JSON, so a throwaway
keypair can sign an enterprise license with features.memory=true.

- scripts/mint-dev-license.mjs: prints (or --write upserts into .env)
  COPILOTKIT_LICENSE_TOKEN + BAKED_LICENSE_KEYS_JSON + INTELLIGENCE_DEPLOYMENT_MODE.
  Drives the signer from the PRIVATE Intelligence source via INTELLIGENCE_REPO
  (same coupling the docker-compose image build already has) rather than
  vendoring any signing code into this public repo. No secret is embedded; the
  script is dev-only and never imported by the app runtime.
- .env.example: documents BOTH the managed path (CopilotKit-issued token, no
  baked key — the eventual hosting target) and the self-hosted dev path, so the
  demo is not locked to the local stack.
- package.json: add `mint-dev-license` script.

Replaces the ephemeral Intelligence/tmp/mint-banking-license.ts. .env stays
gitignored; nothing sensitive is committed. Local-only until verified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 16:20:01 +02:00
Maxim 3b1e04275e chore(banking): rename memory kinds to Intelligence main enum
Phase 2 of the banking->Intelligence-main migration. Main's memory lib
(libs/memory/src/types.ts) closes MemoryKind to topical|episodic|operational;
the demo was authored against the legacy semantic|procedural names, which the
backend now rejects/misfiles. Rename across the whole surface:
- agent prompt (route.ts CLASSIFY + SAVE-THE-PROCEDURE): semantic->topical,
  procedural->operational
- recorder instruction (copilot-context.tsx), learning-tab dual-read dropped,
  memory-tab KIND_COLORS, memory unit-test fixture
- smokes (facts + drift) and the e2e spec seed + fixtures comment

Only true kind: values renamed; "semantic recall"/"top-k semantic search"
mechanism descriptions left intact (recall is vector search regardless of enum).
aimock fixture re-record was a no-op: the one fixture pins the recall-and-apply
arc (no kind: values); the seed is REST-side in the spec.

Verified: pnpm test:unit 47/47, tsc --noEmit clean, eslint clean on touched files.
Local-only until the full migration is verified against the main stack.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 16:20:00 +02:00
Maxim ccd1c974f5 wip(banking): migrate compose auth to Intelligence main (Phase 1 spike)
Phase 1 of the banking->Intelligence-main migration (branch:
feat/banking-intelligence-main-migration). PROVEN GREEN against main:
- INTELLIGENCE_DEPLOYMENT_MODE=self_hosted (renamed from legacy DEPLOYMENT_MODE)
- dropped legacy DEFAULT_ORGANIZATION_ID (main's loadAuthEnv rejects it)
- BAKED_LICENSE_KEYS_JSON wired: main gates memory behind a signed license
  carrying the "memory" feature (MEMORY_NOT_ENTITLED otherwise). A locally
  minted dev enterprise license + baked public key unlocks it (recipe mirrors
  Intelligence apps/app-api-e2e global-setup). Verified: /mcp attaches
  recall/save/forget_memory and save_memory(kind=topical) round-trips via the
  cpk key.

REMAINING (next session): (1) reproducible dev-license mint helper + .env wiring
(mint script currently at Intelligence/tmp/mint-banking-license.ts, ephemeral);
(2) kind rename semantic->topical, procedural->operational across prompt, memory
lib, smokes, e2e spec; (3) aimock fixture re-record for new kinds; (4) re-verify
e2e/smokes/manual arc. Working demo (PR #5763, demo branch) is untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 16:18:52 +02:00
github-actions[bot] 40fe2c64a6 style: auto-fix formatting 2026-07-03 18:15:03 +00:00
Maxim f568c7e3d6 fix(banking): tell the agent to omit save_memory supersedes unless it has a real memory UUID 2026-07-03 19:30:56 +02:00
Maxim ca5f6f7da9 test(banking): use UUID thread/run ids in smokes (backend validates thread id as UUID) 2026-07-03 17:26:39 +02:00
Maxim 277b037193 test(banking): smokes preflight the demo dev server for a clear 'run pnpm dev' error 2026-07-03 17:23:45 +02:00
Maxim 84095d63ec test(banking): add /mcp readiness gate to memory smokes; document backend boot-window flake 2026-07-03 17:17:50 +02:00
Maxim fba5b085c3 test(banking): drain full turn in drift smoke so rule-9 negative save assertion is reliable 2026-07-03 16:28:24 +02:00
Maxim c3728848c2 fix(banking): add memberId to learning-tab fetch useCallback deps 2026-07-03 16:22:38 +02:00
Maxim 40babda9d0 docs(banking): document general memory and the 2-persona cross-user demo 2026-07-03 16:14:26 +02:00
Maxim 6bbe4bb819 test(banking): add real-LLM general-memory smoke (save/no-save/recall/isolation) 2026-07-03 16:12:16 +02:00
Maxim c401b3d4e3 test(banking): drift smoke asserts identity and no spurious save in teach flow 2026-07-03 16:12:12 +02:00
Maxim 0c9c16a4e2 feat(banking): teach the copilot general durable memory for facts and preferences 2026-07-03 16:08:18 +02:00
Maxim cb52e5f9a4 feat(banking): unpin identity for the live demo so persona switch drives memory 2026-07-03 16:03:49 +02:00
Maxim 72a42e6227 feat(banking): reduce roster to two personas for 1:1 memory identity 2026-07-03 16:02:52 +02:00
Maxim f9d798255b feat(banking): forward active member id to runtime and inspector proxies 2026-07-03 15:58:44 +02:00
Maxim 04d155639c feat(banking): resolve memory identity from member id across runtime and proxies 2026-07-03 15:57:01 +02:00
Maxim 40024c9be8 feat(banking): map member id to seeded identity for memory scope 2026-07-03 15:51:22 +02:00
Markus Ecker 7b72bd491a Merge branch 'main' into mme/memory-core 2026-07-03 10:20:47 +02:00
Benjamin Taylor 9b5a124a1c chore(examples): normalize @copilotkit/runtime pins to raw versions
The langgraph/strands examples pinned @copilotkit/runtime via a
self-referential npm alias (npm:@copilotkit/runtime@x) left over from the
de-fork branch (2155821b8), where it forced registry resolution while
react-core used workspace:*. That alias is functionally identical to a
raw pin and react-core was already reverted, so drop the alias in the four
remaining files (langgraph-fastapi, langgraph-js, langgraph-python,
strands-python) and regenerate their lockfiles.
2026-07-02 18:08:32 -05:00
Benjamin Taylor b0ea64c718 chore(examples): bump integration scaffolds to @copilotkit 1.62.2
Bump the 16 integration examples already on the 1.62.x line from 1.62.1
to 1.62.2 (the just-published release), including their in-tree agent
sub-packages (langgraph-js/agent sdk-js, agentcore CDK lambda runtime)
that had drifted to 1.61.0. Regenerated the co-located package-lock.json
files against the published 1.62.2.

a2a-a2ui and agent-spec remain at 1.61.0 (QA-held; out of scope).
2026-07-02 17:55:47 -05:00
Maxim 634e1d908f docs(showcase): fix banking docker-compose header infra port comments
Header documented 70xx ports but actual host-port mappings default to
71xx. Update postgres/redis/minio/minio-console/tei comment ports to
match the real mappings. Comment-only; no ports: mapping changed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 00:47:51 +02:00
Maxim af44459e74 fix(showcase): record approve step before beginRecording resets the feed
In handleApprove for both TransactionsList (transactions-list.tsx) and
PendingApprovalsChat (wow/pending-approvals-chat.tsx) the recorder-feed
narration ran in the wrong order:

    logStep("Approved the charge");
    beginRecording();
    endRecording();

`logStep` early-returns unless `activeRef.current` is true, and that ref is
only set inside `beginRecording()`. Worse, `beginRecording()` calls
`setSteps([])`, resetting the feed. So calling `logStep` first was a no-op and
the "Approved the charge" line never appeared in the recorder HUD.

Reorder to match the correct pattern already used in policy-exception-inline.tsx:

    beginRecording();
    logStep("Approved the charge");
    endRecording();

Adds recording-context.test.tsx (vitest + testing-library): a provider-level
ordering invariant plus a component-level test that clicking Approve in
PendingApprovalsChat lands "Approved the charge" in the feed. RED verified
(step dropped with the inverted order) / GREEN with the fix.

Call-site enumeration (grep logStep/beginRecording/endRecording, all src):
- transactions-list.tsx handleApprove — FIXED (was inverted)
- wow/pending-approvals-chat.tsx handleApprove — FIXED (was inverted)
- policy-exception-inline.tsx handleSubmit — already correct (begin -> logStep -> end)
- transactions-list.tsx:254 / pending-approvals-chat.tsx:184 "Opened the
  exception form" — logStep inside an already-active window; correct
- dashboard/page.tsx, layout.tsx — unconditional nav/tab logStep that
  correctly no-ops when no recording is active; correct
No other site has the inverted begin/log order.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 00:47:50 +02:00
Maxim ad922750cf fix(showcase): align banking memory docs/smoke to kind procedural
The durable memory feature saves kind:"procedural" (route.ts:150) but the
README and drift-smoke script described/seeded kind:"operational", a
doc/code contradiction. Update both to procedural. The learning-tab
back-compat (operational || procedural) is intentionally left untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 00:47:50 +02:00