Hackathon sprint in progress: read HACKATHON.md first.
You are working on Dock, a modular freight voice/SMS toolkit. The product in this repo is detention prevention. Docs are the contract. Code stays small and runnable.
Read in this order: docs/ARCHITECTURE.md, docs/VISION.md, docs/DEMO.md, then the package you were asked to touch.
Modules do not call each other in a graph. They read and write events.
uv run dock-events cat data/samples/harbor-rye.raw.jsonl \
| uv run dock-clock --replay --as-of 2026-10-17T22:05:00Z \
| uv run dock-notify \
| uv run dock-proof --load LL-88421 --print
dock-call plan and dock-proof --print.occurred_at when you display. Do not assume file order is time order.dock-clock drops facts after --as-of. Do not “helpfully” include the future unload when computing a warning.arrived already carries party names and phones. Do not add a database so notify can look up Dan. If a new fact is required later, put it on the event.
packages/dock-*, import names dock_events, dock_clock, and so on.docs/ARCHITECTURE.md.dock_call/plan.py, dock_intake/normalize.py), not only in a prompt string.guava at module import time. The live functions import it inside the live branch.send method in this starter. A new live send path checks DOCK_SMS_MODE=live or DOCK_CALL_MODE=live and still has a test that the default refuses.Decimal in Python and a "0.00" string in JSON.Z. Format America/New_York only at the edge, and label that zone ET.+155555501xx, MC-FAKE-88421, Harbor & Rye, Northwind, Red Kettle, Lantern Lane. Do not fetch a real load, MC, or phone number into the repo..env or put a key in a test, a fixture, or a default argument.dock-<name>: ... on stderr.uv sync
uv run pytest
uv run dock-events schema
uv run dock-web --port 8741
./examples/detention-pipe.sh
uv run python examples/build_sample.py
uv run pytest must pass with no GUAVA_API_KEY. If you add a test that needs Guava, skip it unless the package imports, and never let it dial.
When you change copy or clock math, regenerate data/samples/harbor-rye.trail.jsonl and read the diff. The web desk recomputes from the raw log, so a stale trail file fails the pipe test even if the page looks right.
| Change | Also update |
|---|---|
| New event type | model.py, schema_doc.py, docs/ARCHITECTURE.md, a test |
| Clock phase or money | tests/test_clock.py, sample trail, docs/ARCHITECTURE.md numbers, docs/DEMO.md if a headline changes |
| Preset button label | dock_web/presets.py and docs/DEMO.md |
| Heads-up wording | dock_notify/compose.py, notify test, sample trail |
| Call rules | dock_call/plan.py and the plan test. Keep the zero-dollar rule. |
The CLI and SDK are part of the environment. .cursor/install.sh (wired from .cursor/environment.json) installs the CLI with curl -fsSL https://goguava.ai/install.sh | sh, links it to /usr/local/bin/guava, and runs uv sync --frozen. guava-sdk>=0.48 is a root dependency. Do not log in and do not write keys into the repo.
guava --version
uv run python -c "import guava"
Auth, only when a task needs a live call: guava login, or the GUAVA_API_KEY environment variable. GUAVA_AGENT_NUMBER is the from-number. Leave both unset for tests.
Coding-agent starter: https://goguava.ai/docs/coding-agent-starter.md
agent.listen_phone(os.environ["GUAVA_AGENT_NUMBER"]).agent.call_phone(from_number=..., to_number=..., variables=...).agent.chat(variables=...) and agent.roleplay(prompt, variables=...).call.reach_person(...). Do not also call set_voicemail_action.purpose to one line. Put the goal in set_task and the checklist.guava.Client.send_sms and next_sms. Guava documents these as of 2026-10-17. The Twilio adapter remains a stub beside them.packages/dock-intake/dock_intake/guava_inbound.py and dock_call/plan.py serve_outbound are the seams. Extend those. Do not start a second agent framework.
dock-status, dock-docs, fleet compliance, and crash intake are specified in docs/ROADMAP.md and nowhere else. Do not create empty packages for them in a drive-by refactor. Crash intake has extra constraints in that file. Read them before adding fields about an accident.