Commit Graph

11 Commits

Author SHA1 Message Date
adlee-was-taken
4c0898cd49 docs: QUICKSTART + DEVELOPMENT + CONTRIBUTING, polish README index
Builds out the user-facing docs tree alongside the slice-1 build target.
Kept the implementer's planned Task 7 'Slice 1 dev loop' README section
untouched — these docs are the canonical destination for that pointer.

- docs/QUICKSTART.md: 5-min path to 'hear the echo' (libopus install,
  cargo run, browser steps, troubleshooting, what's happening under the
  hood).
- docs/DEVELOPMENT.md: dev loop — workspace layout, per-crate iteration,
  running tests, the 20 ms loop / 'drop + observe' rule, slice-1
  boundaries (what NOT to add yet).
- CONTRIBUTING.md (at repo root, conventional): trunk-based dev,
  CI gates, commit message style, atomic commits, code style +
  learner-facing documentation policy, terminology policy, PR workflow
  + review checklist, GPL-3.0-or-later license.
- README.md: add a Quickstart pointer at the top, a Documentation table
  linking to every doc, and the slice-1 build-target status block.
2026-06-28 12:32:12 -04:00
adlee-was-taken
470a22a6b7 git: ignore local worktree directories
Per using-git-worktrees skill — local .worktrees/ is for isolated
development workspaces, not tracked content. .
2026-06-28 11:20:58 -04:00
adlee-was-taken
3c5cc75015 plan(slice-1): adversarial review patches
Verified str0m 0.21 + opus 0.3.1 API surfaces via docs.rs subagents;
patched the plan with the real signatures and several design-level fixes.

API-surface patches (str0m 0.21, verified):
- Global Constraints: full verified API surface documented inline
  (Rtc::new takes Instant; SdpOffer::from_sdp_string is the entry
  point, NOT from_str_unchecked; add_local_candidate returns
  Option<&Candidate>; Writer::write takes rtp_time not media_time;
  MediaTime has no add(Duration) -> use mt + MediaTime::from(d);
  payload_params returns impl Iterator; MediaData.data is Arc<[u8]>).
- Task 4 accept_offer: rewritten with from_sdp_string + correct error
  mapping; RtcSessionError::SdpOffer changed to String (collapses parse
  + accept failures uniformly).
- Task 4 loop_driver: MediaTime::add -> + MediaTime::from(Duration);
  media.data deref coercion documented.

Design-level patches:
- Task 4: RtcSession::new_for_test -> pub fn new() (single idiomatic
  constructor, no test/prod split).
- Task 4: added accept_offer_transitions_channel_to_connecting test
  (the transition was claimed but untested in the original plan).
- Task 5: dropped reqwest from workspace deps (unused — integration
  test uses tower::ServiceExt::oneshot); added tower as workspace dep
  + binary crate dev-dependency.
- Task 5: removed duplicate DELETE /v1/sessions route (was incorrectly
  chained via .delete() on the collection route AND on /v1/sessions/:id
  — only the latter is correct).
- Task 5: clarified pub mod requirement (must be pub because the
  integration test references modules via absolute paths).
- Global Constraints: added task/PR strategy (one commit per task,
  merged in numeric order, granular history is load-bearing for the
  learning-codebase goal).

Self-review section updated to reflect the patches.

Plan is now implementation-ready.
2026-06-28 11:19:41 -04:00
adlee-was-taken
1164770d98 spec(slice-1): adversarial review fixes
API-surface corrections (verified against str0m 0.21 docs):
- str0m::Live -> str0m::Rtc (no Live type exists)
- needs_input_timeout() -> Rtc::poll_output() returning Output::Timeout(Instant)
- RtcConfig::with_dtls_cert -> RtcConfig::set_dtls_cert (also: str0m auto-gens
  a cert if none passed; slice 1 still passes explicitly for ownership clarity)
- Event::RtpPacket(pkt, rid) -> Event::RtpPacket(RtpPacket) { single struct,
  RID is a field }
- str0m::ice::IceAgent -> no public 'ice' module; ICE types at crate root:
  Candidate, CandidateKind, IceCreds, IceConnectionState
- str0m.write_rtp() on Rtclive -> Frame API path: Rtc::writer(mid) -> Writer::write

New design decision surfaced by API verification:
- Media API path: Frame API (default) vs RTP API (set_rtp_mode(true)).
  Slice 1 uses Frame API — the proof target is the codec-to-PCM boundary,
  not RTP packetization. RTP API is a candidate for step 5.

Design-level fixes from close reading:
- §3.3 AudioSource/AudioSink: clarify who drives the traits (the poll loop
  drives both; sink on inbound MediaData, source on Output::Timeout deadline)
- §3.6: clarify cert/CrossRef — fresh in-memory cert each restart is safe
  because browser fetches fresh SDP each session, no caching layer to go stale
- §4.1: add Content-Type: application/sdp to /offer (browser-side fetch needs
  it)
- §4.5: resolve 5-min-vs-60s idle-timeout contradiction (60s, not 5 min)
- §4.5: add graceful-shutdown story (drop DashMap on SIGINT, browsers see
  dead peer — acceptable for dev loop)
- §6.4: fix 'mocked str0m Rtc' — str0m's Rtc is a concrete struct, not a
  trait; sans-IO means drive real Rtc with synthetic Inputs, not mock it.
  Stronger than mocking: production path exercised exactly.

