@remits/remits-cli 0.1.114 → 0.1.115

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remits/remits-cli",
3
- "version": "0.1.114",
3
+ "version": "0.1.115",
4
4
  "description": "Local CLI for auth, component sync, and live test execution against Remits",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -76,11 +76,20 @@ reference named after it.
76
76
  - **Ask which world your checkout resolves before you run anything:** `remits-cli components status`.
77
77
  A trunk checkout and a variant-branch checkout differ on both ends of the loop — what a run resolves
78
78
  and what a sync writes. Do not infer it from the branch name. (`branch-variants.md`)
79
+ - **Start from a steady git baseline before the first edit.** Run `git fetch origin`; confirm
80
+ `git log origin/<branch>..<branch>` and `git log <branch>..origin/<branch>` are both empty; then run
81
+ `remits-cli components status`. On a variant branch also run `remits-cli components promotion --branch
82
+ <branch>`. A workspace isolates staging, not the commit your files are based on. (`development-loop.md`,
83
+ `branch-variants.md`)
79
84
  - **Resolution order is staged → variant → trunk, and each layers over the one beneath.** A populated
80
85
  staging cache makes a committed variant look broken through any tokenized entry point; clear it before
81
86
  verifying variant resolution. (`component-resolution.md`)
82
87
  - **Host and data mode are two independent decisions.** `--base-url` picks the Remits host,
83
88
  `--data-mode` picks the data segment on it. Neither implies the other. (`command-reference.md`)
89
+ - **`test run` ignores the stored session data lane.** It defaults to `test` even when `whoami` shows
90
+ the session parked on prod; production Test runs require explicit prod provenance (`--data-mode prod`)
91
+ or Test source declaring `dataMode 'prod'` / `[dataMode:'prod']`. Check returned `dataModeSource`
92
+ when auditing a run. (`command-reference.md`)
84
93
  - **A tool's `dataMode` input never widens the lane.** It may narrow `prod` → `test`, never escalate
85
94
  `test` → `prod`. The response's `dataMode` is the truth, not your input. To reach prod data, pass
86
95
  `--data-mode prod` on the command line. (`account-targeting.md`)
@@ -95,6 +104,10 @@ reference named after it.
95
104
  component (preferred, because it becomes regression protection) or a browser flow through
96
105
  `remits-cli token`. "Just do it" and "that's fine, commit it" are not evidence. If you genuinely
97
106
  cannot verify, say what you would need and ask. (`development-loop.md`)
107
+ - **Read the component's `.meta.yml` before changing behavior.** Sidecar descriptions can be dated
108
+ decision records. Before changing a displayed value, helper, calculation, schema field, or prompt
109
+ contract, check the sidecar and either preserve its decision or explicitly supersede it.
110
+ (`development-loop.md`)
98
111
  - **Read the account's `resolution` block before acting on it** — `role`, `type`,
99
112
  `resolvedDatabaseName`, `relationships`. More than one relationship means the account can legitimately
100
113
  resolve differently depending on the path a request travelled. Never infer an account's shape from its
@@ -111,6 +124,12 @@ reference named after it.
111
124
  - **Reading and investigating are parallel-safe; editing one account's repository is exclusive**, via a
112
125
  lease. A refusal is not an error — carry on read-only and hand off with `ticket progress --next-step`.
113
126
  Never wait or poll for a lease. (`support-tickets.md`)
127
+ - **A brief's `## Rules you will be held to` section is ENFORCED, not requested.** The platform refuses
128
+ the verb and the message says what to do instead — act on that sentence rather than retrying or
129
+ looking for another door. A `[require]` rule needs a person; hand off. (`support-tickets.md`)
130
+ - **`components commit` takes a short landing lease on `(account, branch)`.** Refused means somebody else
131
+ is landing right now — keep staging and iterating, which is lane-isolated, and retry in a minute.
132
+ Never loop on it. (`development-loop.md`)
114
133
  - **If something looks wrong, stop — do not paper over it.** Unexpected deletes, creates, renames,
115
134
  uniqueness errors, id drift, or a 500 from the platform: stop, preserve the session log and tool
116
135
  responses, and escalate. Never create replacement components to make ids line up, and never discover
@@ -139,7 +158,11 @@ repo's `account-info.json`. `cli-state.md` maps every remaining question to its
139
158
 
140
159
  Keep support and development sessions lean:
141
160
 
142
- - Prefer local repo files over remote tools whenever the target account repo exists locally.
161
+ - Prefer local repo files over remote component tools whenever the target account repo exists locally.
162
+ `mcp_component_view` / `mcp_component_grep` are fallback surfaces for agents without that checkout,
163
+ or for confirming what the live DB has stored after you already understand the files. For a ticket
164
+ with `implementationAccountId`, resolve that account's indexed repo first, pull the appropriate
165
+ branch when the checkout is clean, and inspect `account-info.json` + `components/` there.
143
166
  - Do not read entire `.remits-cli/sessions/*.jsonl` or large tool response files unless you first narrow
