mirror of
https://github.com/CopilotKit/CopilotKit.git
synced 2026-09-14 16:26:20 +08:00
codex/cloudplot-showcase-migration
9 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
acac2b7f27 |
docs(reskinnable-demo): correct the in-code comments the beat-parity wave slots could not reach
Comment-only, no behaviour change. Each of these sat OUTSIDE the boundary of the slot whose work falsified it, so each described the tree as it was mid-migration. All verified against the current tree before editing. src/shell/skin-contract.ts - `RuntimeProviders`: "airline needs neither, so omits it". Airline omits `RuntimeProviders` and DOES supply `useRuntimeProperties` — the two are SEPARABLE, and airline is now the worked example: one account holder, no switcher, so its hook reads no context and returns a frozen module constant. Do not mount an empty provider for symmetry. - `useData`: "Omit when a skin has no shell-managed data (banking …)". Every skin omits it now; documented with the grep, plus WHY the field is kept (the shape is legitimate, it just has no worked example left). - `CanvasSurface`: the "omit if the skin has no report canvas" branch is currently unexercised — every shipped skin has one. src/shell/agent-registry.ts - The logistics entry said it ships "neither `intelligence/seed-memories.ts` nor `intelligence/forget-memories.ts`" and is "identity plumbing only — do NOT read it as a durable-memory demo". It ships both (`ls src/skins/*/intelligence/`), and its `dev/reset` sweeps and re-seeds through them. Corrected, with the same properties-forwarding caveat the other five entries carry, and a note that "expensive half built, cheap half skipped" was its state for two releases. src/skins/keel/data/types.ts - The `THE REST SUBSTRATE` banner said the two substrates are "deliberately not merged yet", that `useKeelData` "holds runs in `useState` and ticks them on a 900 ms interval", and that "the pages still read it through `useSkinData`". All three are false: one substrate, one clock, `useSkinData` returns undefined. Rewritten to name the server-settled read (`settle-runs.ts`, called by both `GET /ledger` and `GET /runs/[runId]`) and to record WHY the deleted client ticker was a defect rather than a design choice — it was a second clock that painted progress the server never heard of, which the next re-read after any write silently rewound. - The `KeelData` interface header claimed to be "the interface every page, component, and tool codes against". It is not referenced by any code at all (`grep -rn KeelData src` returns only comments). Marked HISTORICAL, with a do-not-add-a-consumer note. NOT deleted: it is a doc pass, several comments across the skin describe the migration in terms of this shape, and removing an exported type is a code change for a separate commit. Flagged as a follow-up. src/skins/keel/data/store.ts - "it does not advance them on a timer, because the ticker lives in `useKeelData` on the client. Whichever slot migrates that hook has to decide where the ticker ends up" — decided: the server is the only clock now. src/skins/keel/data/beat-map.md - Header: "Keel today is `useKeelData`, an in-memory `useState` store, and it hits about one beat." Marked BUILT and reframed as the design record. - Risk #2 (the two-substrates/ticker question, correctly called "the biggest single risk in the migration") marked RESOLVED, with the answer (move the clock, do not relocate the ticker) and the generalised lesson. src/skins/airline/data/beat-map.md - Header: the tools/prompt/pages/pills were "later slots". All landed. - § "What this slot did NOT build": every row of the deferral table has shipped. Kept as the retrofit record — which is the most useful thing about it — with a third column saying where each landed, and the three flagged traps marked resolved (including "the reset route says memoryBeats: unarmed on purpose", which was removed in exactly the change that added the seed module, as instructed). src/skins/airline/data/fare-waiver-codes.ts - "⚠️ THE LINT GUARD DOES NOT COVER THIS SKIN YET." It does: both `src/skins/airline/tools.tsx` and `agent.ts` are in `withheldGateVocabulary`'s `files` glob. Also dropped its "COUNT the selectors" instruction (that count has rotted twice) in favour of the resolved-selector table in `skins-config.test.ts`, and spelled out that a green lint still leaves the three prose channels AND `waiverGround` — which matches no `*_CODES` pattern, so the rule cannot see it — as hand-review items. src/skins/airline/tools.test.ts - Header said `statusKeyedTerminalRender` "covers logistics only; airline's glob entry is a later slot's, so until it lands this file is the whole guard" and that `withheldGateVocabulary`'s glob "does not list airline yet either". Both globs list airline now. Also fixed "Three defect classes" over a list of five. src/skins/keel/skin.tsx - "exactly as it does for the four other REST-backed skins" → every skin; nothing sets `useData`. src/proxy.ts - "matching how the other three skins behave" → numeral-free. This was one of the two known-stale instances named in `skin-roster-docs.test.ts`'s header; that header is updated in the app-docs commit, and the remaining one (`e2e/inset-layout.spec.ts`'s hardcoded four-skin loop) is deliberately left — fixing it means adding assertions against skins the spec has never visited, which is a coverage change rather than a prose fix. docs/teach-mode/README.md - It correctly refuses to write the roster into prose, but its verified-by-role paragraph named only banking/commerce/logistics/people and its "so copy commerce or logistics" line named the only two skins with pinned replay behaviour. The `offerWorkflowRecording` grep now returns every registered skin, and `ls src/skins/*/teach-mode-directives.ts` — added as the mechanical discriminator for role #3 — returns four. Also: "logistics and commerce both" skip project-scoped rows in `forget-memories.ts` is now every skin but banking, replaced with the grep that proves it. Does this make anything in .claude/skills/reskin/ stale? No — the reverse. The preceding commit updated the skill for exactly these facts, and these comments were brought into line with it. Checked: `grep -rn "useKeelData\|use-data\|in-memory" .claude/skills/reskin/` names no path or symbol that no longer exists. Verified: pnpm lint, pnpm exec tsc --noEmit, pnpm test:unit (197 files / 2227 tests), pnpm build — all green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
b5800c35b6 |
docs(reskinnable-demo): fold logistics into the teach-mode roster
The standing rule at the top of CLAUDE.md, answered out loud: YES, this change made things in `.claude/skills/reskin/` and its neighbours wrong. Logistics is now a FOURTH teach-mode skin, and four separate places were written against three. The DERIVATIONS the previous commit introduced all still read correctly — `grep -l offerWorkflowRecording src/skins/*/tools.tsx`, `grep -rln useAgentContext src/skins/*/layout.tsx` and `ls src/skins/*/intelligence/seed-memories.ts` each pick logistics up automatically, which is exactly what they were converted for. What rotted was the PROSE around them: - `docs/teach-mode/README.md` enumerated a role-by-role verdict for every skin the roster grep returns. The grep now returns four and the paragraph named three, so a reader would have found logistics uncertified with no way to tell whether that was an omission or a verdict. Logistics satisfies all five roles; it is also a second worked example of the pinned replay directives, so "so copy commerce" now names both. - That file's memory-SCOPE divergence note gave only half the argument for `user` over `project`. The half it was missing is the decisive one: a skin whose `forget-memories.ts` skips project-scoped rows — logistics and commerce both do — has a presenter reset that physically cannot un-teach a project-scoped memory, so the second run of the demo opens already taught and the beat proves nothing while looking perfect. - `failure-modes.md` § 10 described withholding the vocabulary from the agent and never said to BUILD the surface the operator demonstrates on. Withholding perfectly with no filing form is an unlearnable gate — which is the state logistics was actually in. Points at the worked example and the two load-bearing properties of it. - `demo-beats.md` said the pre-bar skins "ship four or five" pills. Logistics ships ten. Fixed, and the sentence now says so as the reason to run the count rather than trust the prose. `CLAUDE.md`'s beat matrix gains logistics' teach-a-procedure row, and its logistics bullet is corrected: it claimed the skin omits `chatHeaderActions` and `onSuggestionSelect`, which beat 3d set two commits ago. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
da69dea5c5 |
fix(reskinnable-demo): stop the beat-6 rule block disabling the LOCK_SKIN guards
Flat-config `rules` options are REPLACED, not merged. The beat-6 block added in
|
||
|
|
f39a6fb0b4 |
fix(reskinnable-demo): withhold logistics' escalation vocabulary from the agent
Beat 6 claims the agent learns an unknown procedure by watching once. An
agent holding the unlock vocabulary already knows it, clears the gate
unaided, and there is nothing to teach.
Logistics published the catalogue FOUR ways, not the three the plan named:
a useAgentContext readable described as "valid escalation codes", a
z.enum(ESCALATION_CODES) on fileEscalation's schema, that tool's own
description pointing at "the catalogue in your context", and an agent.ts
RULES line listing the codes among what is "provided". Closing three of
four moves the leak rather than closing it, so all four are closed: the
code parameter is now a free z.string() whose describe() states the
withholding, and the prompt names escalation codes as the one thing NOT in
context. The route already refused an uncatalogued code without
enumerating the valid set (audited, unchanged).
The justifying/decoy split and checkAuthority are unchanged, and
escalation-codes.test.ts already covered the predicates, so no test was
added. The guard is instead a new AST no-restricted-syntax rule,
withheldGateVocabulary in eslint.config.mjs, scoped to
src/skins/logistics/tools.tsx: every symptom here is invisible (the app
compiles, type-checks, lints and demos with the readable restored), and the
schema leak was line-wrapped, so a source-text guard would silently never
have matched. It was verified RED (6 errors, including the wrapped :268
enum) before the removals and green after.
docs/teach-mode/verify-logistics-gate.sh proves the gate over pure REST
with no agent: refusal names the symptom and no code, a decoy records and
approves without unlocking, an uncatalogued code is refused without
enumerating, a justifying code lifts the gate. It diverges from the plan's
draft on four audited facts — mitigate requires plannerId and answers 403
OVER_AUTHORITY (not 422 ABOVE_APPROVAL_AUTHORITY); "absorb" always costs
$0 and can never be over authority, so the script discovers the bounded
planner, the exception shipment and the over-authority KIND (expedite)
from the live API; and the refusal legitimately names the generic recovery
path ("file an escalation"), so the leak assertion is that it names no
CODE.
Skill staleness (CLAUDE.md standing rule): YES, the reskin skill was wrong
here and is updated in this commit. SKILL.md and templates.md told every
author to enumerate closed-set parameters with z.enum "so the vocabulary
reaches the model" with no carve-out — the exact advice that produced this
defect; all three sites now carry the beat-6 exception. failure-modes.md
gains § 10 (the five leak channels, why the guard is a lint rule, and the
requirement to append your skin to its files glob), renumbering the old
§ 10 to § 11. demo-beats.md's beat-6 part 3 and SKILL.md's beat-6 walk step
now name the channels and the REST proof.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
190be901d5 |
refactor(reskinnable-demo): migrate people and commerce onto the shell teach module
Both gain the visible-duration floor, the feed de-dupe and the automatic fresh-window reset they were missing; both lose their manual reset() and their per-skin @keyframes, which the shell's token-driven .recording-vignette replaces. Six copies of the ref-counted state machine are now one. Skill impact: checked. `.claude/skills/reskin/demo-beats.md` item 4 already points at `@/shell/teach` (Task 2), and neither SKILL.md nor templates.md teaches a per-skin recording context or per-skin vignette keyframes, so nothing there went stale. One live doc DID: `docs/teach-mode/README.md`'s role table still named the banking copy Task 2 deleted — repointed at `src/shell/teach/`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
d9dcf69893 |
docs(reskinnable-demo): update the app docs for a six-skin roster
`CLAUDE.md`, `README.md`, `.env.example` and `docs/teach-mode/README.md`. The roster went from four skins to six, and almost every count derived from it was wrong. Corrected here: - The demo-beat matrix, which now lists `commerce` and reports gen-UI counts that match the registrations actually made. - The `useData` contract row, which names BOTH in-memory skins rather than one. - The list of skins that identify their user, and the list that ship `intelligence/seed-memories.ts` -- `commerce` was missing from both. - `.env.example`, which capped `LOCK_SKIN` at four legal values. - The claim that `people` re-scopes memory per operator, stated more strongly in CLAUDE.md than the code supports. Two decisions about HOW the docs were fixed, because they cost the most time: - CROSS-SKIN CLAIMS ARE SCOPED TO THE SKINS ACTUALLY CHECKED. Several sentences asserted a property of "every skin" on the evidence of one or two. They now name the skins verified. - EACH FIX WAS CHECKED AGAINST THE SENTENCE BESIDE IT. Correcting one count repeatedly left its neighbour false, because the counts are stated redundantly in adjacent prose. That pattern is what motivated the roster test in the shell. Subsumes: 7f5813d7ea 1600591918 8071d05812 f78f6f7cd4 ca2145228d ad76437e1c 4308c02135 3fab172fb1 0ca1564406 f0afa4acce Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
3d4de1cedd |
feat(reskinnable-demo): add the people skin (Rowan), a demo-complete People Ops desk
Rowan is a People Operations command center and the second skin built against
the full nine-beat bar in `.claude/skills/reskin/demo-beats.md` (banking was the
first). Pages: Roster (index), Compensation, Requests, Onboarding.
REST-backed like banking and logistics: `/api/people/v1/*` serves one `ledger`
snapshot read plus the write paths, a generated `offer-letter` PDF, and a
presenter-gated `dev/reset`. Components read the ledger through the skin's own
`usePeopleLedger()` context, so `useData` is omitted. That context is mounted in
`RuntimeProviders` rather than `Providers`, which lets the single fetch also feed
`useRuntimeProperties`.
The signature element is the band ladder: one rail per level, each normalized to
its OWN band, so "halfway up L3" and "halfway up L7" line up at the same height
and become comparable. Anyone outside their band is drawn outside the rail, in
the negative colour, always labelled.
Beats, all walked in a browser against a live Intelligence stack:
1 face showCompBands renders the ladder + a two-sentence answer
2 rich thread gen-UI replays intact on reopen after a hard reload
3a drive the app setBaseSalary — the figure is typed into a chat card and
goes straight to REST; it appears nowhere in the transcript
3b sees screen route readable + per-page on-screen readables on all four
pages; Roster and Requests give different, correct answers
3c levers HITL confirm naming the levers, then
?status=pending&sort=aging_desc&top=10 with the Status, Sort
and Show controls visibly tinted, "TOP 10 OF 11"
3d multimodal an offer-letter PDF rides the pill, and the filed packet
survives deleting the thread and reloading
4 memory seeded preference recalled AND named in the component's
`note` slot
5 stored skill one vague sentence fires three visible writes in order, no
confirmations, amid four distractor tools
6 teach a skill 422 OUT_OF_BAND (symptom only) -> decline -> record the
demonstration -> save -> apply unaided to a DIFFERENT person
in a fresh thread
Notes for reviewers:
- The beat-6 gate is deliberately discriminating. Decoy exception codes file and
finalize successfully and still do not lift it, and an unknown code is refused
without enumerating the catalogue — so "the agent filed an exception" is not
the same as "the agent cleared the gate". Two out-of-band comp requests are
seeded so the case taught on stage and the unaided replay are different people.
- Seed dates are relative offsets materialized at store init, not absolute ISO
strings, so request aging and the generated offer letter stay coherent years
from now and a Reset genuinely re-freshens the queue.
- Memories are seeded and saved at `user` scope, not `project`. Verified against
the running stack: a project-scoped row is returned for EVERY user id in the
instance, so with several skins sharing one backend it is not a per-skin
boundary. For the same reason this skin's `forgetAllMemories` skips
project-scoped rows rather than deleting data it does not own, and `dev/reset`
reports the skipped count.
- `temperature` is not set. gpt-5.4 rejects it and the value is discarded, so
carrying it alongside a comment claiming determinism would be misleading.
- Beat 2 additionally requires the thread-list identity fix sent separately; the
skin merges and runs fine without it, it just cannot demo thread reopen.
Docs updated for the fifth skin per the app's standing skill-staleness rule:
CLAUDE.md (skin list, substrate split, beat matrix), README.md,
docs/teach-mode/README.md (teach-mode is now per-skin, not banking-only), and
`.claude/skills/reskin/{SKILL,demo-beats,templates}.md` — including six
"only banking does this" claims that are no longer true.
Verified: pnpm build, pnpm lint, pnpm test:unit (335/335) on this base.
Co-Authored-By: Claude <noreply@anthropic.com>
|
||
|
|
7aab1bead2 |
docs(reskinnable-demo): document the inset frame and retire the old chrome
The reskin skill was the urgent part: it is the sanctioned path for adding a skin, and it still taught two patterns the frame retired. It told authors to publish --nw-nav-inset-left/right from a useEffect so the floating selector could dodge their nav -- both the variables and that selector are gone -- and to root the layout at h-screen overflow-hidden, which overflows the app card by the frame's padding. Following it produced a skin with dead code and a broken root height. The nav-inset step is removed with a short "Retired" note so it is not reintroduced by copying an older skin, and the root guidance now explains that the CARD is the bound. Adds a "The inset frame" section to CLAUDE.md covering what a reader needs before touching src/shell/layout: the two-panel model and its bounds, why the thread rail is a fixed element rather than a nested panel, the v4 API rename and the id-becomes-data-testid behaviour, where the shell controls live, the fixed 12px card radius, and the h-full requirement for skin layouts. Also corrects the composition chain, the shell's ownership list, and the four-skins-not-two count across CLAUDE.md, README.md and DESIGN.md, plus the skill's verification step, which told authors to look for their skin in a bottom-left floating pill. |
||
|
|
1387f32dee |
docs(reskinnable-demo): document the architecture and add the reskin skill
Describes the app that exists: shell versus skins, the Skin contract field by field, the client/server boundary that keeps a skin's agent out of the browser bundle, per-skin server identity, and the theming split. Adds a repo-local authoring skill that walks someone through creating a skin and registering it in both registries. The inherited docs described a single-skin banking demo, which was actively misleading once a second skin shipped, and carried claims that were false here — that OGUI can only render inline in the chat (a published-SDK limitation that does not apply on workspace packages) and that the airline skin omits every optional contract slot when it ships nine tool labels. |