Space concepts
Teams own the numbering
Section titled “Teams own the numbering”A team is a group of work with a short key: 2–6 characters, starting with a
letter, uppercase letters and digits only. ENG, DES, OPS, PLAT2.
Every issue belongs to exactly one team, and the team’s key is the prefix of
its issue key. Numbers count up per team, so ENG-1 and DES-1 both exist
and never collide. The number is assigned when the issue is created and never
changes.
The key — ENG-12 — is the identifier a person uses. The UUID underneath is
for programs. Every surface prints the key: the web app, the assistant, the
MCP tools, and the CLI, which all accept a key wherever an issue is named.
Status is a vocabulary, not a state machine
Section titled “Status is a vocabulary, not a state machine”Space has six statuses, in board order:
backlog → todo → in_progress → in_review → done → cancelled
Any status can move to any other. There is deliberately no table of legal
transitions. In a tracker, dragging a card from done back to todo is an
ordinary correction, not an error — a rule that refused it would be a rule
fighting the user. (Contrast Commerce, where an order’s
state machine is enforced, because an illegal order transition is fraud.)
Priorities are the same shape — a validated vocabulary with no ordering rules
imposed on it: none, low, medium, high, urgent.
Reordering the status list reorders the board, because the board groups by that same list rather than a second copy of it.
Everything is a thread
Section titled “Everything is a thread”Issue threads, channels and direct messages are three faces of one concept: a thread. This is the single most useful thing to know about Space’s shape.
| Surface | What it is |
|---|---|
| Issue thread | Created with the issue, carries its discussion |
| Channel | A named thread, public or private |
| Direct message | A thread between two members |
Because there is one underlying thread, messages behave identically in all three: reply to a specific message, edit or delete your own, react with an emoji, and get read-state tracked the same way. The issue-scoped message routes are a facade over the general thread routes — never a second implementation — so a change to how messages work applies everywhere at once.
Visibility and workspace scope
Section titled “Visibility and workspace scope”Every query in Space is scoped to your active
workspace. An id from another workspace is not an
error message, it is a 404 — the same answer as an id that does not exist,
so the API never confirms that someone else’s issue exists.
Within a workspace:
- Every member can read every issue. Filtering by assignee or creator narrows a list; it does not unlock one.
- A public channel is visible to the whole workspace.
- A private channel is visible only to its members. One you are not in is
not listed, and opening it by id is a
404. - Archived channels are read-only and hidden from the default list.
Unread and mentions
Section titled “Unread and mentions”Read state is per conversation, per person. The unread view returns, for each thread you can see: its kind (issue, channel or DM), how many messages you have not read, and how many of those mention you.
A mention is written @ followed by a member’s name, and it is resolved
against the workspace’s member directory when the message is posted. Longer
names win over shorter ones, so a member called “Ana” is not matched inside
“Ana Maria”. A mention that cannot be resolved simply does not fire — posting a
message never fails because the member directory was briefly unavailable.
Live updates, and what happens without them
Section titled “Live updates, and what happens without them”Space publishes events — issue.created, issue.updated, issue.deleted,
message.created, message.updated, message.deleted, reaction.updated,
channel.created, dm.created — over a server-sent event stream that the web
app subscribes to once per browser profile and shares across every open tab and
component.
Each event carries the id of the client that caused it, so the tab that made the change drops its own echo instead of rendering it twice.
Where live delivery is not configured for a deployment, the stream endpoint
answers 503 and the app switches itself to polling rather than retrying a
connection that will never open. Updates still arrive; they arrive later.
The three surfaces
Section titled “The three surfaces”Space’s operations reach you three ways, and all three are thin adapters over the same HTTP routes — none of them can do something the others cannot reach:
- The assistant in the web app, for a person in the middle of the work.
- MCP tools, for an AI coding agent that should file the ticket where the problem was noticed.
dst space, for a terminal or a script.
The assistant is the only one of the three with an approval gate, and it sits on exactly one verb: posting a message. Creating and updating issues is done directly, because it changes your own data, is reversible, and is visible the moment it happens. Posting speaks to other people under your name and cannot be unsent, so it always asks first.
Quotas
Section titled “Quotas”Space measures two things against your plan:
| What | Capability |
|---|---|
Open issues — those not done or cancelled |
max_open_issues |
| Monthly assistant model spend | max_hu_per_month |
Closing an issue frees its slot, because the count is of open issues rather than issues ever created.
The two gates fail in opposite directions on purpose. The issue count fails closed — if the policy cannot be answered, the write is refused, because an unanswerable policy means we do not know what you bought. The assistant’s spend budget fails open on infrastructure trouble and closed on the budget itself: a workspace genuinely out of budget is always stopped, but an unrelated outage must not silence every conversation at once.