The app is in active development, not yet public — replace the "Launch app"
CTAs with a "Private beta — coming soon" state (nav, hero, and final CTA).
Add a "Built by" section crediting the team, each name linking to their
LinkedIn, plus JSON-LD SoftwareApplication + Person author markup, an author
meta tag, and a canonical link for name/entity SEO.
Team: Karti Tripathi, Ramis Hasanli, Yahya Alhinai, Shakthi Bachala.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a public marketing landing at "/" celebrating the Top-3 finish at the
AI Engineer World's Fair 2026 hackathon (2nd overall of 95+ teams, LiveKit
track + DigitalOcean Best Use), with a scroll-to-read hero, feature/tech
sections, and the demo embed.
Introduce react-router: "/" serves the public landing (no auth) and "/app"
mounts the existing Clerk-gated app. The app route degrades gracefully to a
"deploying" placeholder when no Clerk publishable key is configured, so the
site renders without secrets.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Captures uncommitted work present on the live droplet so origin/main can be integrated and the new control toolbar deployed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Collapse the five full-width control buttons (audio, mic, background
music, test voice, share) into a compact icon pill with hover/focus
tooltips, plus a labelled Share primary CTA. Row now flex-wraps instead
of a fixed 2-col grid, so it stays on one line on desktop and wraps
cleanly on narrow screens. State is encoded visually (filled = engaged,
ghost = idle, primary = needs action). Background music gets a distinct
Music2 icon instead of reusing the audio Volume2 icon. Handlers are
unchanged — presentation only.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
voiceCue and hermes were never reset, so a new intervention card could show the previous one's spoken line. Clear both when a COLLISION arrives and on respond(); safe against the reliable publish order COLLISION -> HERMES_MESSAGE -> VOICE_CUE.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Codex review fix. The earlier approach synthesized a 'suppressed' beat from every
dismissed OUTCOME, which is wrong: a dismissal is not a later suppressed repeat,
and the old dismissal timestamp sank below the 12-row activity cap (invisible).
Now the negative-feedback loop is recorded WHEN IT HAPPENS. When shouldIntervene()
returns false specifically because a signature was dismissed before
(agent/podman.ts), the agent writes a durable SuppressionDoc to a new
`suppressions` collection, timestamped at the repeat. graph/live.ts materializes
those into kind:'suppressed' activity (recent -> surfaces at the top). The
suppressed collision is never written to `collisions` (agent returns before
recordCollision), so this is its own record.
Verified end-to-end: a transient demo-pod suppression renders at the TOP of the
activity stream; cleaned up after. shared build + backend/frontend typecheck +
eslint pass.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Surfaces "rework saved" at the top of the teammate Work History dialog:
a transparent heuristic over collisions Hermes caught early (eligible =
gitOverlap or critical, with an intervention), credit split across
involved engineers. Shows hard counts (clashes caught, conflict-free
files) plus an info-tooltip breakdown of the estimate.
- shared: optional MemberWorkHistoryRoi field (back-compat, self-zeroes)
- backend: query collisions + interventions in getMemberWorkHistory,
computeRoi helper
- frontend: RoiBand + RoiTooltip components, hidden when no clashes
Implements docs/plans/work-history-roi.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LuV8W8oNYRsDWKoqK8Mkqc
Backend becomes authoritative for the verifier signal. recordOutcome now
overrides the client-supplied wasRealCollision with deriveWasRealCollision():
a flagged collision counts as REAL only if BOTH named engineers currently have
the collided file in their git changedFiles (getGitStates, 120s freshness TTL).
Conservative false when the collision is orphaned/missing or git state is
stale. Restores the (accepted x wasReal) 2x2 the spec assumes instead of the
hardcoded 107/107 true.
frontend/useInterventions.ts stops sending a hardcoded `true` (now a
backend-overridden placeholder). Spec: continual-learning/spec.md:98-108,
policy.md:35-42. backend+frontend typecheck + eslint pass. PLAN.md P0.5 rung 3
added.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The 'Test audio' button becomes 'Background Music': each pod gets a calm looping track from Gemini Lyria 3 that sings the pod name once up front then stays instrumental. Backend GET /api/pods/:id/music generates via the Gemini interactions endpoint and caches the MP3 per pod in Mongo (pod_music); the frontend fetches and loops it via Web Audio, published pod-wide on the existing podman-beat track.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Lands the dynamic Team-memory redesign on top of main's continual-learning
pipeline. main already computes loop/activity in the API but its GraphView never
rendered them and kept a static-column graph; this swaps in the dynamic graph and
surfaces the rails, reusing main's richer PodLearningLoop / PodGraphActivity types.
Frontend (new frontend/src/components/graph/*, composed into GraphView.tsx):
- forceSim.ts: dependency-free force layout (charge, link springs, centroid
recenter, 2-pass collision, bounds clamp, alpha anneal) — no new deps/lockfile churn.
- GraphCanvas.tsx: SVG render from the sim — draggable + pinnable nodes, curved
edges, weight-sized shapes, fade-in, animated learned_from dash, risk-path
lighting / rest dimmed, label collision-avoidance.
- MetricsRail / LearningLoop / ActivityStream / SelectedNodePanel / encoding.ts:
the mock's rails + stream + detail panel in light shadcn. LearningLoop consumes
main's PodLearningLoop (steps + activeStep); ActivityStream consumes
PodGraphActivity (title + detail). SelectedNodePanel adds a Flow section that
narrates the path through a clicked node (flowNarrative); default copy is
mode-aware. Edge legend rounded out (editing/touches).
- GraphView polls every 5s and diffs (positions preserved), + ws /api/events nudge.
Stale selection (node gone across a poll) dropped so the canvas can't dim entirely.
Backend (surgical — main's materializer + buildLoop kept):
- live.ts: headline metric cards derived from the FINAL de-noised graph (Open risk
paths = distinct collision files; Learned owners = distinct owner engineers)
instead of raw collision-signature / accepted-outcome counts that inflate with
test churn (50 -> 4 risk files, 16 -> 1 owner on live). buildLoop untouched.
- demo.ts: metrics realigned to the demo graph (3 owners / 1 risk path / 100%).
Verified: lint + -r typecheck + -r build pass; Playwright confirmed the dynamic
graph (ticks on load, draggable), the loop rail (5 steps, ADAPT active) and
activity stream rendering main's shapes, honest metrics (3/1/100%), and the flow
narrative per node kind — zero page errors.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Surface audio-playback unlock and mic publish as persistent buttons in the pod control row (alongside Test audio / Test PodMan voice / Share screen), replacing the conditional 'Sound is off' banner that only appeared after a refresh. Enable mic calls setMicrophoneEnabled, which triggers the browser permission prompt so users can verify their mic is set up right.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Make the "Test audio" connectivity check pod-wide instead of local to the
publisher. Shared on/off state is derived from the presence of the podman-beat
track across participants (self-syncing on join/leave). Any participant can
stop it: the owner unpublishes directly; non-owners send a new additive
BEAT_STOP data message that the owner honors. Drives the button label, status
line, and status waveform for everyone, and guards against rapid-double-click
double-publish and mid-start unmount leaks.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop vite-plugin-pwa and add an index.html snippet that unregisters any leftover service worker and clears its caches on load. Continuous deploys during the event plus a self-destroying SW were forcing open tabs to reload mid-demo. Browsers self-heal on next load; re-add a precaching PWA post-event.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the confusing Join / Add-and-join / +Add trio on PodCard with one flow: type your name, hit Join → added to the roster (deduped server-side) and connected in one step. Removes the join-as-members[0] impersonation footgun where a second person could kick the first.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
My/Team streams were one flat lane; source provenance was buried as a
gray badge by the filename. Group each lane into Signals (vision/git
inputs) and Reasoning & decisions (collision/intervention/outcome), and
promote source to a color-coded provenance chip with a readable kind
label. Presentation-only; no shared-type or backend changes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VpySDjxpM1usXMEngJRWqG
Materializer (live.ts) — cut demo-pod from 110 -> 22 nodes:
- cap to 8 recent collisions; collapse repeats by memorySignature
- collapse interventions to one (most recent) per collision
- filter junk 'files' (URLs, env vars, browser/app names, scratch/test) to
real source paths only
- prune test-artifact engineers (a/b/verify/codex-check/-testrepo) + any node
orphaned by that
- collisions referenced by accepted outcomes bypass the cap so the learned_from
money path never drops; risk-paths metric counts distinct signatures
UI: per-pod 'Team memory' action on each PodCard's menu (replaces the header
button that always opened pods[0]).
Verified against live demo-pod data (joins connect); typechecks clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Agent-published LiveKit audio is unreliable for voice: the track is
short-lived (publish, speak ~3s, unpublish) and blocked by browser
autoplay, so participants heard nothing even though the server published
fine. The VOICE_CUE text already arrives over the data channel, so speak
it in the browser via speechSynthesis instead — instant and reliable.
Prime speechSynthesis from user gestures (Enable sound, Share screen) so
later cues are allowed to play.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AaCFWMkYQmTcuPsxaaACft
Voice generation, critical escalation, and audio publish all worked, but
participants heard nothing: browsers block autoplay of the agent's audio
track until a user gesture. Add the canonical LiveKit unlock — listen for
AudioPlaybackStatusChanged and show an "Enable sound" button that calls
room.startAudio() so PodMan's voice cues are actually heard.
Also make collision alerts short and direct instead of chatty AI prose:
card: "Conflict: ram + yahya both on README.md (unpushed). Seen before."
voice: "Conflict. ram + yahya, both on README.md."
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AaCFWMkYQmTcuPsxaaACft
- backend/src/graph/live.ts: materializePodGraph builds the graph from the real
collections (pods, engineer_states, observations, collisions, interventions,
outcomes) instead of the demo seed. Parses git-status paths, fuses git+vision,
draws collides/warns/learned_from, computes live metrics + a column layout.
- store.ts: loadPodGraph now prefers live → seeded team_model.graph → demo.
- GraphView.tsx: light/shadcn theme (from the team-memory-theme work), composed
from the ruixen primitives; node-shape encoding unchanged.
- docs/graph.md: live data→graph mapping + fallback order.
Typechecks clean. Not yet runtime-verified end-to-end (Atlas creds rotated again).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
infra/Caddyfile: add podman.live + www.podman.live (serve app + proxy /api),
so the domain is durable in the canonical config (not just a manual edit).
index.html: Open Graph + Twitter Card meta (title, description, og:image) so
sharing www.podman.live renders a rich preview. Adds a 1200x630 og.png card
(generated from og.svg) under public/.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SVG favicon (dark #0b0f17 tile, emerald "P" + live dot) wired via
<link rel="icon"> in index.html. Fixes the favicon.ico 404.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Resolve App.tsx header conflict: keep main's "Privacy-limited" badge AND the
"Team memory" graph button (both in the header action group). server.ts and
backend/package.json auto-merged cleanly — main's closeMemory/shutdown and the
graph:seed script are both preserved.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Resolve conflicts:
- backend/src/server.ts: keep main's getPresence + closeRoom (room auto-cleanup)
and add the graph imports/routes (additive).
- frontend/src/App.tsx: take main's shadcn command-center UI and re-integrate
GraphView — import, graphPodId state, an early-return render branch, and a
shadcn "Team memory" button next to Refresh.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- reachFrom now returns the direct outbound edges PLUS the recursive
$graphLookup reaches, de-duped by edge id, with maxDepth to bound cycles.
It was dropping edges straight off the start node. [review P2]
- GraphView SVG nodes are keyboard-accessible: role/tabIndex/aria-label +
Enter/Space handler alongside onClick. [review P3]
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds the team_model graph layer (the "it learned" view) and its visualization,
per docs/graph.md. Demo-backed first; built on origin/main conventions.
- shared: PodGraph / node / edge / metric types + GraphNodeDoc / GraphEdgeDoc
- backend/src/graph: demo graph data; Mongo store (loadPodGraph w/ demo
fallback, seedGraph, reachFrom via $graphLookup); graph:seed script
- backend/src/server.ts: additive GET /api/pods/:id/graph + /graph/reach/:node
- frontend: dark-Bauhaus GraphView + fetch helper, reachable from a
"Team memory" toggle in App.tsx
- docs/graph.md: spec (data model, $graphLookup, API, demo-first plan)
Demo-backed: the route serves a grounded demo graph when team_model has no
graph yet; graph:seed writes team_model + graph_nodes/graph_edges so the
$graphLookup traversal is real. Swap loadPodGraph to live team_model later.
Known follow-ups before merge: branch is based on 65a0791; origin/main is now
at 1294b84, so this needs a rebase + App.tsx conflict resolution (teammate
rewrote App.tsx with live room view / one-click join).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
room.disconnect() removes the participant from LiveKit but doesn't stop
the underlying OS capture. Without track.stop() the screen share indicator
keeps running after Leave. beatRef already had cleanup; add the same for
screenTrackRef.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AaCFWMkYQmTcuPsxaaACft