Combine Caddy+API and Hermes+detector into single nodes, collapse the
LiveKit room internals, and relabel every edge with the value it carries
(pre-commit signal, nudge before clash, learn from outcomes) instead of
listing every transport hop.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LuV8W8oNYRsDWKoqK8Mkqc
Replace the single all-in-one architecture flowchart with two focused
diagrams: (1) how LiveKit, Hermes, MongoDB, and DigitalOcean wire
together, and (2) Gemini's five surfaces with their triggers, models,
and call sites.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LuV8W8oNYRsDWKoqK8Mkqc
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
Build-ready spec for adding a "rework saved" ROI band to the member
Work History dialog: transparent heuristic over caught collisions,
additive shared field + backend queries + presentational component.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LuV8W8oNYRsDWKoqK8Mkqc
- docs/plans/research-overlap.md: self-contained build spec for code-edit
vs research cross-channel overlap nudge (vision classifies editing vs
research, semantic embedding match, collaboration nudge). Ready for an
implementing agent.
- CLAUDE.md: replace branch-first habit with push-directly-to-main policy
plus mandatory pull --rebase before push for concurrent teammates.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LuV8W8oNYRsDWKoqK8Mkqc
Reframe README around the real bottleneck (human coordination, not
engineering ability) with the "five-minute meeting" cost story; rewrite the
demo script to match. Update gemini/livekit/mongodb/digitalocean specs to
reflect shipped code (Gemini Live agent, TTS, embeddings, Lyria via
Interactions API; current API routes; hermes_jobs collections). Add hermes.md.
Rename graph.md -> cont_learning.md. Remove outdated/dead docs (agent-learning
scaffolding, graph-discovery, handoffs, superpowers, idea/plan/demo-setup) and
the bundled LiveKit starter under examples/. Rewire CLAUDE.md doc-first gate
off the deleted PLAN.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LuV8W8oNYRsDWKoqK8Mkqc
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
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
Document the box topology so future sessions (and teammates' agents) don't
rediscover it the hard way: systemd-managed services (never launch the agent
manually — duplicate podman-hermes identities evict each other and silently
drop interventions), Caddy serving the static frontend from /var/www/podman,
the deploy procedure, and the shared-package build order.
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
Live observations showed two engineers both dirty on README.md but zero
collisions firing. Two root causes:
1. normalize() only lowercased and prepended src/, so the same file at
different path depths ("agent.ts" vs "backend/src/agent.ts") never
matched. Replace with lowercased-basename matching.
2. Git ground truth (engineer_states.changedFiles) was only used to set
the unpushed flag, never to match the file. The strongest signal was
wasted.
Detector now fuses vision currentFile AND git changedFiles into one
file->engineers map, so a collision fires when two people share a dirty
file even if both screens aren't on it at the same instant.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AaCFWMkYQmTcuPsxaaACft
Reverse the best-effort error swallowing. MongoDB is core to PodMan's
continual-learning story and must always be used, so a broken memory
layer must surface immediately rather than silently masquerade as
working (which is how observations stayed at 0 unnoticed).
- agent verifies Mongo via initMemory() at boot; bad creds / unreachable
Atlas now fail loudly before joining the room, not mid-demo
- server exits on Mongo init failure instead of warning and limping on
- getGitStates and onScreenFrame no longer swallow Mongo errors
- memory persist() logs the failure and rethrows instead of warning
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AaCFWMkYQmTcuPsxaaACft
A Mongo auth/connection failure in getGitStates escaped uncaught and
killed the agent process on the first screen frame, so collision
detection never ran. Make git-state fusion best-effort (degrade to
vision-only) and wrap the whole onScreenFrame loop so no per-frame
Gemini/GitHub/Mongo error can crash the long-running agent.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AaCFWMkYQmTcuPsxaaACft
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
Add getGitStates(podId) to db.ts — queries the engineer_states collection
written by scripts/podman-agent.mjs and returns a map keyed by engineer name.
In PodMan.onScreenFrame(), fuse before detectCollisions(): if an engineer has
changedFiles in engineer_states, force hasUnpushedChanges=true on their context.
This overrides Gemini vision's unreliable pixel-based guess with deterministic
local git state — preventing the money-moment collision from silently not firing.
Key assumption: LiveKit participant identity matches the --name arg used when
running the git watcher (e.g. identity "alice" → --name alice).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AaCFWMkYQmTcuPsxaaACft
- Add scripts/podman-agent.mjs — polls git every 15s, upserts changedFiles/
diffStat/recentCommit/branch into MongoDB engineer_states collection
- README: add "Git watcher" section with per-laptop demo commands for each
team member (alice/bob/carol --pod demo-pod)
- PLAN.md: mark scheduled git truth ✅ partial, update acceptance checklist,
clarify remaining fusion step (GIT_REPORT data channel wire-up still needed)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AaCFWMkYQmTcuPsxaaACft
No fixed ownership — any teammate can pick up any task.
PLAN.md: drop Owner field from all tasks, remove team assignments table.
CLAUDE.md: remove ownership map table and person-specific lane rules.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FFbfi4Cmb7BY75Wtne7bZn
Hard gate: all code must trace to docs/PLAN.md task or a spec.
Claude must stop, consult, and update docs before writing unplanned code.
Includes off-plan signals checklist and rationale for 4-person concurrent team.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FFbfi4Cmb7BY75Wtne7bZn
Tell Claude this repo has 4 simultaneous owners with distinct lanes.
Adds ownership map, rules for staying in lane, merge conflict guidance,
and integration point contract rules.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FFbfi4Cmb7BY75Wtne7bZn
- Remove all docs/generated/* (stale research output from prior workflow)
- Rewrite PLAN.md as ordered implementation plan: 10 tasks by dependency + demo criticality
- Each task has owner, estimate, dependencies, specific files to create/modify
- Cut line separates must-ship from nice-to-have
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FFbfi4Cmb7BY75Wtne7bZn