144
167
  to the relevant request, endpoint, tool, or ticket.
145
168
  - Prefer targeted Firestore queries: use `documentId`, tight `filters`, narrow `fields`, and low `limit`
@@ -53,9 +53,18 @@ Two more, easily confused: top-level **`componentBranches`** lists the variant b
53
53
 
54
54
  ### Repo selection rules
55
55
 
56
- - **Inside the target implementation repo**: read `account-info.json` and inspect `components/` directly.
57
- - **Inside one repo but supporting a different account**: switch to that account's repo if it exists;
58
- otherwise use `mcp_account_view` / `mcp_component_view` / `mcp_component_grep`.
56
+ - **Inside the target implementation repo**: make sure you are on the relevant branch and the checkout is
57
+ current before reading source or editing. Run `git fetch origin`; when the tree is clean,
58
+ `git pull --ff-only origin <branch>`; then confirm `git log origin/<branch>..<branch>` and
59
+ `git log <branch>..origin/<branch>` are both empty. A worktree can have an isolated staging workspace
60
+ and still be based on a stale commit. Then read `account-info.json` and inspect `components/` directly.
61
+ - **Inside one repo but supporting a different account**: switch to that account's indexed repo if it
62
+ exists. For tickets, prefer `implementationAccountId` / `implementationAccountName` over the reporting
63
+ `accountId` when choosing that repo; a subscriber or client often reports the symptom while the
64
+ implementation lives in an upstream `PLATFORM` / `PRODUCT` repo.
65
+ - **Only use `mcp_component_view` / `mcp_component_grep` when the correct repo is not available locally,**
66
+ or when you are deliberately comparing local source to the live DB after reading the files. They are not
67
+ the normal way to learn source on a machine with the account repo.
59
68
  - **Outside any repo**: rely on the tools, and `mcp_get_guide` for the front-stage guides.
60
69
  - **Never create a new local repo/directory just because a ticket references an account name.** Resolve the
61
70
  account type and parent hierarchy first, and work only from an existing indexed repo unless the user
@@ -68,7 +68,7 @@ capacity. For each new ticket it launches a headless worker:
68
68
 
69
69
  | | headless invocation | edit mode | investigate mode |
70
70
  |---|---|---|---|
71
- | `codex` | `codex exec --cd <repo>` | `--sandbox workspace-write` | `--sandbox read-only` |
71
+ | `codex` | `codex exec --cd <repo>` | `--sandbox workspace-write` | `workspace-write with investigation-only brief and no edit lease` |
72
72
  | `claude` | `claude -p --add-dir <repo>` | `--permission-mode acceptEdits` | `--permission-mode plan` |
73
73
  | `gemini` | `gemini -p` in `<repo>` | `--approval-mode auto_edit` | `--approval-mode plan` |
74
74
 
@@ -83,6 +83,9 @@ and the worker are one answer, not two.
83
83
  The brief always arrives on **stdin**, never in argv — it is a page of prose and argv has a hard
84
84
  length limit, so an argv brief would fail on exactly the detailed tickets that most need the detail.
85
85
  The brief itself is generated by the platform, so all three worker types are told the same thing.
86
+ In `--mode investigate`, the supervisor still claims tickets and may update them with findings, but it
87
+ does **not** acquire or renew the repository edit lease. The brief says the run was launched for
88
+ investigation only and forbids file edits, component staging, commits, and manual lease escalation.
86
89
 
87
90
  **Following a run.** `remits-cli start`'s control center lists every worker; **Follow live** streams
88
91
  that run's transcript into the page, rendering commands with their exit codes, file edits, and the
@@ -162,6 +165,7 @@ and holds a PID lock (`~/.remits-cli/listener.pid`) so only one runs per machine
162
165
 
163
166
  The control center shows, in one browser view:
164
167
  - which agent sessions are registered, what each is doing right now, and its recent activity
168
+ - live and recent worker runs, with historical transcript follow/stop controls keyed to the exact run
165
169
  - the open support-ticket queue, and which agent each ticket is routed to
166
170
  - a control to route a ticket at a specific available agent
167
171
  - websocket connection and topic health
@@ -81,6 +81,22 @@ checkout and 15/15 from trunk, with no code difference.) **Run branch-variant su
81
81
  - **Nothing is renamed.** A variant sync never renames files and never repoints the account's trunk
82
82
  branch. A `new_*` file stays `new_*`.
83
83
 
