Skip to content

amicode: home/profile/bridges polish, one-spine run truth, Gemini tool-schema fix, multi-drive pulse fix, audit sweep - #1

Merged
jack-champagne merged 52 commits into
local/amicodefrom
rchari/amicode-fixes
Jul 7, 2026
Merged

amicode: home/profile/bridges polish, one-spine run truth, Gemini tool-schema fix, multi-drive pulse fix, audit sweep#1
jack-champagne merged 52 commits into
local/amicodefrom
rchari/amicode-fixes

Conversation

@Rchari1

@Rchari1 Rchari1 commented Jul 7, 2026

Copy link
Copy Markdown
Member

Two nights of product polish + fixes from live-testing the fork inside the amicode dev host, a full 3-agent audit sweep, and one cross-provider blocker fix. 50 commits, deliberately granular (one fix per commit). Pairs with amicode PR rchari/workbench → aaron/problem-workspaces (the bridge/extension side).

Cross-provider blocker (worth reading first)

Gemini rejected our tool schemas outright. The amicode plugin declares optional args as type: ["array","null"]; passed through verbatim, Google's adapter emits an any_of whose array branch has no items — the API rejects the whole function declaration and every turn on a Gemini model died with an empty reply. legacyJsonSchema now strips the null and marks the field optional (the behavior the plugin comment always claimed) + tests. Verified end-to-end with a live tool-bearing turn on gemini-3.5-flash.

Home page

  • Brand: Mark + "Amicode / by Harmoniqs" block replaces the bare "Projects" label; slanted Logo de-slanted; boot splash (Mark + Piccolo code typing/backspacing) and rotating typewriter tagline.
  • Cards: Meet-Amico hero (hover gold shine + lift, card click opens chat, big accent "Open chat ↗" CTA); sessions collapse to 3 + "Show all (N)"; single-project row hidden; layout floor fixes (session list no longer overlaps the cards).
  • Footer: Harmoniqs brand link → harmoniqs.ai (bridge-opened), Piccolo.jl + GitHub links, engine chip.
  • Laptop fit: @media(max-height) tiers (880px/760px) compact chrome AND content (capability bullets stay — only decor compacts); one page scroller (no trapped inner scroll region); dead Help row + floating "?" removed (their links are no-ops inside the webview); "Now solving" polls while Home is mounted so chat-started solves surface.

Profile (About You)

  • Inline editing (name/affiliation/focus/scholar + Save → new POST /amicode/profile, merges only editable fields into ~/.amico/profile.json).
  • Institution pipeline: Clearbit autocomplete → Wikidata P154 brand logo → Commons @512px → Wikipedia pageimage → favicon fallback; LinkedIn-style banner tile; Scholar pill (bridge-opened).
  • Audit hardening: Save failures show a message (was a silent revert); resolvingLogo is a counter (overlapping picks persisted the blurry favicon); out-of-order search guard + debounce cleanup + stale-dropdown hygiene; dead logo URLs fall back to the monogram; paste interception is iframe-only (plain browsers keep native paste); non-object profile.json can't 500 the save.

Webview bridges (cross-origin iframe: clipboard/window.open/prefers-color-scheme are all dead)

  • Theme: ?colorScheme= preload seed + live {kind:"theme"} messages → setColorScheme.
  • Clipboard paste + open-external + ⌘⇧P → VS Code palette, all over the origin-checked message bridge.

