0.1.0 base architecture

This commit is contained in:
ben
2026-04-14 14:36:18 -04:00
parent 149b841cb0
commit 5ad2b6b9b7
2 changed files with 286 additions and 13 deletions

View File

@@ -0,0 +1,106 @@
#+title: 0.1.0 v0 Bridge Contract
#+created: [2026-04-14 Tue 14:28]
* summary
v0 is a tiny Python relay bridging one XMPP MUC room to one Zulip stream/topic.
The bridge is append-only. It relays new human-written messages in both directions. It does not attempt to sync edits, reactions, threads beyond a fixed Zulip topic, presence, history, or rich metadata.
The design goal is to make transport behavior obvious. If something breaks, it should be clear whether the problem is Zulip ingress, XMPP ingress, relay logic, or configuration.
* first-run assumptions
- single bridge process
- single XMPP MUC room
- single Zulip stream + fixed topic
- trusted private deployment
- Python implementation
- one bridge identity on each side
- human-readable sender attribution is sufficient for v0
* system actors
** Zulip bot/client
- connects to one Zulip server
- subscribes to events for one stream/topic target
- receives new Zulip messages
- sends relay messages into the configured stream/topic
** XMPP client
- connects as one XMPP account
- joins one MUC room with one nick
- receives new groupchat messages
- sends relay messages into that room
** relay core
- owns config, logging, message normalization, and loop prevention
- accepts inbound events from either side
- converts them into one minimal internal message shape
- republishes them to the opposite side
* message flow
** Zulip -> XMPP
1. a new Zulip message arrives in the configured stream/topic
2. Zulip bot/client emits an inbound event to the relay core
3. relay core validates scope
- correct stream
- correct fixed topic
- not authored by the bridge itself
4. relay core normalizes sender name + body
5. relay core formats a plain relay message
6. XMPP client posts that message into the configured MUC room
7. relay core logs success/failure
** XMPP -> Zulip
1. a new XMPP groupchat message arrives in the configured MUC room
2. XMPP client emits an inbound event to the relay core
3. relay core validates scope
- correct room
- not authored by the bridge nick/account
- ignore non-message noise
4. relay core normalizes sender name + body
5. relay core formats a plain relay message
6. Zulip bot/client posts that message into the configured stream/topic
7. relay core logs success/failure
* v0 relay format
Plain text only.
Recommended shape:
- Zulip -> XMPP: "[zulip] <sender>: <body>"
- XMPP -> Zulip: "[xmpp] <sender>: <body>"
This is intentionally crude. The point is attribution and debuggability, not elegance.
* non-goals
- no message edit sync
- no delete sync
- no emoji/reaction sync
- no attachment mirroring in v0
- no presence mirroring
- no roster/contact sync
- no multi-room routing
- no per-thread/topic mapping beyond one fixed Zulip topic
- no history backfill
- no Hermes behavior in the transport process
- no Retcon writeback in the transport process
* operational boundaries
- the bridge should ignore service noise such as joins, parts, presence, and subscription events
- the bridge should only handle newly observed messages after startup
- the bridge should fail loudly in logs and stay simple in behavior
- the bridge should not try to be clever about replay, dedupe, or recovery yet beyond basic self-loop avoidance
* why this scope
This gives the smallest useful system:
- phone-friendly Zulip UI
- XMPP room remains the low-friction bus
- one boring relay to test whether the transport idea is worth keeping
If this small version is unreliable, adding Hermes or Retcon would only hide the real problems.
* exit condition for 0.1.0
Task 0.1.0 is complete when:
- this note exists
- the actor model is frozen
- both message directions are described
- v0 non-goals are explicit
- first-run assumptions are frozen

View File