84
+ **Start from a current branch, not just an isolated workspace.** Before the first edit in a variant
85
+ checkout:
86
+
87
+ ```bash
88
+ git fetch origin
89
+ git status --porcelain
90
+ git log origin/<branch>..<branch> # must be empty: nothing local-only
91
+ git log <branch>..origin/<branch> # must be empty: not behind the remote
92
+ remits-cli components promotion --branch <branch>
93
+ ```
94
+
95
+ `components promotion` reads the remote and reports whether the branch is also current with trunk. If it
96
+ says `diverged` or `STALE`, merge trunk in or sync first, as instructed, before writing new work. A
97
+ workspace lane prevents another agent from overwriting your staged Redis snapshot; it does not say which
98
+ commit your files are based on.
99
+
84
100
  **Branch-local `account-info.json` can describe a subscriber.** On a variant branch the repository is
85
101
  still the OWNER's component repo — files overlay that owner's trunk ids and sync writes overlays owned by
86
102
  that owner. But when the checkout was synced from a subscribing account reached through an
@@ -193,7 +209,10 @@ resolution on production/subscription semantics. Do **not** use this pattern wit
193
209
  ### The SDLC is identical on a variant branch
194
210
 
195
211
  ```bash
196
- git checkout feature_branch # or: git checkout -b feature_branch
212
+ git fetch origin
213
+ git checkout feature_branch
214
+ git pull --ff-only origin feature_branch
215
+ remits-cli components promotion --branch feature_branch
197
216
  # edit components/actions/50_ExtractInvoice.groovy (KEEP the trunk id)
198
217
  remits-cli components stage # Redis, scoped to this branch — same as always
199
218
  remits-cli test run --test "Invoice Tests" # the feature_branch world
@@ -158,7 +158,7 @@ remits-cli data-mode set test # Switch back to test for development
158
158
  remits-cli auth [--base-url URL] [--account-id ID] [--data-mode test|prod]
159
159
  remits-cli sessions [list|remove] [--account-id ID]
160
160
  remits-cli config [set] [--agent claude|codex|gemini]
161
- remits-cli agent serve [--worker-agent claude|codex|gemini] [--max-concurrent N] [--mode edit|investigate] [--label NAME] [--data-mode test|prod]
161
+ remits-cli agent serve [--worker-agent claude|codex|gemini] [--max-concurrent N] [--mode edit|investigate] [--serves a,b] [--label NAME] [--data-mode test|prod]
162
162
  remits-cli agent workers [--json]
163
163
  remits-cli agent register [--label NAME] [--data-mode test|prod] [--account-id ID] [--max-concurrent N]
164
164
  remits-cli agent work [--wait SECONDS] [--json]
@@ -181,7 +181,7 @@ remits-cli ticket artifact --ticket ID --type TYPE --label "..." [--url U | --co
181
181
  remits-cli ticket participant --ticket ID --email E [--role watcher|requester|agent]
182
182
  remits-cli ticket field --ticket ID --key K --value V # the ORGANIZATION's own field, outside the planning slots
183
183
  remits-cli ticket reclaim [--ticket ID | --account-id ID] [--stale-hours 24] [--apply] # OPERATOR: take back an agent's abandoned ticket
184
- remits-cli ticket queue --account-id ID [--status ...] [--unrouted] [--unassigned] [--awaiting-response] [--workstream W] [--board-stage S] [--planned-in P] [--search "..."] [--sort-by ...] [--json]
184
+ remits-cli ticket queue --account-id ID [--status ...] [--unrouted] [--unassigned] [--awaiting-response] [--min-runs N] [--workstream W] [--board-stage S] [--planned-in P] [--search "..."] [--sort-by ...] [--json]
185
185
  remits-cli ticket create --account-id ID --subject "..." --type defect|question|task|incident|enhancement [--priority P] [--description "..."] [--tags a,b] [--workstream W] [--affected-component C] [--implementation-account-id ID] [--reference-id KEY]
186
186
  remits-cli start [--foreground true] [--port 8787]
187
187
  remits-cli stop
@@ -211,7 +211,9 @@ remits-cli tool status --call-id <callId> [--data-mode test|prod]
211
211
  ```
212
212
 
213
213
  For tests specifically:
214
- - If `--data-mode` is omitted, `remits-cli test run` uses `test`.
214
+ - If `--data-mode` is omitted, `remits-cli test run` uses `test` and sends `dataModeSource:"cliDefault"`.
215
+ An explicit `--data-mode prod` sends `dataModeSource:"explicitFlag"` so production test runs are
216
+ auditable from the server status payload even when the original terminal history is gone.
215
217
  - `--names` is `|`-delimited (a comma still splits a single value) and may be repeated; an unmatched
216
218
  selector fails the run instead of reporting zero cases as success.
217
219
  - `--as-account <ID>` runs AS a descendant subscriber so its edge selects the component branch
@@ -135,9 +135,14 @@ file is catastrophic.
135
135
  variant branch the id/delete/renumber checks below apply to the **overlay set** instead: confirm every
