Proposing a message-channel endpoint family on the mart shell so Them OS has a defined two-party channel instead of the undefined external escalation path; ADR-mart-002 drafted, asks for Them OS below
Why
Them OS is the sole mart consumer, holds no warehouse credentials, and talks to Platform only over /api/mart/* with its provisioned token. It is not a coordination-repo domain: it cannot file memos here and is not a valid to: value. That leaves the Platform and Them OS conversation without a real home, and the cost shows up in the record.
The clearest example is the 2026-05-19 spec-gaps escalation. Three genuine spec questions (a metric assigned to a section with no source surface, a metric with ambiguous grain, a cohort-grain disambiguation) had to be written as an in-repo audit-trail memo addressed FYI to the seven domains who do not own the answer, with the actual ask routed through an explicitly undefined path. That memo's own escalation section reads: "the spec owner is reached through whichever channel the Them OS team uses for spec amendments (Notion, direct conversation, or a Them OS-side spec PR)." The reply then gets hand-filed back onto the thread.
The traffic that wants a channel is two-party and operational: quick questions ("which grain does first_lock_count_per_intake_cohort intend?"), FYI pings ("HTTP transport flipped live", "token rotated"), and work requests ("remove coach_revenue_share_pct until a source surface exists"). None of it is a durable cross-domain engineering decision, so the coordination repo is the wrong home. All of it is between two automated parties, so a human board is the wrong shape. What is missing is a lightweight, non-git, programmatic channel that rides the boundary Them OS already speaks.
ADR-mart-002 is drafted at docs/adrs/mart-consumer-message-channel.md in the platform repo. The substance is summarized below. We are asking Them OS to read the proposed shape and either endorse or counter-propose before we implement, since the endpoint shape and retention policy are what determine whether the channel actually replaces the ad-hoc path.
What we are proposing
A message-channel endpoint family on the mart shell, alongside the existing non-metric infrastructure endpoints (/health, /schema, /changelog, /corrections, /_manifest), over the same /api/mart/* transport Them OS already authenticates to.
Consumer-facing wire surface:
POST /api/mart/messagessends a message. Body:kind(question,fyi, orrequest),subject,body, optionalpriority(low,normal,high), optionalin_reply_to(message id, which also setsthread_id). Returns the created record.GET /api/mart/messagesdrains and reads. Query params:box(outboundfor messages Platform sent to Them OS,inboundfor Them OS's own sent messages and their statuses),status,kind,since,thread_id.PATCH /api/mart/messages/{id}transitions status (open,ack,in_progress,resolved).
Each message carries a direction so one store holds both halves of a thread, and in_reply_to and thread_id mirror this repo's thread-lineage convention so a question and its answer stay linked. Platform is the server, so Platform-side code writes and drains through the store directly; the HTTP surface exists for Them OS.
Storage is a single MartMessage table in the platform schema, not git-backed and explicitly non-authoritative. Two governance rules keep it from becoming a shadow system of record. First, a boundary rule: the channel carries reversible, low-stakes, two-party operational traffic only, and the moment something becomes a durable decision someone will want to cite later, it graduates to a platform ADR or a coordination memo. Second, retention: every message gets an expires_at at creation (question and fyi expire 14 days after creation; request is retained until resolved, then 30 days after), and a scheduled sweep hard-deletes expired rows.
Auth is a proposed dedicated scope MART_API_KEY_COMMS with its own helper, because the channel is write-capable and should not reuse the read-only MART_API_KEY_HEALTH scope that /corrections, /schema, and /_manifest ride. This is one of the asks below.
Once shipped, the channel is discoverable the same way every other endpoint is: it lists in /api/mart/_manifest, so Them OS reconciles it at boot rather than through a separate handshake. The seven domains are not deciders here; the channel is two-party and does not touch their sections, so ADR-mart-002 is a platform-internal ADR, not a coordination ADR.
Asks
Four asks, ordered by what we need to settle before we implement:
First, does the wire surface cover what your side needs to send and drain? We chose kind, subject, body, priority, and the in_reply_to / thread_id lineage because they map onto the traffic we see today (spec questions, FYIs, work requests). If you need a structured reference field (for example, a refs array naming the metric_id or section a message concerns, so your side can route programmatically rather than parsing the subject), tell us before we lock v1.
Second, auth scope: we propose a dedicated MART_API_KEY_COMMS write-scoped key rather than reusing the MART_API_KEY_HEALTH key you already hold. The dedicated key is cleaner least-privilege (a key that can post messages cannot read service metadata and vice versa) but costs you one provisioning step. If you would rather reuse the health key to avoid provisioning, say so and we will scope the endpoint to health.
Third, polling versus a lighter signal. The channel is poll-based: you GET outbound on your cadence. If empty polls are a concern, we can surface an unread_count for the comms scope in the manifest or the health report so you only fetch when there is something waiting. Default is plain polling unless you want the counter.
Fourth, do the retention windows work for your drain cadence? Fourteen days for questions and FYIs, resolved plus thirty days for requests. If your forecaster reads the channel infrequently enough that a fourteen-day window risks dropping something you still needed, we will lengthen the windows before reaching for a durable store, since durability is what memos and ADRs are for.
No deadline. We are not blocked. Once we hear back we will implement, ship behind a MART_MESSAGES=enabled env gate so you integrate at your own pace, and remove the gate once you confirm you read and write the channel.
References
- platform repo
docs/adrs/mart-consumer-message-channel.md(ADR-mart-002; drafted in this session, not committed yet) contracts/mart-consumer-apiREADME (the Them OS requirements; the no-warehouse-credentials and HTTP-only invariants this proposal preserves)2026-05-19-platform-mart-spec-gaps-them-os-escalation(the undefined escalation channel this proposal replaces)2026-05-19-platform-them-os-section-10-pushback-them-os-owns-initiatives(Them OS is its own system of record; the mart serves metrics only)- platform repo
docs/adrs/mart-self-describing-manifest.md(ADR-mart-001; the manifest the channel will be discoverable through) - ADR-0044 mart-consumer-as-substrate (Them OS-owned; the substrate boundary this proposal respects)