@@ -1,22 +1,189 @@
#+title: Task Log
#+updated: [2026-03-18 Wed 14:19]
#+updated: [2026-04-14 Tue 13:26]
Use the template below, which should be a top-level org-mode header.
* [ ] M.m.m: Task Title (estimate # commits)
replace the old observed/canonical workflow with a review-first pipeline that groups normalized rows only during review/combine and links them to catalog items
* [x] 0.1.0: Define v0 bridge contract (estimate 1 commit)
Write a one-page spec for the first bridge: one XMPP MUC room <-> one Zulip stream/topic, append-only relay, no edits/reactions/history sync.
keep scope painfully small so transport bugs are obvious.
my preference is for python-based systems.
** Acceptance Criteria
1. Criterion
- expanded data
2. Criterion
- pm note: amplifying information
1. A short design note exists under pm/ or docs/
- includes message flow in both directions
- identifies system actors: Zulip bot, XMPP client, relay core
2. Explicit non-goals are listed
- no thread mapping beyond fixed topic
- no rich sync
- no presence mirroring
3. First-run assumptions are frozen
- single room
- single stream/topic
- trusted private deployment
** evidence
- commit: abc123, bcd234
- tests:
- datetime: [2026-03-18 Wed 14:15]
- commit:
- tests: n/a (design note only)
- datetime: [2026-04-14 Tue 14:28]
- artifact: pm/0.1.0-v0-bridge-contract.org
** notes
- explanation of work done, decisions made, reasoning
** notes
- This is the boundary-setting task; everything else depends on it.
* [ ] 0.1.1: Define canonical relay envelope + anti-loop rules (estimate 1 commit)
Specify the minimal message metadata the bridge must preserve and the exact loop-prevention mechanism.
** Acceptance Criteria
1. Canonical fields are listed
- origin
- source message id
- sender display name
- target room mapping
- timestamp
2. Loop prevention rule is explicit
- bridge stamps outgoing messages
- bridge ignores messages carrying its own origin marker
3. Failure handling is defined
- duplicate delivery behavior
- malformed message behavior
- reconnect replay policy
- pm note: this is the real core of v0; if this is fuzzy the bridge will thrash.
** evidence
- commit:
- tests:
- datetime:
** notes
- Prefer boring explicit metadata over clever heuristics.
* [ ] 0.1.2: Survey Zulip bot constraints + auth model (estimate 1 commit)
Confirm what kind of bot/client should be used on the Zulip side and document any constraints that change architecture.
** Acceptance Criteria
1. Zulip integration mode is chosen
- bot user vs normal user account
- event queue / polling approach
2. Constraints are captured
- message formatting limitations
- topic requirements
- rate limits / event semantics if relevant
3. Setup checklist is written
- credentials needed
- permissions needed
- minimal stream access needed
- pm note: Zulip quirks may force the shape of the relay more than XMPP will.
** evidence
- commit:
- tests:
- datetime:
** notes
- Keep this empirical; document only constraints that affect v0.
* [ ] 0.1.3: Survey XMPP MUC event model + library options (estimate 1 commit)
Pick the first XMPP client library/runtime and document the exact events needed for room relay.
** Acceptance Criteria
1. First implementation language/runtime is chosen
- likely Python unless a strong reason says otherwise
2. Library candidates are compared briefly
- connection support
- MUC message receive/send
- reconnect behavior
3. Required event subset is documented
- groupchat message receive
- send message to MUC
- ignore join/leave/presence noise
- pm note: avoid solving the Emacs client here; this is just relay transport.
** evidence
- commit:
- tests:
- datetime:
** notes
- Goal is “good enough to prototype,” not perfect XMPP abstraction.
* [ ] 0.1.4: Write config schema for single-room bridge (estimate 1 commit)
Design the smallest possible config file/environment contract for running one bridge instance.
** Acceptance Criteria
1. Config fields are listed
- Zulip site/email/api key
- Zulip stream/topic
- XMPP jid/password/muc room/nick
2. One-room mapping is represented simply
- avoid generalized many-room config unless needed
3. Secrets vs non-secrets are separated
- env vars or secrets file for credentials
- checked-in example config for everything else
- pm note: optimize for easy local bring-up, not future elegance.
** evidence
- commit:
- tests:
- datetime:
** notes
- If the config shape feels overdesigned, shrink it again.
* [ ] 0.1.5: Define observability + manual test plan for v0 (estimate 1 commit)
Specify how to tell whether the bridge is healthy before adding Hermes.
** Acceptance Criteria
1. Logs are defined
- startup config summary without secrets
- inbound message event
- outbound relay result
- duplicate/loop drop reason
2. Manual test cases are listed
- Zulip -> XMPP happy path
- XMPP -> Zulip happy path
- duplicate suppression
- reconnect after disconnect
3. Success criteria are concrete
- messages appear once on each side
- sender attribution preserved enough for humans
- no infinite echo loops
- pm note: make the bridge boring before attaching Hermes or Retcon.
** evidence
- commit:
- tests:
- datetime:
** notes
- This should become the operator checklist for first deploy.
* [ ] 0.1.6: Sketch Hermes/Retcon follow-on integration points (estimate 1 commit)
Document where Hermes and Retcon could attach after transport is stable, without implementing them yet.
** Acceptance Criteria
1. Hermes interaction modes are listed
- passive listener
- command-triggered actor
- summarizer
2. Retcon integration points are listed
- append raw inbox
- synthesize summaries
- extract durable notes
3. Trust boundaries are explicit
- what can be written automatically
- what should remain user-confirmed
- pm note: this keeps the long-term vision visible without contaminating v0 scope.
** evidence
- commit:
- tests:
- datetime:
** notes
- Hermes should arrive after transport and logging are stable.