generated from ben/template
0.1.0 base architecture
This commit is contained in:
106
pm/0.1.0-v0-bridge-contract.org
Normal file
106
pm/0.1.0-v0-bridge-contract.org
Normal 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
|
||||||
193
pm/tasks.org
193
pm/tasks.org
@@ -1,22 +1,189 @@
|
|||||||
#+title: Task Log
|
#+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.
|
Use the template below, which should be a top-level org-mode header.
|
||||||
|
|
||||||
* [ ] M.m.m: Task Title (estimate # commits)
|
* [x] 0.1.0: Define v0 bridge contract (estimate 1 commit)
|
||||||
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
|
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
|
** Acceptance Criteria
|
||||||
1. Criterion
|
1. A short design note exists under pm/ or docs/
|
||||||
- expanded data
|
- includes message flow in both directions
|
||||||
2. Criterion
|
- identifies system actors: Zulip bot, XMPP client, relay core
|
||||||
|
2. Explicit non-goals are listed
|
||||||
- pm note: amplifying information
|
- 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
|
** evidence
|
||||||
- commit: abc123, bcd234
|
- commit:
|
||||||
- tests:
|
- tests: n/a (design note only)
|
||||||
- datetime: [2026-03-18 Wed 14:15]
|
- datetime: [2026-04-14 Tue 14:28]
|
||||||
|
- artifact: pm/0.1.0-v0-bridge-contract.org
|
||||||
|
|
||||||
** notes
|
** notes
|
||||||
- explanation of work done, decisions made, reasoning
|
- 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.
|
||||||
|
|||||||
Reference in New Issue
Block a user