Resolves 5 load-bearing API errors + 3 design-level ambiguities. Spec is now
implementation-ready pending user review.
2026-06-28 10:41:18 -04:00
adlee-was-taken
504d0020f4 docs: add AGENTS.md for opencode
Project orientation for any agent (human/AI/hybrid) working in the repo.
Covers: project structure (current + planned), build/lint/test commands,
Rust code style (formatting, naming, error handling, async/concurrency,
learner-facing documentation comments), terminology policy (inclusive
language + ICE-as-protocol-convention exception), architecture
pre-reading order, key decisions to respect, git workflow, and the
slice-1 boundaries (what NOT to add yet).
2026-06-28 09:34:04 -04:00
adlee-was-taken
075e984fb5 docs: ratify vision revision across README/ARCHITECTURE/PORT_PLAN + ADRs 0002-0006
Folds the 2026-06-26 vision-revision pressure-test into the canonical
docs. The spec moves from Proposed to Ratified; the decisions it produced
land in the docs it said it would amend, with ADRs recording each
load-bearing reversal.

- README.md: reframe north star (AI-era contact-center engine, not
  Asterisk successor); persona; revised pillars (add data-ownership,
  demote WASM, promote spend-control); update 'what it is/isn't'.
- ARCHITECTURE.md: replace three-plane framing with fused per-call
  vertical + composable horizontal platform; remove control<->media
  hot-path gRPC hop; make the agent tap the central interface; add
  DX spine + GUI-as-API-client + k8s declarative/operational model.
  Also: 'too slow to police' -> 'too slow to enforce' (terminology).
- PORT_PLAN.md: recharacterize as capability checklist (not template);
  graduate contact-center capabilities to first-class domain; Rust-native
  trunk SIP rows; WASM demoted; thin-slice + capability ladder phasing.
- ADR-0001: marked Superseded by ADR-0003.
- ADR-0002 (new): north star + fused per-call core.
- ADR-0003 (new): Rust-native trunk SIP, no SBC shield.
- ADR-0004 (new): GPL-3.0-or-later license.
- ADR-0005 (new): Valkey as event bus + state store.
- ADR-0006 (new): WebRTC-first ingress; SIP endpoint deferred.
- vision-revision spec: status -> Ratified 2026-06-26.
2026-06-28 09:33:29 -04:00
adlee-was-taken
23cec14977 spec(slice-1): self-review fixes + terminology
- Clarify RtcSession/Channel ownership: ChannelId IS the session id;
  RtcSession owns both str0m Live + codecs and the Channel. Fixes ambiguity.
- Drop the separate /ice endpoint: non-trickle ICE bundles candidates
  into the SDP offer/answer, so the endpoint was redundant. Fixes
  contradiction.
- Clarify idle timeout = 'no RTP for 60s' (not 5 min blanket), and that
  no per-session tokio task is spawned (pre-paves the wrong pattern
  for step 4's dedicated thread).
- 'reflex to police' -> 'reflex to enforce' (terminology: avoid
  authoritarian verbs).
2026-06-28 09:30:55 -04:00
adlee-was-taken
2310367b15 spec: slice 1 — WebRTC media loopback design
Workspace scaffold + spearhead step 1: browser talks WebRTC to the core,
core terminates DTLS-SRTP, decodes Opus to canonical 16-bit PCM @24 kHz mono,
echoes back. Proves the media core + the codec-to-PCM boundary (pre-paves
the tap). Stubs lock the ADR-0002 fused-vertical boundaries for steps
2/5/6.

Drafted in brainstorming session 2026-06-28.
2026-06-28 09:26:38 -04:00
adlee-was-taken
098814b734 docs: capture vision revision — self-hosted AI-era contact-center engine
Records the decisions from pressure-testing the four founding docs:

- North-star reframe: the engine for the AI-era contact center, not an
  Asterisk-protocol successor (Asterisk's map = checklist, not template)
- Fused per-call vertical + composable horizontal platform (tightens the
  three-plane model; removes the control<->media hot-path gRPC hop)
- Rust-native trunk SIP, IP-allowlisted; drops the Kamailio/rtpengine C
  shield (reverses ADR-0001, to be formalized as ADR-0003)
- Pillars re-weighted: +data-ownership, spend-control promoted to
  constitutive, WASM demoted out of the core story
- Developer-first DX spine (config-as-code, AEL lesson, engine+batteries)
- GUI as pure API client (FreePBX model) + k8s declarative/operational split
- Sequenced thin-slice first proof + capability ladder

For review before applying to README/ARCHITECTURE/PORT_PLAN and writing
ADR-0002 (identity) and ADR-0003 (SIP).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RUtgQTo3wHGXP1TixHr4gd
2026-06-26 22:47:47 -04:00
adlee-was-taken
0370347642 ADR-0001: SIP strategy — native Rust core behind Kamailio + rtpengine
Record the SIP edge decision and align the docs:
- docs/adr/0001-sip-strategy.md: layered strategy (own Rust parser, rent the
  interop tail via a Kamailio + rtpengine SBC, grow native core behind the shield);
  pjproject FFI explicitly rejected for breaking the memory-safety thesis at the
  most exposed seam.
- PORT_PLAN §1 + open decisions: SIP row updated to the decided strategy.
- ARCHITECTURE: "biggest technical risk" now points at ADR-0001.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C2bfD7MkqEdfnMXxXBu456
2026-06-26 21:49:36 -04:00
adlee-was-taken
d3bd621aa0 Initial scoping: architecture + Asterisk→Rust port plan
Establish rutster — a memory-safe, API-first, security-first telephony
platform; spiritual successor to Asterisk for the WebRTC/microservices era.

- README: project framing, design pillars, open decisions
- docs/ARCHITECTURE.md: three-plane (control/media/app) model
- docs/PORT_PLAN.md: every Asterisk subsystem mapped to a disposition
  (core / WASM-plugin / service / edge-FFI / dropped / replaced) with rationale

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C2bfD7MkqEdfnMXxXBu456
2026-06-26 21:38:45 -04:00