Run truth (one-spine, amicode #84)

  • run-terminal.ts: documented mirror of amicode's canonical readTerminalState — FINISHED status-field authority, torn → keep polling, AMICODE_STOPPED relabel, fidelity only from result.toml (bounded 0..1.0001; raw "stopped" rejected — relabel-only, matches the schema); run-status/run-series route through it; DONE demoted to a fidelity hint.
  • Stalled: FINISHED-less run with run.log cold >10 min reports "stalled" (never solving-forever); logless fallback anchors on run.toml mtime (writing STOP/.DS_Store into the dir used to resurrect corpses).
  • Stopped/aborted render honestly: rail chip keeps them (they used to vanish or read "failed"); run-window colors them muted/danger (was solving-blue); window polls through "stalled" so it converges.
  • Pulse plot fixed for every multi-drive solve: the parser NaN-dropped one sample per ;-drive-seam and glued all drives into one corrupt trace — now parsed per-drive and rendered as one path per drive (shared amplitude scale).

Run cards + gallery (new)

  • Shareable solve cards: fixed 1200×630 (og-image aspect) SVG poster per completed solve — nines-gold fidelity headline, convergence curve, final pulse (one path per drive), platform/gate from the recorded entities, Harmoniqs sign-off. Theme-independent by design (exports render identically everywhere). PNG export at 2x via SVG→canvas.
  • Gallery: GET /amicode/run-cards collects every completed solve across problem workspaces (failures/stops excluded — trophy case); a "Run gallery" action card on home opens the overlay; what you see is byte-identical to the exported PNG. Saving routes through the extension's new save-file bridge (downloads are dead in the iframe); browsers fall back to <a download>. Tests on the endpoint, renderer (incl. hostile-string escaping), and parser.

Misc

  • Ask-card reopen fix: answered state derived from the persisted transcript (was an in-memory singleton).
  • MCP/LSP/Plugins status popover hidden (operator noise; slot reserved for a future solver-health panel).
  • Titlebar session tab: Mark idle / AmicoSpinner working / unread dot.
  • Formatting: prettier (repo config) over the branch, then repo-wide — upstream was already clean, so the whole-repo pass touched only 11 extra files.

Verification

packages/ui amicode tests 56 green, server amicode tests 14 green (updated to the one-spine + stalled contract), new registry-schema tests green, typechecks clean across ui/app/opencode; live-driven in the dev host across both nights (profile save, logo pipeline, theme flip, stalled → force-stop end-to-end, live Gemini turn).

Also: please consider cutting v1.17.3-amicode.2 from this so the amicode opencode.lock.json can pin it (the extension currently runs a source build).

🤖 Generated with Claude Code

Rchari1 and others added 30 commits July 6, 2026 16:32
Fixes the home-page overlap after visiting a session and navigating back:
the session column's ScrollView is positioned (scroll-view.css position:
relative) so it paints ABOVE the static cards wrapper; once a "Today" group
exists, the unbounded grid row lets the list box extend down over the cards
and the rows bleed across them.

- home.tsx cards wrapper: relative z-[1] — cards paint above the list, still
  below the z-10 session-search overlay.
- home.tsx project <aside>: min-h-0 — the auto grid row can shrink to the
  flex allotment instead of growing to the column's content height (root
  cause; the z fix alone removes the visible symptom).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The app has complete light+dark themes but nothing tells it the EDITOR's
theme (prefers-color-scheme inside a webview iframe reports the OS). Two
entry points, both riding the existing opencode-color-scheme machinery:

- oc-theme-preload.js: read ?colorScheme=light|dark (passed by the amicode
  extension from vscode.window.activeColorTheme) and seed the storage key
  before the scheme read — the app BOOTS in the editor's theme.
- app.tsx AmicodeThemeBridge (inside ThemeProvider): a window message
  listener for {source:"amicode", kind:"theme"} envelopes (extension →
  outer relay → iframe) routing through setColorScheme — LIVE re-theme on
  editor theme switch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… read the contract

Both endpoints hand-rolled terminal state and drifted from the run-dir
contract (amicode #84, one-spine rule): FINISHED's presence (not its status
field) decided the outcome — a failed run WITH a result.toml reported
"finished"; a torn mid-write FINISHED latched "failed"/"finished" off a read
race; the script's DONE line could promote status; user-stops read as
converged.