136
136
  component absent from the branch is *meant* to be tombstoned for subscribers.
137
137
  - The user intends durable platform promotion now — not just local edits, staging, or verification.
138
+ - `git fetch origin` has run, and this checkout matches the remote branch the platform will sync:
139
+ `git log origin/<branch>..<branch>` and `git log <branch>..origin/<branch>` are both empty. A local
140
+ commit that is not pushed is invisible to Remits; a local branch behind the remote is a stale baseline.
138
141
  - `git status --short` shows only intended changes; every rename/delete is explained. **No component file has
139
142
  been renumbered to a different id.**
140
- - Local branch is committed and pushed; sync will read the intended remote commit.
143
+ - Local branch is committed and pushed; sync will read the intended remote commit. If a sync just
144
+ completed, `git pull --ff-only origin <branch>` has run before any next git operation, because sync may
145
+ push generated artifacts back to the branch.
141
146
  - Local filenames and live inventory (`mcp_account_view`) **agree on id and name for every component**: no live
142
147
  component appears locally under a different id, and no expected component is missing a repo file.
143
148
  > **Do not run this comparison against `account-info.json` alone — it will report false orphans.** That
@@ -153,7 +153,11 @@ overwrite each other, and a `components commit` clears the lane out from under t
153
153
  If more than one agent is working on the same branch, give each its own workspace:
154
154
 
155
155
  ```bash
156
- git worktree add ../repo-agent-a forked # one checkout per agent, same branch
156
+ git fetch origin
157
+ git switch forked
158
+ git pull --ff-only origin forked
159
+ git rev-list --left-right --count HEAD...origin/forked # must print: 0 0
160
+ git worktree add --force ../repo-agent-a forked # one checkout per agent, same branch
157
161
  cd ../repo-agent-a
158
162
  remits-cli workspace use --auto # names the lane after this directory
159
163
  remits-cli components stage # isolated: nobody else sees it, nobody overwrites it
@@ -161,6 +165,14 @@ remits-cli test run --test 42
161
165
  remits-cli token --path /page/whatever
162
166
  ```
163
167
 
168
+ That first block matters. `git worktree add ... forked` uses the local `forked` ref; it does not fetch or
169
+ prove that `forked` equals `origin/forked`. If the local ref is stale, every isolated staging lane starts
170
+ from the same stale files and a later sync looks like a deliberate revert. Before the first edit in a new
171
+ or reused worktree, `git status --porcelain`, `git log origin/<branch>..<branch>`, and
172
+ `git log <branch>..origin/<branch>` should all be empty. For variant branches, run
173
+ `remits-cli components promotion --branch <branch>` too; a branch can be current with its own remote and
174
+ still stale relative to trunk.
175
+
164
176
  A workspace narrows STAGING and nothing else. A commit still targets the same branch and the same owner
165
177
  account, and the run still resolves whatever committed variant branch the account subscribes to — so it
