Skip to content

Decision 110: an instance is a named, scoped cli-config.yaml; new work reaches it by mode and by address ​

  • Status: proposed
  • Date: 2026-09-08
  • Work item: issue-322
  • Deciders: MadaraUchiha-314 (the ask and its three questions), the-loop (design); MadaraUchiha-314 (owner, at the PR)
  • Refines: decision-032 (the CLI config is the daemon's, not a repository's), decision-040 (the label arms, an authorized start runs), decision-046 (portable vs local state)

Context ​

Every instance of the-loop was the same instance: one cli-config.yaml describes one set of daemons, and every daemon judges every labelled event the same way. Two instances watching one repository both spawn for one the-loop start. The issue asks for several instances in isolated environments, each scoped to its own work items, with a way to say which work item goes where and a way to lock an instance — and asks whether the scope is a new file, and how one talks to an instance.

Two later additions are named as constraints, not deliverables: a manager instance that serves the same API aggregated across instances, and an instance managed from a ticket.

Decision ​

#What was chosenWhy
D1The scope lives in cli-config.yaml, under a top-level instance block — no second file.An instance is a running CLI config (decision-032): the file already names the daemons, the state root, the authorized users. It is hot-reloaded by both daemons and the service and editable from the dashboard, so a scope edit is live without a restart. A second file would be a second thing to find, back up, reload and document — for three keys.
D2The managed set is derived, not kept: the declared list ∪ live session records ∪ control records.The instance already writes a record for every work item it acts on (decision-046's portable half, and the local registry). "What am I managing?" is a question those records answer; a second list would drift from them. The declared list is the one thing the records cannot know: what the operator wants added.
D3Three modes, not a boolean: open (13.3.1 — take any armed, authorized start), addressed (take only what names me), locked (take nothing new; the declared list is the door).The issue's "lock" is the closed end. But two instances need a steady state that is neither wide open nor frozen: addressed is the multi-instance normal, where every start says which instance runs it. open stays the default so a lone instance that names itself changes nothing.
D4An address token in the comment — instance:<name>, grammar-validated, beside any keyword — rather than a per-instance keyword vocabulary.Keywords are already configurable per config, so laptop-b start could be done today by renaming eleven keywords on each instance; it would also split the thread's vocabulary and every doc. One token composes with every command, is validated like the collaborator @login (issue-307), and is what a future ticket-managed instance would type.
D5An explicit address is authoritative — it wins over the managed set, and an address never unlocks a locked instance.The human named the instance; a managed-set override would let two instances both act on one steer. Locked means locked: the only door is the config (the issue's own wording).
D6A refusal leaves no mark: no reaction, no comment, no record — an event-log line and a settled delivery.Another instance may own the work item. A non-owner that reacts or comments is noise on the thread, and a non-owner that records a stop is a second daemon steering the item.
D7Unknown or impossible scope config narrows: an unknown mode and addressed without a name both resolve to locked, with a warning.A scope typo must not make an instance take on work it was not meant to. locked is loud in status and the event log; open would be silent and wrong.
D8The future manager is a client, not a peer protocol. Each instance serves one identical surface, GET /api/v1/instance names it and lists its managed set, control.instance is on every portable record; instances share nothing and never talk to each other.Aggregation over N base URLs is exactly what the dashboard already does for one; a peer protocol would add a second trust boundary and a discovery problem this work item has no requirement for.
D9instance.ticket is reserved, not added.An instance managed from a ticket is a loop of its own (which events, which keywords, which gates); designing the binding before that loop is guessing. The token (D4) and the block (D1) are where it attaches.

Consequences ​

Good. Two instances on one repository stop spawning for the same start once either is addressed or locked; an operator can pin a work item to an instance by config or by one word on the ticket; the thread and the portable record say which instance took an item; a session knows its instance (THE_LOOP_INSTANCE); an unnamed open instance is byte-for-byte 13.3.1.

Costs, accepted. Two open instances still clash — the design makes the steady state reachable, not automatic, and the guide says so. A work item declared on two instances is managed by both; that is the operator's declaration, honoured. A comment consumed by a refusal is not re-judged when the scope changes — the operator claims it with the-loop sessions start on the instance, which is the addressed form.

Alternatives considered ​

AlternativeWhy not
A separate instance.yaml / scope.yamlA second file with three keys, outside the reload and the dashboard; the issue's own question, answered: no
A registry of "my work items" the instance appends to on claimDrifts from the records that already say the same thing (D2); a second write on every claim path
A boolean locked onlyNo steady state for several instances short of freezing them (D3)
Per-instance keywords (laptop-b start)Splits the vocabulary per instance across eleven keywords and every doc; composes with nothing (D4)
@name as the addressPings a GitHub user of that name
Claim by label (the-loop: instance/laptop-b)A label is a fact about the item, not a steer for one command; every instance would need label-write rights and a race on who labels first
The managed set wins over an explicit addressTwo instances act on one steer when both manage an item (D5)
Reacting or commenting on a refusalMarks from a non-owner (D6)
Unknown mode → openFails open on a typo (D7)
A gossip / lease protocol between instancesA second trust boundary and a discovery problem with no requirement behind it (D8)

Released under the MIT License.