feat(models): Allow reliable models and update model selection logic in UI
agharsallah
83e16dc
feat(about): add About tab with project overview, architecture, and links
agharsallah
52b556c
feat(dependencies): restrict pandas version to <3 to avoid compatibility issues with gradio
agharsallah
ed6315a
feat(logging): remove warning suppression for pandas deprecation, handle it at the source
feat(lab): include competition contract in composed world to ensure leaderboard accuracy
fix(uv.lock): simplify pandas dependency specification across Python versions
feat(session): finalize run on verdict and enhance leaderboard recording logic
agharsallah
5851d28
feat(commentary): introduce universal rafters-critic for scenario commentary and cadence control
agharsallah
f637227
feat(lab): add roster model defaults merging to preserve user selections for newly added agents
agharsallah
05b49a8
Merge pull request #22 from abducodez/feat/hall-of-fame-leaderboard
feat: Add Hall of Fame leaderboard backed by a dedicated results table
feat(show): enhance rafters gallery with stable keys for improved audio handling and component persistence
agharsallah
0ee642e
feat: Add Hall of Fame leaderboard backed by a dedicated results table
agharsallah+1: Codex
c952d77
Add a competitive-results leaderboard as a dedicated, durable table
(leaderboard_entries) detached from the event ledger: the events log stays
the run trace, while one denormalised scoreboard row per decided run records
who won on which model. A row is written only when a run is finished, has a
winner, names a concrete winning model, and ran a competitive scenario; the
run_id links each row back to its full trace for replay.
- src/core/leaderboard_store.py: LeaderboardEntry + LeaderboardStore
(SQLAlchemy, separate table in the same database as the event store),
build_entry write gate, memoised make_leaderboard_store factory.
- src/core/leaderboard.py: model / agent / fairness / sessions / headline
aggregations over stored entries, with a per-seat fairness rollup.
- src/ui/fishbowl/session.py: record a scoreboard row on finalize.
- src/ui/fishbowl/hall_of_fame.py + app.py: the "Hall of Fame" tab —
champion headline, model podium with win-rate bars, sessions with replay,
and t…
feat(rafters): implement navigable gallery for illustrated and spoken beats with improved audio handling
agharsallah
5e2e876
feat(feed): update media rendering to use native components with badges instead of inline tags
agharsallah
7c81add
feat(media): introduce MediaRouter and stubs for image and speech generation
agharsallah
8400d8c
- Implement MediaRouter to resolve media capabilities to providers, supporting both live and offline modes.
- Add StubImageProvider and StubSpeechProvider for deterministic offline media generation.
- Create tools for image rendering and text-to-speech synthesis, integrating with the ToolRegistry.
- Enhance the commentator (rafters-critic) to generate and render media alongside commentary.
- Update UI components to display generated images and audio clips in the feed.
- Ensure tests cover the new media capabilities, including deterministic outputs and capability enforcement.
feat: Enhance telemetry store with revision tracking and optimize UI refresh logic
agharsallah
e1959d5
feat: Enhance color handling and styling across fishbowl components
agharsallah
d2180f0
feat: Implement audience-only secret badge for Twenty Sprouts game
agharsallah
f6566bb
- Added `_secret_badge` function to render a hidden-word run's secret for the audience.
- Updated `_core` function to include the secret badge in the HTML output.
- Introduced `peek_next_actor_name` method in `FishbowlSession` to provide the next actor's name without advancing the run.
- Modified `ReplaySession` to handle `peek_next_actor_name` appropriately.
- Refactored `build_show` to simplify the show controls, removing unnecessary buttons and adding play/restart functionality.
- Enhanced `view_model_at` to include the secret and its holder for the audience's view.
- Added tests for the new functionality, ensuring the secret is handled correctly and does not leak into agent prompts.
- Created a new test suite for Twenty Sprouts gameplay to validate the secret handling and game mechanics.
feat: implement winner celebration overlay and judging mechanics
agharsallah
6432854
- Added `render_winner` function to create a celebratory overlay for the winning agent or team.
- Integrated winner rendering into the main application flow, allowing for a modular display of victory.
- Introduced `has_judge` and `force_verdict` methods in `FishbowlSession` to manage judging logic.
- Updated session handling to allow for forced verdicts, even when the budget is spent.
- Enhanced CSS styles for the winner celebration, including confetti and trophy animations.
- Created tests for judging mechanics and winner rendering to ensure correct functionality across scenarios.
feat: Adjust narrator rail feed styling for compactness and fixed height
agharsallah
e3ba862
feat: Replace llama.cpp backend with in-process transformers backend for local GPU inference
agharsallah
7d636f8
feat: Add support for `spaces` package and integrate GPU self-test functionality
agharsallah
6d180a1
Refactor code structure for improved readability and maintainability
agharsallah
a464e67
Merge remote-tracking branch 'origin/main' into worktree-scenarios
feat: make every scenario arena-grade with a competition contract
agharsallah+1: Codex
0d0c561
Add a validated `competition` block (versus|judged|none) to scenarios,
stamped onto run.started so runs are self-describing and winners attribute
to models. Winners become data, not prose: judges emit a `winner` field
that the reusable JudgedCompetition handler validates against the live cast
(repairing deterministically so the offline stub always names a real
player); ground-truth judges (SpyHost, SproutJudge) decide in code.
Audit the five existing scenarios (The Steeped versus+teams with code-scored
winner; Mystery Roots judged; Open Table gains a table-judge; Thousand Token
Wood and Oracle Grove marked none) and add three competitive scenarios:
Debate Duel and Beat Battle (symmetric seats, different models) and Twenty
Sprouts (code-dealt secret word, deterministic win).
Surface a winner ribbon in the verdict banner only when a winner exists, so
none-kind and legacy runs render byte-identically. Enforce the authoring
checklist in tests/test_scenario_contract.py and document the co…
feat: Implement well-known typed fields for verdicts in output models
agharsallah
ce159dc
- Introduced `_well_known_specs` function to define typed fields for `winner` and `scores` in agent output.
- Updated `build_output_model` to handle new field types, allowing `winner` to be optional and `scores` to default to an empty map.
- Enhanced `json_instruction` to provide specific hints for well-known fields in the output format.
- Modified `FishbowlSession` to derive `winner_kind` and `winning_models` based on verdicts, supporting team-based outcomes.
- Added validation tests for new competition configurations and verdict handling, ensuring proper behavior for both agent and team winners.
- Created comprehensive tests for the new verdict validation logic, including re-ask scenarios and score normalization.
feat: implement per-event model attribution for enhanced event tracking
agharsallah
a71301e
Merge remote-tracking branch 'origin/main' into worktree-small-enhancement
agharsallah
1c1fbba
# Conflicts:
# src/ui/fishbowl/assets/styles.css
feat: implement Archive feature for past session management
agharsallah
a2ca0e0
- Added `archive.py` to handle listing and loading past runs for a specific user and scenario.
- Introduced `list_runs` function to retrieve past runs scoped by user session ID and scenario.
- Implemented `load_replay` function to create a read-only `ReplaySession` for a given run ID.
- Created helper functions for formatting run cards and timestamps.
- Enhanced CSS styles for the Archive drawer and run cards to improve UI presentation.
- Updated `FishbowlSession` and `ReplaySession` classes to support new functionality and ensure session isolation.
- Added comprehensive tests for the Archive feature, ensuring correct session attribution and replay functionality.
- Modified memory index tests to include run ID scoping for event searches.
- Created new tests for run history and lifecycle management, ensuring proper event emission and session handling.
feat(fishbowl): badge each agent's model + auto-follow the live feed
agharsallah+1: Codex
881a18d
The Show now surfaces what each cast member is actually running. The MindCard
and Split-view badges showed the profile tier name; an agent can override its
profile with a concrete catalogue endpoint, so the badge could mislead on
composed runs. New adapter helpers resolve the endpoint slug to a short model
name (offline-safe, degrading to the raw key, never blank) and colour the tier
dot from that model's own profile; the view-model carries `model` per card.
The narrator feed is a gr.HTML island whose content is fully replaced each
transport tick/scrub, so a fresh node started at scrollTop 0 — the newest line
sat below the fold and the feed looked frozen on the oldest message while the
show played or the scrubber slid. A dependency-free script (injected via head
so it actually executes) now auto-follows the live edge, and when the viewer
scrolls up to read history it stops following and reveals a floating
"jump to live" pill instead of yanking them down — preserving the exact reading
…
feat(fishbowl): hide the seed edit box behind a small "edit" toggle
agharsallah+1: Codex
2fcf1b7
The Quick lane now reads as one clean picker: the seed preset dropdown plus a
compact "✎ edit" button. The editable beat textbox starts hidden and only appears
when edit is clicked (the button flips to "✓ done" to close it again). Picking a
preset still fills the hidden box, and it remains the value Summon reads — so the
default flow is pick-and-go, with free-text editing one click away.
501 tests pass; ruff clean.
Co-Authored-By: Codex <codex@openai.com>
fix(fishbowl): anchor dropdown popups + make Premise a text-supporting dropdown
agharsallah+1: Codex
1e17273
Two issues in the Lab's Director's cut:
1. Model/judge dropdown option lists rendered detached from their input. Cause:
the .lab-advanced reveal animation used `translateY` with fill-mode `both`,
leaving a permanent transform on the column — which makes it the containing
block for descendant absolutely-positioned dropdown popups, so Gradio's
viewport-relative popup coordinates landed in the wrong place. Switched the
reveal to an opacity-only fade (no lingering transform) and set the per-agent
accordion card to overflow:visible so the list is never clipped. Verified: the
option list now anchors to its input (opens up/down as space allows).
2. Premise / goal was a plain textbox. Made it a gr.Dropdown(allow_custom_value=
True) — a dropdown that offers the scenario's goal as a preset and still accepts
free-typed text. The app shell now reseeds its preset (choices + value) on
scenario change.
501 tests pass; ruff clean.
Co-Authored-By: Codex <codex@openai.c…
feat(fishbowl): seed is a preset dropdown that fills an editable beat textbox
agharsallah+1: Codex
3782a33
Editing a long opening beat inside a combobox was awkward. Split the seed into a
clean preset dropdown (the scenario's example beats, filterable=False) plus an
editable multiline textbox: picking a preset drops its text into the box, and
the box — which you can rewrite freely — is the value Summon reads.
- lab.py: seed_presets Dropdown (local) + handles["seed"] Textbox; presets.change
fills the textbox; scenario change reseeds the preset list (the box value is
reseeded by the app shell).
- app.py: the scenario-change reseed now sets the seed textbox value (not choices).
- tests: handles["seed"] is now a gr.Textbox.
Verified in-browser: selecting a preset fills the editable box; switching worlds
reseeds both the preset list and the box (Open Table → its own beats/value); no
console errors. 501 tests pass; ruff clean.
Co-Authored-By: Codex <codex@openai.com>
fix(fishbowl): make the model pickers click-to-select dropdowns (filterable=False)
agharsallah+1: Codex
b3189b5
Gradio's gr.Dropdown defaults to filterable=True, so clicking the model field
turned it into a type-to-filter combobox rather than a plain dropdown — it read
as a text input, not a picker. The model is always chosen from the catalogue,
never typed, so set filterable=False on the per-agent model dropdown and the
judge model dropdown: a click now opens a clean option list with the current
pick checkmarked.
Co-Authored-By: Codex <codex@openai.com>
feat(fishbowl): make the Lab digestible — Quick lane + Director's cut + world digest
agharsallah+1: Codex
886aaca
The Lab had become a wall of always-open cards (brutal in the 5-mind worlds).
Reframe it with progressive disclosure so the first run is three taps and the
full console is one click away.
- Quick lane (default): scenario gallery → a live "world digest" card (goal +
capability badges: cast size · judge/no-judge · tools · turn budget, derived
from scenario_caps) → the opening seed → Summon. Nothing else competes for
attention.
- Director's cut (mode toggle): reveals backend, goal/genesis, cast roster,
governor budget, the cast, and the judge in one hidden column.
- The cast is no longer a stack of giant textboxes: each mind is a collapsed
gr.Accordion titled "name · archetype · tier · 🛠", the lead mind auto-opened.
- scenario_panel drops the seed (it lives in the Quick lane now); the seed is
still reseeded by the app shell on scenario change, unchanged.
- New CSS extends the phosphor-console language: world-digest card + badges,
segmented mode switch, advanced-column rail…
feat(fishbowl): scenario-adaptive Lab with per-agent & per-scenario config editing
agharsallah+1: Codex
4007d4b
The Lab now adapts to the selected world and lets the user edit each agent's and
the scenario's real configuration, wired through to the live run (per-run,
non-destructive — config/*.yaml and the cached registry are never mutated).
- scenario_caps.py: pure capability lens over the effective cast (judge present?
which agents may use which tools?), so the form shows only valid controls.
- render/agent_panel.py: one editable card per non-judge mind — model, per-agent
tool grant (only for tool-capable agents), persona override, schedule knobs;
event contract shown as read-only info chips.
- render/scenario_panel.py: goal, seed, genesis, cast-roster multiselect, and the
governor budget bounds.
- build_lab: Judge section renders only when the effective cast has a judge (so
dropping the judge from the roster hides it live); per-agent edits accumulate in
four gr.State dicts; scenario/backend change re-seeds states, roster, governor.
- collect_world_config: applies model/tools/pers…
feat: update agent personas and scheduling in YAML configurations; enhance event handling and memory deduplication in core logic
agharsallah
27b304e
feat(telemetry): skip log entries with empty context in log_rows function
New "Telemetry" tab in the Fishbowl app, reading live from the in-memory
telemetry store: a filterable structured-log feed (by level/layer), metric
charts (LLM calls, tokens in/out, agent-turn latency via gr.BarPlot/LinePlot),
and a per-trace timeline grouped by trace_id where each span reveals the actual
prompt + memory the agent saw. Manual Refresh + 3s auto-tick + filter-driven
repaint. New render/telemetry.py holds the pure store->view shaping.
Co-Authored-By: Codex <codex@openai.com>
- registry: config.loaded, manifest.loaded, model-endpoint resolution (no api key),
cast assembly, governor configuration logs.
- tools: tool.call span + capability-check (granted/denied) logs + tool.calls metric.
- session: session.created/reset/step/inject logs + session.step span so a UI step
produces a full trace down through the conductor.
- modal: configure() + modal.run_episode span + episode start/done logs with token stats.
Co-Authored-By: Codex <codex@openai.com>
refactor: tidy HF backend per /simplify review
agharsallah
1f581d5
- inference.backend_available dispatches via each backend's catalogue
has_credentials() — no per-backend name branches; adding a backend to
_BACKENDS now works here for free. modal_catalogue gains has_credentials()
to match hf_catalogue (symmetric contract).
- inference.backend_label() is the single source of backend display names;
the Lab cast render and the topbar chip use it (drop app.py's hardcoded map).
- hf_catalogue builds its entries + by-key index once at import; entries()/
entry_by_key() no longer rebuild the list per call.
- lab._resolve_scenario() centralises the "title or name" lookup repeated
across the cast render, judge/cast re-seed, and collect_world_config.
feat: add Hugging Face inference backend next to Modal
agharsallah
45917c7
Introduce a second, serverless inference backend (Hugging Face Inference
Providers) alongside the self-hosted Modal vLLM endpoints, and surface the
choice in the Fishbowl Lab.
- src/models/hf_catalogue.py: stdlib-only, offline-safe catalogue of small
instruct models (tiny<=4B .. strong<=32B); binding_for yields the same
LiteLLM custom-endpoint form, so the existing transport calls it unchanged.
- src/models/inference.py: one facade unifying Modal + HF behind
entries/binding_for/default_key_for_profile/backend_available. Models are
named by backend-qualified keys ("hf:<repo>"); a bare key means Modal, so
all existing keys/config/tests are untouched.
- router, registry endpoint: expansion, and has_live_credentials now read the
facade (live = any backend configured).
- Fishbowl Lab gains a headline "00 - Inference backend" radio (Modal vs HF)
driving the cast/judge pickers; the topbar chip names the live backend(s).
A composed run forces live on the chosen backend when it…
feat: implement streaming agent responses and enhance conversation flow with repeat guards
agharsallah
0b0d9be
feat: Enhance model routing and deployment flexibility
agharsallah
c1656a8
- Introduced `vllm_version` to allow per-model inference stack pinning, enabling models to opt for nightly builds when necessary.
- Updated image building logic to handle model-specific vLLM versions, ensuring compatibility with various architectures.
- Added `model_endpoint` to `AgentManifest` for explicit model binding, allowing agents to route to specific models instead of relying solely on profiles.
- Enhanced `ModelRouter` to resolve specific catalogue models, improving routing accuracy and flexibility.
- Updated UI components in the Fishbowl Lab to support new model selection features, ensuring only deployable models are presented.
- Improved tests to validate new model selection and routing behaviors, ensuring robustness and adherence to expected functionality.
Merge branch 'feat/live-loop-safety' into feat/live-integration
agharsallah
d09c82a
# Conflicts:
# src/ui/fishbowl/app.py
Merge branch 'feat/live-meters' into feat/live-integration
agharsallah
748a416
feat: surface LIVE/OFFLINE status + real token/spend budget in meters
agharsallah+1: Codex
73f0d0d
view_model adds offline + spend_usd (additive); meters render a LIVE/OFFLINE
pill, real tokens/ceiling, spend, and round, coral near the cap. Pure presenter,
no Gradio import. Offline shows OFFLINE / STUB.
Co-Authored-By: Codex <codex@openai.com>
Make the Fishbowl autoplay transport safe to point at live models: a tripped
governor budget, a verdict at the head, or a hard 40-tick backstop now stop the
autoplay timer and paint a "⛔ STOPPED — <reason>" banner instead of crashing the
Gradio callback or burning tokens in an infinite loop.
- Catch BudgetExceeded generically (getattr reason / str) in on_tick, step_at_head,
and the poke handlers; stop the timer (active=False) and set a stopped flag.
- advance_one_tick(): a pure, testable loop-safety core the timer handler drives.
- FishbowlSession.has_verdict(): auto-pause autoplay once the Judge has ruled
(also added to the defensive fallback session so on_tick never crashes).
- Hard backstop: per-play tick counter in gr.State stops autoplay after 40 ticks
regardless of budget; reset on Summon and on each ▶.
- Topbar chip now computed from has_live_credentials(): "● LIVE · MODAL" vs
"OFFLINE · STUB" (offline-first default unchanged).
- Loop-safety pytest proving auto-stop on …
Wire the prototype's flagship social-deduction scenario into the live engine,
config-only (no engine edits). Four minds get a secret word — the herd shares
COFFEE, a lone spy holds TEA — and bluff with clues while the mind-reader watches
the spy hide; a host unmasks the seam.
- config/agents/spy-{cara,bex,nil,ovo}.yaml: players emit agent.spoke with the
say-vs-think split; the secret word rides each persona so it never leaks.
- config/agents/spy-host.yaml + SpyHost handler: runs the generic judge turn for
the verdict text, then attaches a structured reveal:[{agent,secret,role}] to the
judge.verdict (same "decorate the emitted event" move as FortuneTeller's omen).
- config/scenarios/the-steeped.yaml: auto-discovered by the registry, surfaced in
the Lab; defaults to the DOCUMENTARIAN narrator.
- provider.py: curated offline lines + per-role mood bias so the bluff lands with
no API key (the spy leans bluffing/panicking).
Also make the Show usable as intended:
- Fix transport h…
refactor: update import paths and enhance layout structure for Fishbowl UI
The phosphor ink ramp bottomed out into invisibility (--ink-faint ~1.9:1,
--ink-dim ~3.3:1 on the tank), sinking real content — table headers, bubble
tags, the 'mind sealed' seal text, form labels. Recalibrate the ramp up the
lightness axis (same teal hue family) so every tier reads, darken the glass
panels so text sits on a stable field, and ease the CRT scanline/vignette.
Also repaint the Gradio-native chrome that shipped light fills from the default
palette and washed bright-on-bright in the tank:
- Group/Form/Styler wrappers (slate-700) -> dark panel / transparent
- radio + checkbox option chips (light slate, incl. the scenario radios the
earlier testid selector missed) -> dark phosphor via structural label:has()
- the Cast Dataframe's white header cells + virtual-row fills -> dark grid
- secondary buttons (Surprise me / Drop it) -> phosphor ghost
- disabled Lab fields kept legible; placeholders + checkbox/radio dots visible
No structure or vibe change; verified in-browser (0 l…
fix: align Fishbowl app shell to the session unit constructor
agharsallah+1: Codex
a2ac4f3
Unit 9 (app shell) assumed FishbowlSession(conductor, scenario_name=...), but the
shipped session unit builds its own Conductor from FishbowlSession(scenario_name).
Unify _new_session and the fallback session to the real (scenario_name, *, registry,
tools) constructor, and add an additive head property to FishbowlSession so the
transport's generation-head reads work on the real session.
Co-Authored-By: Codex <codex@openai.com>
Merge branch 'worktree-agent-a68e44256a7a3b2e0' into fishbowl-integration