amicode: widget-kernel — home dashboard, in-chat widget authoring, Amico presence, clipboard/model bridges (fork half of amicode#136) - #20
Merged
Conversation
Prepend 'Aero' to the AMICODE wordmark/logo font-family chain (logo.tsx, wordmark-v2.tsx), matching each file's current fallback stack. Additive only. Re-applied fresh after the branch fast-forwarded 57 commits to current origin/local/amicode — this had been uncommitted WIP on the old base. Aero is donationware (Nirmal Biswas / Picatype, $25+) — bundled preview- only, must be licensed or replaced before any release. See AMICODE- PATCHES.md #15.
The chat composer's handlePaste bailed out silently whenever event.clipboardData was empty — which it always is inside the sandboxed cross-origin webview iframe (navigator.clipboard is denied there too). Cmd/Ctrl+V into the composer was a no-op. The extension side of this bridge already ships on main (chat_panel.ts answers clipboard-request), and home-cards.tsx already proved the pattern for a different input. This wires the same bridge into the main composer: platform.readClipboardText (new, mirrors readClipboardImage) -> entry.tsx implements it via the postMessage bridge when framed -> attachments.ts falls back to it when clipboardData yields no text. See AMICODE-PATCHES.md #16 for the full trace + build/verify evidence.
Live test (Aaron) found the prior commit's fix was composer-only: pasting into a generic "Connect <provider>" API-key dialog (dialog-connect- provider.tsx - one of many such plain-input settings forms) was still a silent no-op, since that input has no knowledge of the bridge. Same root cause, generalized properly: one document-level paste listener (installGlobalPasteFallback, entry.tsx) covers every form field and contenteditable in the app, activating only when the native paste event gave no text (the sandboxed-iframe symptom) - a no-op everywhere clipboardData already works. The composer's own handler stopPropagation()s on every paste it handles, so it never double-fires there. See AMICODE-PATCHES.md #16 addendum for the full trace + build evidence.
QNode {id, prereqs, relevant?(value predicate), optionsFrom?, batchable};
frontier(graph, answers) returns answerable-now nodes (prereqs met AND
optionsFrom answered AND relevant AND not-yet-answered). Value-dependent and
relevance-pruning guardrails both covered. v1 = tested reference the SCORE
batching policy mirrors (not runtime-wired; spec §4.1). 6/6 bun test.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chipText (system): composite branch -> compositeChip (N=1 matches the legacy flat chip; N>1 = "platform · N×role · kind · arch"); entityRows: composite branch -> compositeSystemRows (component-table + coupling-list, not a JSON blob); new systemProjection (composite read-through; flat collapses to N=1 with isComposite flag). All parse BOTH shapes defensively in place -- the fork repo cannot import the plugin normalizeSystem (spec §3 cross-repo). Never throws. +5 tests; 73/73 amicode-ui bun suite green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bring the fork mainline up to date with the merged upstream stack (PRs #6–#12): onboarding wizard, Library upload, brand-mark consolidation, receipt-card + entity-view redesign, Inspect Run button, chat-jitter/reduced-motion fix, accent-rail removal. Conflicts resolved: - logo.tsx: auto-merged; the local 'Aero' font-family prepend survived origin's brand-mark rewrite (verified line 112 + wordmark-v2 intact). - AMICODE-PATCHES.md: kept both sides. Local Aero (#15) + composer paste bridge (#16) preserved; origin's mark-drift entry renumbered 15 -> 17 to sit after them. Local Aero + paste-bridge commits (a4fd244/c811798/b868a59) retained — still local-only WIP. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New facets.ts (pure). receipt.ts short()/problem.ts shortValue() delegate to compactValue — arrays/objects render as compact summaries, never raw JSON blobs. Spec §4 / plan Task 1. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…sk 2) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ask 4) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
spec §6.1 / plan Task 5. Thin SolidJS over systemProjection + system-render models; theme-aware --v2-* CSS. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
spec §5,§6.1 / plan Task 6. entity-view routes system→SystemComposite (generic field-row path retired for system; Hamiltonian moved to the hero). card.tsx renders systemReceiptPieces (semantic +/−/change, or post-state compositeChip on creation/large/elided) instead of JSON diff pieces. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ey) + shared corpus spec §6.2,§9 / plan Task 12. Defensive legacy/structured projection (never throws, raw passthrough on unknown enums), derives primaryKey from type+free_phase+time_mode, synthesizes derivedFinalFidelity for min_time. Re-implements the §10 mapping in place (no cross-repo import), locked to the amicode corpus by a byte-identical fixture mirror. 9 tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…m problem_type (spec §6.3 / Task 13) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… + constraints) spec §6.2 / plan Task 14. Mode-badge header via modeBadges; derived primary objective headline + OBJECTIVE_LATEX (keyed by primaryKey, distinct from ObjectiveKind); added-terms + typed-constraint rows (incl. the synthesized min-time final_fidelity row); solve scalars. Theme-aware --v2-* CSS. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ask 15) entity-view routes formulation→FormulationView (generic field-rows gated off for both hero kinds). card.tsx generalizes the system receipt path to a hero path (system|formulation): formulationReceiptPieces renders mode transitions / flag +/− / objective+constraint setDiff, or the post-state mode-chip on creation/large/elided. 107 fork tests green; typecheck clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nk grid/flex children Grid/flex children defaulted to min-width:auto, so long history notes / table params forced the dialog content wider than its frame and clipped the right edge (timestamps). Add min-width:0 + overflow-wrap:anywhere on the offending children (history summary, system table params, formulation constraints/solve) and overflow-x:auto on the LaTeX blocks. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…bulletproof dialog overflow
- systemHamiltonianLatex: derive an illustrative Hamiltonian for ANY composite
(drift per role + interaction per coupling kind + drive) so the System hero
shows math for cavity+qubit/etc., not just transmon/rydberg ("show the system").
- param symbols (ω/δ/χ/J) in the component table; unit-suffixed keys kept.
- formatTs: compact ISO ("07-10 15:53") for history + Updated — cleaner, no clip.
- overflow: container overflow-x:hidden + min-width:0 down the timeline/event
chain + nowrap compact timestamp → history no longer bleeds past the frame.
110 fork tests green; typecheck clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…el bleed) The fit Dialog sizes to content; the wrapper only set overflow-y, so a wide child (long history line) bled past 680px, grew the panel, and clipped both edges. Set overflow:auto + min-width:0 + max-width:90vw so the 680px box holds and content wraps within it. Root cause of the "still cut off" reports. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…fit-panel growth) The fit Dialog was measuring the scroll-width of a nowrap child (the katex Hamiltonian) through the wrapper's overflow-x:auto, growing the panel to ~1170px and clipping both edges. Switch to a definite 620px width with overflow-x:hidden (+ overflow-y:auto for history) so there's no scroll-width to leak — content wraps within, the Hamiltonian scrolls inside its own box. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pull Raghav's "bunch of bug fixes just landed" (2026-07-10) into the composite-system work. 13 commits from the local/amicode integration branch: #13 High-Performance Solver toggle + brand typeface (Racing Sans One) restore #16 entity-view + problem-switcher modal padding, remove card-family gold tint #17 chat paste via extension clipboard bridge (⌘V intercept) #18 chat prose no longer clips + AMICO signature on every assistant turn Conflict resolutions (4 files), all preferring the landed, reviewed fixes: - message-timeline.tsx: took the team wrapper (width:100%); dropped my untested 620px definite-width workaround. The katex Hamiltonian is now contained by the auto-merged amicode.css hardening (entity-view overflow-x:hidden + .amc-ev-formula overflow-x:auto), so width:100% against the v1 dialog's definite max is sufficient. - logo.tsx: took Racing Sans One (team brand decision, straight-sans reverted per review). Dropped the Aero face — it is license-pending donationware and cannot ship. - prompt-input.tsx / attachments.ts: took the canonical paste-bridge impl (readClipboardViaBridge, resolves "" not null). Verify: packages/ui amicode suite 112 pass / 0 fail; packages/app paste-bridge 43 pass. The 1 pre-existing submit.test.ts failure (Toast export via Object.assign, bun ESM quirk) is untouched by this merge on both sides. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Revert the merge's Racing Sans One resolution back to Aero per Aaron — matches wordmark-v2.tsx (already 'Aero', 'Racing Sans One' fallback). Aero @font-face + asset survived the sync (index.css, public/assets/Aero-Regular.ttf). NOTE: Aero is license-pending donationware (preview-only, USD 25+ to the author). Racing Sans One (OFL) remains the CSS fallback. Must be licensed or replaced before any release ships. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…atch #18) anthropic.txt "Tone and style" -> "Communicating with the user": output renders as rich GFM (headings/bold/lists/tables/inline code), match structure to content, lead with the outcome, readable-beats-brief in complete sentences. "interactive CLI tool" -> "interactive coding agent". Companion patch in amicode AGENTS.md covers custom-prompt agents (pulse-designer) that bypass this file. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ha 3c26d8d9 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
#18 addendum) Live test showed no change: the model pin is opencode/deepseek-v4-flash-free (no anthropic creds), so sessions load default.txt — whose "fewer than 4 lines / one word answers are best" rules steamroll everything. Same "Communicating with the user" section as anthropic.txt, terse examples replaced with structure-matching ones; gemini.txt minimal-output bullets replaced likewise. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… model (patch #18 addendum 2) One canonical "Communicating with the user" section (communicating.txt) appended in provider() for all model families, with a supersede clause that outranks per-model CLI/terseness rules. Inlined copies in anthropic/default/gemini slimmed back to near-stock. Custom-prompt agents still bypass by design (subagents return model-directed data); pulse-designer is covered via amicode AGENTS.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…for user-facing custom-prompt agents system-render.ts: role-aware driveTerm — atoms get Ω(t)/2(|r><1| + h.c.) instead of the hardcoded bosonic ε(t)(â+â†); atom drift -Δ n̂ → -Δ|r><r|. +3 tests (115 pass). request.ts: custom-prompt agents append PROMPT_COMMUNICATING unless mode === "subagent" — covers pulse-designer interview sessions at the system-prompt level; subagent output stays style-free (model-directed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two-finger / right-click on a tab now opens a context menu:
· Close (mirrors the × / middle-click)
· Close other tabs (disabled when only one tab)
· Close tabs to the right (disabled when it's the last tab)
- context/tabs.tsx: two bulk actions (closeOthers, closeToRight) living
alongside removeTab/removeSessions. Both are navigation-safe — closeOthers
activates the kept tab; closeToRight re-navigates to the anchor only if the
active tab was among those removed (via a new currentTabIndex helper that
matches session tabs by href and draft tabs by draftId). Index-shift safe:
single splice under produce/startTransition, not a removeTab loop.
- titlebar.tsx: wrap TabNavItem's root in the existing Kobalte ContextMenu
(Trigger as="div", modal={false}), mirroring sidebar-project.tsx. Wired from
the <For> where the index is in scope; enablement flags from tab count/index.
- i18n/en.ts: common.closeOtherTabs + common.closeTabsToRight (other locales
are Partial and fall back to en).
Scope: session tabs (TabNavItem). Draft "new session" tabs unchanged.
Verify: packages/app tsgo -b exit 0, 0 errors.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e above not below (patch #20) Upstream styled all h1-h6 identical to body text (14px medium, same color as the container) with the margin below the title instead of above — section titles read as unrendered prose. strong/b 500 -> 600 (500 vs the 400 body was near-invisible). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…jective fallback)
…+ preview The conflict-safe core of spec-20260712-014749 (all NEW files; no edits to the message-part.tsx / entity-rail.tsx / run-window.tsx surfaces the dashboard agent is actively changing): - amico-presence.ts: pure presence state machine (dormant/stepping_in/on/ settling/idle) — classify + transition; the shared brain rail+flow read. 14 tests. - amico-presence.css: offset accent lane + rail wake/settle motion (v2 tokens, reduced-motion gated); new file, not the hot amicode.css. - amico-presence.stories.tsx: self-contained Storybook preview of all 5 states + an auto-playing pop-in/out sequence (mock data). Deferred (dashboard-agent file contention): the invasive wiring — stamp scrub in message-part/card/ask-card/run-window, thinking-line decouple, rail wake/settle hookup. Fully specified in the approved spec; needs a coordinated pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…inherits the app CSP and kills the inline runtime
…ock; about-you failures render loud
…ce (spec stage1.5)
…fallback chain, control rebind (T3.2)
…e grid (spec stage1.5 T3.1/T3.3/T3.4)
…pill
The old edit mode floated a heavy row of five bordered buttons above every
card with a truncated label, drowning the content and reading as its own UI.
Rebuild: cards stay visible under a light scrim + dashed ring ("arranging,
not using"), each gets one compact grouped control pill in its top-right
corner (↑↓ reorder / ⚙ config / fork / ×), a banner orients, the add-back
tray only appears when something is hidden. Reorder ↑/↓ disable at row ends;
move buckets by hero/tile row (matches what the user sees). Overlay is
click-safe over the iframe; scrim blocks accidental widget clicks.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…the frame Moving display:none onto the frame wrapper left the cell holding an empty grid column. Hide the whole cell when not editing and there's nothing to render; keep the frame mounted under display:none so its amc:empty signal keeps flowing and the cell re-appears if the widget later has content. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Realizes the approved spec (identity rule + working lane) — the conflict-scoped pass (rail wake via CSS only; NO edit to entity-rail.tsx, which the widget kernel is editing): - message-part.tsx: drop the per-turn AMICO signature (data-slot= amicode-turn-signature); repurpose the amicode_* check as the in-domain signal; mount the thinking line in an offset accent lane BELOW the streamed parts, gated on inDomainTurn && working (decouples it from the old card-suppression so it now shows on in-domain turns — the reviewer's issue 5). - card.tsx / ask-card.tsx / run-window.tsx: drop the 'AMICO' wordmark (keep the H-mark glyph as a subtle leading icon); remove orphaned separators. - amico-presence.css: rail wakes on entry via [data-component=amicode-entity-rail] (session-sticky mount => plays once, no entity-rail.tsx edit). - styles/index.css: load amico-presence.css in the components layer. Verified: 20 tests pass, 0 typecheck errors. NOT visually run (heavy fork build; main checkout held by widget agent). Deferred: grouping amicode cards INTO the offset lane (open-question-2) + rail livedot-while-working — visual-iteration follow-ups. Not merged/pushed; reconciles with wip/stage1-widget-kernel at merge. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…el build Disjoint from the widget kernel (UI chat flow vs dashboard widgets); brings the presence lane + un-stamped cards into the current build for live review. Stage 2 widget-author WIP left uncommitted in the working tree, untouched.
…n-chat preview + pin
Prompt Amico to build a home widget; it renders a live preview in the chat and
you pin it to the dashboard. Rides the existing /^amicode_/ tool-name seam — no
stock-code, no new part type, no new route.
Server (opencode):
- authorWidget() in widgets.ts: validate structured manifest fields + js, assemble
the manifest TOML, round-trip through parseManifest, write ~/.amico/widgets/<id>/;
re-authoring an id overwrites (new content hash = hot-reload). Never throws.
- amicode_author_widget built-in tool (Tool.define + registry) whose description IS
the authoring contract (mount signature, --amc-* tokens, fetch allowlist,
empty-state). Output carries an AMICODE_WIDGET {json} sentinel for the preview.
- mergeDashboard: BUILT-IN widgets still auto-surface; USER/authored/forked widgets
are now opt-in via pin (no home clutter while iterating in chat).
UI:
- widget-preview.ts: pure parseWidgetSentinel (mirrors parseDiffSentinel).
- WidgetPreviewCard: live WidgetFrame (reuses the kernel) + Pin button + warnings;
reads a widgetHost transport off the ui-bridge; degrades to a note with no host.
- AmicodeToolCard: new <Match> for amicode_author_widget.
- ui-bridge: AmicodeWidgetHost {frameSrc, callbacks, pin}; entity-rail passes it in.
App:
- message-timeline provides widgetHost (frame src, fetch/prompt callbacks, pin =
GET+append+POST /amicode/dashboard).
Tests: authorWidget 5, sentinel parser 4, dashboard opt-in 1 (ui 178 / server 40 green).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…or.clipboard.read in the outer webview + copy-back The webview half of the bidirectional clipboard bridge (extension half is in amicode#136): image paste answered client-side in the outer webview where navigator.clipboard.read is granted (the sandboxed iframe + text-only vscode.env.clipboard can't); copy writes back to the OS clipboard; text-paste fallback on any failure. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rchari1
marked this pull request as ready for review
July 14, 2026 22:54
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Aaron's widget-kernel program, opened as a PR so CI runs and it's reviewable. 70 commits, +7,953/−382 across 111 files — 0 behind
local/amicode, merges clean. All commits are Aaron's; it adds alongside the already-merged amicode fork work (solver-toggle #13, chat-fixes #18) without reverting any of it.The load-bearing bit for amicode#136
The fork half of the bidirectional bridges whose extension-side listeners are in amicode#136 — without this PR + a vendored-binary bump, those three features are dead listeners:
packages/app/src/components/prompt-input/clipboard-bridge.ts→ sendsclipboard-write(copy-back) +clipboard-image-request, consumes theclipboard-imagereply (image paste). Has a test.packages/app/src/components/amicode-default-model.tsx→ sendsset-default-model(drives amicode'samicode.defaultModel).The rest of the program
packages/ui/src/amicode/amico-presence.*, with stories + test).dashboard.ts,widgets.ts+widgets-src/*,widget-*.ts,toml-lite.ts(all new underserver/amicode/);problems.tsbumps the log tail 8→24 (a smaller window can blank the filtered mid-solve view).Before this lights up in shipped amicode
One verification I want a reviewer to confirm
The bridge senders live in
packages/app; Kate's original paste bridge was inpackages/ui. Worth confirming a binary built from this branch actually serves thepackages/appcode (astringscheck on the built binary), so the senders don't just exist in-tree but ship. I can run this once we're at the release-cut step.🤖 Generated with Claude Code