New run-terminal.ts — a documented mirror of amicode's canonical
readTerminalState (packages/extension/src/run_dir_reader.ts):
  * FINISHED (the orchestrator's verdict) is the only terminal authority,
    and its status FIELD decides; torn/invalid FINISHED = not terminal,
    keep polling.
  * AMICODE_STOPPED relabels completed → "stopped" (a user-stop is never a
    convergence).
  * fidelity/iterations only from result.toml, only when completed.
Both endpoints now route through it; the DONE line is demoted to a
pre-FINISHED fidelity HINT that never decides status.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- About-You card: the pencil now toggles INLINE editing (name/affiliation/
  focus inputs + Save) instead of opening a chat. Save rides a new raw
  POST /amicode/profile route (query-param idiom, same auth layer as the
  GETs) → profile.ts saveProfile merges the editable identity fields into
  ~/.amico/profile.json, invalidates the response cache, and returns the
  fresh profile; the app refetches and the card renders the saved state.
  Derived fields (platforms/stats/remembers) stay computed, never stored.
  The edit-in-chat path remains the fallback when onSave isn't wired.
- Home Projects column: brand block (Mark + "Amicode / by Harmoniqs")
  replaces the bare "Projects" label — the lone letter-avatar row beneath
  read as a stray "A amicode".
- Getting-started tagline: "Andiamo." un-italicized; "By Harmoniqs" byline
  added under the tagline.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…op band keeps a min-height floor and the cards region scrolls internally when squeezed (edit-mode growth clipped the brand/search chrome)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… friendly Quantum Computing Agent' types/holds/backspaces through rotating phrases (shared AmicodeTagline); Meet-Amico subtitle updated; plucky-pal copy retired

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…or unread) replaces the blue letter-avatar radar; Logo wordmark on a straight professional face (sans 750 + letterspacing) brand-wide

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ed (capture-phase; rides the allowlisted command bridge)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rd click opens a fresh session (the Amicode page); inner CTA unaffected

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… working, unread dot) instead of the letter-avatar radar; home columns isolated (own stacking contexts) so positioned children can't paint across columns during resize

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e was too much); spinner-on-working + unread dot kept

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ession pinned the spinner forever); sessions collapsed to the 3 most recent with a Show all (N) expander

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…type in / backspace out under the Mark); tagline starts faster (700ms first cycle, tighter holds)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…m the persisted transcript

Reopening a session made the pulse-design interview dead: the ask-card's
answerability gated on the ask-bridge SINGLETON (mounted only with the
header rail) and a local picked() signal — both in-memory, both gone on
reopen — while everything needed was already persisted (the ask tool part's
input, and the user's reply as the next user text message).

- ask.ts answeredOption(): pure helper — the first later user reply that
  matches an option is the persisted pick (rehydrates the highlight); a
  non-option reply means answered-otherwise (static, no highlight).
- ask-card: active = !answered && !clicked, derived from the transcript via
  useData() — the bridge is now ONLY the submit transport, never a gate.
  Unanswered cards stay interactive on reopen; answered ones render static
  with the chosen option highlighted.
- card.tsx/message-part: sessionID threaded (already supplied by the part
  renderer). 3 new bun tests on answeredOption.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tection; bigger brand block

- About You: institution banner row (accent-tinted) with the university/
  company logo (user-pasted URL, persisted) or a generated monogram badge,
  "institution profile" caption, and a Google Scholar pill (opens in a new
  tab). Both editable inline (scholar + logo URL fields join name/
  affiliation/focus in profile.json); "self-improving — Amico refines this
  as you work" note under the eyebrow.
- run-status/run-series: a FINISHED-less run whose run.log has gone cold
  (>10 min) reports "stalled", never "solving" — the Now-Solving card stops
  advertising wedged runs (the OOM-stuck run showed "iter 8, now solving"
  forever).
- Brand block: Mark size-6 + larger Amicode/by-Harmoniqs type.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…earch

- command.tsx: clipboard/undo chords (⌘/Ctrl + V C X A Z Y) in editable
  targets are the editor's, never the app keymap's — a colliding keybind was
  preventDefault-ing paste in plain inputs (composer had its own handling,
  masking the bug).
- About You edit: the affiliation field is now a type-ahead over Clearbit's
  free autocomplete (name + domain + logo, CORS-open, no key) — pick "New
  York University" and the NYU logo fills in automatically; free text still
  saves as plain affiliation with the monogram fallback. Manual logo-URL
  field dropped; live logo preview chip beside the input.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…o CDN is sunset — blank images); explicit ⌘V clipboard-read fallback on all profile inputs (native paste doesn't reach inputs inside the VS Code webview iframe)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ard can't be delegated into the webview iframe); institution logos via unavatar w/ google-favicon fallback; LinkedIn-style banner (44px white logo tile, stronger hierarchy)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…initials tile); Scholar pill sits with the user's name and actually opens (open-external bridge; _blank is dead in the webview); logos via gstatic faviconV2 @256 for the sharpest available mark

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…k time (high-res/SVG marks — the NYU seal renders as vector); favicon mark stays as instant placeholder + fallback

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…U torch, not the seal) rasterized crisp by Commons at 512px; fallbacks pageimage→favicon; Save held during resolution (fixes the race that persisted the blurry favicon)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…apsed sessions pull the cards up; container pt-14→pt-10. Expanded Show-all scrolls inside the section

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…) replaces the small what-can-Amico-do button; opens a fresh chat like the card click

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
….jl + GitHub links, Piccolo-engine chip; hairline top border, sits at the page bottom

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…reen layout — container 1440px, cards column minmax(0,1fr) (kills the fullscreen white gutters)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- run-window: 'stalled' gets the warning color — a wedged run (OOM) must not
  read as live-solving blue; iter N stays visible as last progress