166
178
  does **not** have the side effects of inventing a throwaway git branch per agent (which would make a
@@ -93,6 +93,22 @@ This is how every development task should flow:
93
93
  #### Step 1: Understand the Request
94
94
  Read the user's request. If you may need a repo other than the current one, read `~/.remits-cli/account-repos.json` first. Then review `account-info.json` and `README.md` to understand what components exist and how they relate. Read the source of any component you'll modify before changing it.
95
95
 
96
+ **Establish a steady git baseline before the first edit.** The platform syncs from the GitHub remote, not
97
+ from your local files, and a worktree can be stale even when its staging lane is isolated. In the checkout
98
+ you will edit:
99
+
100
+ ```bash
101
+ git fetch origin
102
+ git status --porcelain # empty, or only generated guide files you will discard
103
+ git log origin/<branch>..<branch> # empty: no local commits invisible to the platform
104
+ git log <branch>..origin/<branch> # empty: not behind the remote the platform syncs
105
+ remits-cli components status
106
+ ```
107
+
108
+ For a non-trunk variant branch, also run `remits-cli components promotion --branch <branch>`. If it reports
109
+ that the branch is behind trunk or that overlays were computed from an old SHA, settle that before changing
110
+ code. A workspace prevents staged-cache collisions; it does not make a stale branch current.
111
+
96
112
  **Establish the account's shape too, not just its components.** Read the `resolution` block in
97
113
  `account-info.json` (or `mcp_account_view`): the account `type` decides whether this repo is even the right
98
114
  place to change code, `resolution.relationships` shows whether the account has more than one parent (and
@@ -108,6 +124,11 @@ variants of these components exist: editing an origin component will drift them,
108
124
  #### Step 2: Make the Change
109
125
  Edit component files under `components/`. This is local file editing — the platform doesn't know about your changes yet.
110
126
 
127
+ Before changing a displayed value, helper, calculation, schema field, or prompt contract, read that
128
+ component's existing `.meta.yml` sidecar too. Descriptions often carry dated decisions and line-number
129
+ references explaining why a value looks odd. If you are reversing one, say so in the new sidecar text;
130
+ otherwise you are probably reopening a closed bug.
131
+
111
132
  **Creating a component that does not exist yet.** Files are named `<id>_<Name>.<ext>`, where the numeric
112
133
  prefix is the platform's component id. A new component has no id, so name its files with the **`new_`
113
134
  prefix** and let the sync assign one (it then renames the files to that id):
@@ -272,7 +293,7 @@ If the work is tied to a support ticket:
272
293
 
273
294
  Before committing, update metadata so the next session understands what changed:
274
295
 
275
- 1. **`.meta.yml` sidecars** — Update `summary`, `description`, and `mermaid` for each modified component. `summary` is what drives the compact component description in generated `account-info.json`; `description` is the fallback when no summary is set and is capped in that file.
296
+ 1. **`.meta.yml` sidecars** — Update `summary`, `description`, and `mermaid` for each modified component. `summary` is what drives the compact component description in generated `account-info.json`; `description` is the fallback when no summary is set and is capped in that file. Preserve or explicitly revise dated decision notes; do not delete the evidence the next agent needs.
276
297
  2. **`README.md`** — If the change affects account-level capabilities or workflows.
277
298
  3. **New components** — Always fill in `.meta.yml` immediately.
278
299
 
@@ -316,7 +337,15 @@ This separates the local failure boundaries cleanly:
316
337
  1. Local git commit
317
338
  2. Remote push
318
339
 
319
- After the push, run the **`component-integrity.md`** safety checks before any durable platform sync. Do not run
340
+ After the push, run `git fetch origin` and confirm both local and remote agree on the branch you are about
341
+ to sync:
342
+
343
+ ```bash
344
+ git log origin/<branch>..<branch> # empty
345
+ git log <branch>..origin/<branch> # empty
346
+ ```
347
+
348
+ Then run the **`component-integrity.md`** safety checks before any durable platform sync. Do not run
320
349
  `remits-cli components sync` when local files, `account-info.json`, and live inventory disagree about component
321
350
  IDs or when unexpected deletes/renumbers are present.
322
351
 
@@ -340,6 +369,29 @@ unexpectedly, stop and inspect the repo-local session log before running any mut
340
369
 
341
370
  **Git is required for durable sync.** The platform syncs by pulling from the git remote (`GitHubClient.syncFromRepository`). If `git push` fails, the server has nothing new to sync. You can still **stage** and **test** without git — only durable sync requires it.
342
371
 
372
+ **Landing is serial, and the platform now enforces it.** `components commit` takes a short exclusive
373
+ landing lease on `(account, branch)` before it pushes, and `components sync` takes it too. If another agent
374
+ is landing that branch you are refused with a sentence naming who holds it and how long is left:
375
+
376
+ ```
377
+ Refused: Branch 'forked' on account 33 is being landed by dev@acme.test in /Users/dev/wt/acme-a ...
378
+ Keep staging and iterating — staging is lane-isolated — and land when this clears.
379
+ ```
380
+
381
+ Do exactly that. **Do not loop on the refusal**: the lease is minutes at most, staging and testing are
382
+ unaffected because they are lane-isolated, and retrying in a tight loop just burns the run. The reason it
383
+ is serial at all is that `git add -A` sweeps a shared checkout and the platform pushes a regenerated
384
+ `account-info.json` back to the branch during sync, so two commits racing one branch collide on the remote.
385
+
386
+ **Staging also refreshes your presence.** You do not need `remits-cli agent register` for other agents to
387
+ see you: `components stage` records `(user, checkout, branch, workspace)` so headless workers on other
388
+ machines find you in their "current repository activity" block instead of assuming the repository is
389
+ theirs. A derived record is never routed work.
390
+
391
+ **An account may make `commit` a refusal outright.** A `no-commit` rule in its `OPERATIONS` process means
392
+ the platform refuses the landing lease and the sync — leave your changes in the working tree and describe
393
+ them on the ticket. Read `support-tickets.md` §"Some of that process is enforced, not requested".
394
+
343
395
  #### Step 8: Close the Ticket
344
396
 
345
397
  If the request came from a support ticket, the task is not complete until you update the ticket lifecycle yourself:
@@ -187,7 +187,10 @@ Before starting an investigation outside the confirmed current repo:
187
187
  8. `mcp_user_activity` — for "user X is slow right now" reports, list sessions by `userId`/`accountId`, open the session story, and use the returned beat pivots.
188
188
  9. `mcp_performance_trace` — for slow/sluggish reports, open the beat `traceId` with `action:"trace"`; use `action:"slowest"` when you only have a broad time window.
189
189
  10. `mcp_system_logs` — correlate via `threadGroupingId` for raw log context when the trace needs supporting log lines.
190
- 11. `mcp_component_view`/`mcp_component_grep` — explain how the responsible component works.
190
+ 11. If no local checkout exists for the responsible implementation account, use
191
+ `mcp_component_view`/`mcp_component_grep` to explain how the component works. If the repo exists on
192
+ this machine, inspect the branch/files there instead; the remote component tools are fallback and
193
+ live-DB comparison surfaces, not the starting point for source comprehension.
191
194
 
192
195
  **Slow / sluggish user report:**
193
196
 
@@ -11,10 +11,12 @@
11
11
  - [Support Ticket Mental Model](#support-ticket-mental-model)
12
12
  - [You are an agent, and you register yourself](#you-are-an-agent-and-you-register-yourself)
13
13
  - [Autonomous: one ticket, one process](#autonomous-one-ticket-one-process)
14
+ - [Serving only some workstreams](#serving-only-some-workstreams)
14
15
  - [The manual loop](#the-manual-loop)
15
16
  - [If you are the worker](#if-you-are-the-worker)
16
17
  - [Before you edit anything: where you are, and whether you may](#before-you-edit-anything-where-you-are-and-whether-you-may)
17
18
  - [Your account's process is binding, and it is already in your brief](#your-accounts-process-is-binding-and-it-is-already-in-your-brief)
19
+ - [Some of that process is enforced, not requested](#some-of-that-process-is-enforced-not-requested)
18
20
  - [Seeing the queue as a human does](#seeing-the-queue-as-a-human-does)
19
21
  - [Agent components are workers too](#agent-components-are-workers-too)
20
22
  - [Moving a ticket through its lifecycle](#moving-a-ticket-through-its-lifecycle)
@@ -80,10 +82,17 @@ and it expires on its own so a killed worker cannot park a ticket forever. You d
80
82
  remits-cli agent serve # workers are whichever agent THIS session is
81
83
  remits-cli agent serve --worker-agent codex --max-concurrent 2
82
84
  remits-cli agent serve --mode investigate # read-only workers: no file edits
85
+ remits-cli agent serve --serves support,sdlc # only these workstreams are routed here
83
86
  remits-cli agent workers # what is running right now
84
87
  remits-cli agent release # stop serving, go offline
85
88
  ```
86
89
 
90
+ `--mode investigate` is still autonomous ticket work. The supervisor claims a ticket, launches a
91
+ worker, and the worker should read/reproduce/localize the issue and update the ticket with useful
92
+ findings or a handoff. What it must **not** do is become the repository editor: investigation-mode
93
+ polls do not acquire or renew the repo edit lease, and the brief explicitly forbids file edits,
94
+ component staging, commits, and `remits-cli ticket lease`.
95
+
87
96
  **Run it in a plain terminal tab.** That tab becomes the agent host: `serve` returns immediately, a
88
97
  detached supervisor is anchored to the tab's shell, and closing the tab stops the agent. Nothing in
89
98
  that tab is an AI session — the AI only ever appears as the worker processes the supervisor spawns.
@@ -111,6 +120,33 @@ runs, reporting the worker's activity to the dashboard, dropping the claim when
111
120
  failed ticket once, and releasing a ticket back to the queue when it has failed too often. Closing
112
121
  the terminal stops everything and hands any in-flight work back.
113
122
 
123
+ ### Serving only some workstreams
124
+
125
+ `--serves` declares which of the account's **workstreams** this machine covers, so a fleet can be a
126
+ set of queues rather than a pool of interchangeable machines:
127
+
128
+ ```bash
129
+ remits-cli agent serve --serves support,incident --mode investigate # the support desk box
130
+ remits-cli agent serve --serves sdlc --max-concurrent 2 # the engineering box
131
+ ```
132
+
133
+ The names are the account's own — the platform compares them and learns nothing about any of them.
134
+ Read `remits-cli ticket queue --workstream ...` or the account's `OPERATIONS` prompts to find out
135
+ what this account calls its processes; do not invent names.
136
+
137
+ **Omit it unless the user asked for it.** A session that declares nothing is a generalist and takes
138
+ everything, which is the right default and what every existing fleet does. Specialising has a real
139
+ cost: a specialist is only routed tickets in its workstreams *and its unrouted sweep takes only
140
+ those*, so a workstream no live session covers is routed to nobody. The platform reports that rather
141
+ than quietly overriding the declaration —
142
+
143
+ - `dispatch` answers `reason: 'no_agent_serves_workstream'` and names what the live sessions do cover;
144
+ - `agent map` prints each session's declared queues;
145
+ - the supervisor logs `serve.out_of_scope` when it passes over unrouted work it does not serve.
146
+
147
+ **So after specialising a fleet, run `remits-cli agent map`** and confirm every workstream the
148
+ account ingests is covered by something.
149
+
114
150
  ### The manual loop
115
151
 
116
152
  Only when the session registered with `agent register` rather than `agent serve`.
@@ -137,6 +173,15 @@ timer.
137
173
  local directory through `~/.remits-cli/account-repos.json` and `cd` there before making changes. You
138
174
  registered from anywhere; you do not fix anything from anywhere.
139
175
 
176
+ For subscriber/fork tickets, this is also the investigation starting point. The reporting account may be
177
+ the fork or client that observed the issue, while `implementationAccountId` names the repo whose branch
178
+ contains the front-stage source. Read the ticket, run/inspect the run context (`ticket where` when useful),
179
+ open the indexed implementation repo, then establish the relevant branch's steady starting state before
180
+ the first edit: fetch origin, fast-forward the branch, and confirm local and remote have no commits missing
181
+ from either side. Then read `account-info.json` and the component files. Use `mcp_component_view` /
182
+ `mcp_component_grep` only when that repo is unavailable locally or when explicitly comparing live DB source
183
+ to the files.
184
+
140
185
  **Capacity is real, not advisory.** A serving session tells the platform how many workers it can run
141
186
  (`--max-concurrent`, default 1), and the router will not send it more than that. So a session at
142
187
  capacity is skipped in favour of one that is free, rather than accumulating tickets it will never
@@ -155,6 +200,14 @@ headless run is invisible otherwise), and **end in a terminal state** — `compl
155
200
  resolution, or `update_status` with what you established and what the next agent should try. Exiting
156
201
  quietly leaves a ticket that looks in-flight forever.
157
202
 
203
+ **If your brief says this is not the first autonomous run on this ticket, believe it.** Earlier runs
204
+ picked it up and handed it back unfinished; whatever they tried did not work, so repeating it will not
205
+ work either. Read what they recorded, then either take a genuinely different approach or **stop and
206
+ ask** (`remits-cli ticket ask`). Asking is a complete, successful outcome, and it is the right one when
207
+ the obstacle is not something a run can remove. Accounts cap how many times a ticket may be picked up
208
+ and handed back — past that the ticket stops being offered to workers at all and waits for a person, so
209
+ a run that exits quietly at the limit has cost every earlier run as well as its own.
210
+
158
211
  ### Before you edit anything: where you are, and whether you may
159
212
 
160
213
  Presence answers *who*. Two more facts answer *whether you may edit*, and with git worktrees and
@@ -185,12 +238,31 @@ Four things are worth knowing and are not obvious:
185
238
  - **A staging workspace does not replace the lease.** Separate lanes stop two runs *resolving* each
186
239
  other's staged code; they do nothing about two processes writing the same files or pushing the same
187
240
  branch, which is what actually destroys work.
188
- - **One editing worker per repository account per lane — worktrees do not change this.** Two worktrees
189
- of one repo push to the same branch on the same remote, so per-directory leases would trade file
190
- conflicts for non-fast-forward push conflicts, which surface later and are worse.
191
- - **A spawned ticket worker already has its own staging lane** (`REMITS_WORKSPACE=ticket-<id>`). You do
192
- not set it, and your brief states it. Say which lane you staged into when you report what you verified
193
- — somebody looking at the shared lane will not see your changes.
241
+ - **You are not restricted to trunk, and you do not choose the branch.** You work on whatever branch your
242
+ checkout is on — `ticket where` prints it — and nothing switches it underneath you. Separately, if this
243
+ account subscribes to a **component variant branch**, its variant components (including its
244
+ `OPERATIONS` process) resolve for you automatically, server-side, without you doing anything. Those are
245
+ two different facts and only the first is about your files. Load `branch-variants.md` before working in
246
+ a non-trunk checkout.
247
+ - **The edit lease excludes per repository account and lane, NOT per branch.** So an agent editing a
248
+ different branch of this same repository still blocks you, even though your files and your pushes would
249
+ not collide. That is deliberate over-exclusion, not a bug — investigate read-only and hand off, exactly
250
+ as for any other refusal.
251
+ - **A spawned local ticket worker owns its checkout grounding and already has its staging lane.** For
252
+ repository work, `remits-cli agent serve` appends the local repository checkout, target branch and a
253
+ suggested per-ticket worktree path. Before editing, create or choose an isolated worktree appropriate to
254
+ the ticket. For a ticket with no component branch subscription, the target branch is the repository
255
+ default before it is the launch checkout's current branch. The supervisor sets
256
+ `REMITS_WORKSPACE=ticket-<id>` for you; if you choose a detached worktree, export
257
+ `REMITS_GIT_BRANCH=<branch>` before running `remits-cli`. A worktree is a checkout-isolation tool, not
258
+ a freshness proof: fetch, fast-forward and prove `HEAD...origin/<branch>` is `0 0` before the first
259
+ edit, following `multi-agent-development.md`.
260
+ - **GCP Agent components do not get a local checkout.** The same ticket brief can name a component branch
261
+ subscription, but for a GCP Agent component that is component-resolution context, not a filesystem
262
+ instruction.
263
+ - **One editing worker per repository account per lane is still the server lease rule.** The worker-owned
264
+ worktree protects a human's checkout from the spawned worker; it does not make the edit lease
265
+ per-directory. A branch-aware edit lease with same-branch exclusion is a separate design.
194
266
 
195
267
  `unlease` returns **your own** lease and deliberately cannot touch anybody else's. Breaking a stale one
196
268
  is a separate, human verb: `remits-cli ticket force-unlease --ticket ID --reason "..."`.
@@ -213,6 +285,27 @@ from the prompt, so **edit the prompt, not the file**.
213
285
  `workstream` is not `type`: a type classifies the request, a workstream names the procedure, and they
214
286
  cross — a `defect` handled by incident response out of hours goes through the SDLC in the morning.
215
287
 
288
+ ### Some of that process is enforced, not requested
289
+
290
+ Part of an account's process can be **deterministic**. If your brief has a `## Rules you will be held to`
291
+ section, those rules are enforced by the platform at the write door — the verb is refused, not
292
+ discouraged.
293
+
294
+ - **Read that section before you act.** A refusal you were warned about costs one command; a refusal you
295
+ were not costs the run.
296
+ - **A refusal is an ANSWER.** The message names the rule and says what to do instead. Act on that
297
+ sentence. Do not retry the identical call, and do not go looking for another door — the rules govern the
298
+ DSL, the MCP tools and this CLI identically.
299
+ - **`[require]` rules mean a human.** You cannot acknowledge one: the platform decides "human" from the
300
+ absence of an agent run identity, which your commands always carry. Record what you found with
301
+ `ticket progress` and hand off.
302
+ - **`[warn]` rules let the call through and write a `policy` worklog entry.** Mention it in your handoff.
303
+ - **If you see "POLICY NOT ENFORCED"**, the account's rules could not be parsed. Do not read the absence
304
+ of a refusal as permission — say so on the ticket. It is a defect in the account's `OPERATIONS` prompt.
305
+
306
+ The same rules govern `components stage` and `components commit`. A `no-commit` rule is why
307
+ `remits-cli components commit` refuses rather than asks.
308
+
216
309
  ### Seeing the queue as a human does
217
310
 
218
311
  `remits-cli start` opens a browser control center showing the same facts you are acting on: which
@@ -385,5 +478,6 @@ Sandbox note:
385
478
  Use the same repo/context rules as other tools:
386
479
  - If the ticket targets a `CLIENT` account, do not assume that client's repo is the implementation repo. Confirm the parent `PLATFORM` / `PRODUCT` relationship first.
387
480
  - Read `~/.remits-cli/account-repos.json` before choosing which local repo to open.
388
- - If the correct repo for the relevant account type exists locally, switch there and inspect `account-info.json` and `/components`.
481
+ - If the correct repo for the relevant account type exists locally, switch there, confirm/pull the relevant
482
+ branch when clean, and inspect `account-info.json` and `/components`.
389
483
  - If the repo is not available locally, use `mcp_account_view`, `mcp_component_view`, and `mcp_component_grep`.
@@ -880,7 +880,7 @@ When a component "can't find" an obviously-present document, run `action:'inspec
880
880
  first — that shows what was indexed, which is usually the answer.
881
881
 
882
882
  ### `mcp_get_guide`
883
- Load the packaged front-stage guides — the same `docs/guides/` set `remits-cli` syncs into a repo. Use it when
883
+ Load the packaged front-stage guides — the same `docs/front-stage/` set `remits-cli` syncs into a repo. Use it when
884
884
  you are working **outside a repo** (or the repo's `guides/` is stale) and need the authoritative guidance
885
885
  before writing a component.
886
886
 
@@ -81,7 +81,7 @@ with `REMITS_PLATFORM_DIR`); `remits-cli` clones it on first authenticated run i
81
81
 
82
82
  Apply the boy-scout rule to the guides themselves: **whenever you only solved the problem by reading the
83
83
  core back stage because a front-stage guide was unclear or missing — even when there was no platform
84
- defect at all — open a guide-only PR** updating the relevant guide in the platform repo's `docs/guides/`,
84
+ defect at all — open a guide-only PR** updating the relevant guide in the platform repo's `docs/front-stage/`,
85
85
  which is the source served to every account repo. Better guides over time are an explicit goal.
86
86
 
87
87
  #### Escalation Bundle (tooling/operational issue)