- problem.ts: run-status parser keeps 'stalled' entries (was silently dropped);
  run chip says 'stalled · iter N' when nothing newer solved/finished
- session-header: MCP/LSP/Plugins status popover hidden (operator noise;
  slot reserved for a future solver-health panel)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…compaction (shell padding/gaps, band cap, card+CTA padding, meet-mark size); scrolling boxes are a phone affordance, not a laptop one

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…act — FINISHED seeds carry a real status field (presence≠verdict, amicode #84); ghost run refs assert 'stalled', not solving-forever

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…-dropped one sample per drive boundary and glued all drives into one corrupt trace (every multi-drive gate solve rendered wrong in the chat pulse view)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ices the flattened wire values, shared amplitude scale) — drives were glued into one polyline

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rchari1 and others added 18 commits July 7, 2026 02:36
…d them away, so a deliberate user stop made the chip vanish or read 'failed' (defeating the one-spine stop semantics)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… were solving-blue); polling continues through 'stalled' so the window converges when a stalled run resumes or is force-finalized instead of freezing forever

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…me (immutable after birth) — dir mtime meant writing STOP (or .DS_Store) resurrected a corpse to 'solving' for another 10 minutes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ing (server down / stale binary without the POST route read as a dead button; also killed the unhandled rejection)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cks let the first pick's finally re-enable Save while the second still resolved, persisting the blurry favicon placeholder

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n't clobber newer results, the debounce timer dies with the component, and a dropdown left open at cancel doesn't haunt the next edit

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…it preventDefault'd the native paste that already works (Firefox/Safari lost paste in all four profile inputs)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… hide (form/dropdown) — a persisted sunset-CDN URL rendered the broken-image glyph in the hero banner; resets when the logo URL changes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ive survived the ?? {} and made Save 500 (which the client used to swallow silently)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… 'stopped' is not a FINISHED enum value (relabel-only), and fidelity outside 0..1.0001 is dropped instead of surfacing an F the extension refuses to trust

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…olving) — the card only fetched once per server selection, so a solve started from chat never surfaced without a remount

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… was deliberately removed (11d1dc9), the comment still claimed it existed

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…inder is our earlier amicode files the touched-file pass missed)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…htens identity/divider/institution spacing; ≤760px drops the Meet-Amico bullet block + engine line (the CTA carries the message) so the hero row fits a short webview without box-scrolling

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…y','null'] passed through raw made Gemini's adapter emit an items-less any_of, Google rejected the function declarations, and EVERY turn on a Gemini model died with an empty APIError reply; null is stripped and the field marked optional (the behavior the amicode plugin comment always claimed) + tests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… the webview iframe — the button did nothing); ONE page scroller — the shell scrolls naturally instead of trapping a nested cards scroll region

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…emoved (its links are dead in the webview); Meet-Amico capability bullets restored on small heights (only the decor engine-line compacts away)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Rchari1 Rchari1 changed the title amicode: home/profile/bridges polish, one-spine run truth, multi-drive pulse fix, audit sweep amicode: home/profile/bridges polish, one-spine run truth, Gemini tool-schema fix, multi-drive pulse fix, audit sweep Jul 7, 2026
Rchari1 and others added 4 commits July 7, 2026 10:01
…s problems, shaped for the share-card renderer (headline F, convergence series, final pulse, platform/gate from recorded entities); failures/stops stay out of the trophy case + test

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… premium-dark SVG poster (nines-gold F headline, convergence curve, per-drive final pulse, Harmoniqs sign-off), gallery overlay from a home 'Run gallery' action card, PNG export (SVG→canvas, 2x) saved via the extension bridge in the webview / <a download> in browsers + tests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… fit-to-content went near-fullscreen on run entities (long paths + history)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
wslOpencodeAction returns "Install Amicode"/"Update Amicode" after the
rebrand; the test still asserted the old "OpenCode" strings. Align the
two assertions so `bun turbo test` is green. Test-only; no runtime change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jack-champagne
jack-champagne merged commit ab0e798 into local/amicode Jul 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants