@remits/remits-cli 0.1.124 → 0.1.126

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.124",
3
+ "version": "0.1.126",
4
4
  "description": "Local CLI for auth, component sync, and live test execution against Remits",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -12,6 +12,7 @@
12
12
  "files": [
13
13
  "index.js",
14
14
  "README.md",
15
+ "scripts/prepare-index-toc.js",
15
16
  "skills/remits-cli/SKILL.md",
16
17
  "skills/remits-cli/references"
17
18
  ],
@@ -29,8 +30,10 @@
29
30
  "automation"
30
31
  ],
31
32
  "scripts": {
33
+ "prepare:index-toc": "node scripts/prepare-index-toc.js",
34
+ "prepack": "node scripts/prepare-index-toc.js",
32
35
  "start": "node index.js",
33
- "test": "node --test test/*.test.js"
36
+ "test": "node scripts/prepare-index-toc.js --check && node --test test/*.test.js"
34
37
  },
35
38
  "dependencies": {
36
39
  "@stomp/stompjs": "^7.2.0",
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env node
2
+
3
+ const assert = require('node:assert/strict');
4
+ const fs = require('node:fs');
5
+ const path = require('node:path');
6
+ const vm = require('node:vm');
7
+
8
+ const indexPath = path.join(__dirname, '..', 'index.js');
9
+ const cliSource = fs.readFileSync(indexPath, 'utf8');
10
+
11
+ function functionSource(name) {
12
+ const declaration = new RegExp('(?:async\\s+)?function\\s+' + name + '\\s*\\([^)]*\\)\\s*\\{');
13
+ const match = declaration.exec(cliSource);
14
+ assert.notEqual(match, null, name + ' should exist');
15
+
16
+ const start = match.index;
17
+ let depth = 0;
18
+ for (let i = start + match[0].length - 1; i < cliSource.length; i += 1) {
19
+ if (cliSource[i] === '{') depth += 1;
20
+ if (cliSource[i] === '}') {
21
+ depth -= 1;
22
+ if (depth === 0) return cliSource.slice(start, i + 1);
23
+ }
24
+ }
25
+ assert.fail(name + ' body should be parseable');
26
+ }
27
+
28
+ const sandbox = vm.createContext({});
29
+ vm.runInContext(
30
+ ['headingSlug', 'formatTocEntry', 'resolveTocEntry', 'resolveTableOfContentsLineNumbers']
31
+ .map(functionSource)
32
+ .join('\n'),
33
+ sandbox
34
+ );
35
+
36
+ const resolveTableOfContentsLineNumbers = vm.runInContext('resolveTableOfContentsLineNumbers', sandbox);
37
+ const prepared = resolveTableOfContentsLineNumbers(cliSource);
38
+ const check = process.argv.includes('--check');
39
+
40
+ if (check) {
41
+ if (prepared !== cliSource) {
42
+ console.error('cli/index.js Table of Contents is stale. Run: npm run prepare:index-toc');
43
+ process.exit(1);
44
+ }
45
+ process.exit(0);
46
+ }
47
+
48
+ if (prepared !== cliSource) {
49
+ fs.writeFileSync(indexPath, prepared);
50
+ console.log('Updated cli/index.js Table of Contents line numbers.');
51
+ }
@@ -74,7 +74,14 @@ reference named after it.
74
74
  (`development-loop.md`)
75
75
  - **Give each agent its own lane: `remits-cli workspace use --auto`.** Without a workspace you are in
76
76
  the SHARED lane, where a full stage replaces what another agent is testing rather than merging with
77
- it. (`component-resolution.md`)
77
+ it. Each agent works in its own **clone**, never a same-branch worktree: worktrees share the branch
78
+ ref, so one agent's pull moves `HEAD` under the others, and `components commit` refuses there.
79
+ (`component-resolution.md`)
80
+ - **Land only from trunk or a real variant branch.** A per-agent/feature branch (`components status` says
81
+ `FEATURE BRANCH … [subscription-fallback]`) is safe to stage and run from — it resolves the same world
82
+ as its target — but `components commit`/`sync` refuse it. Merge into the branch it resolves and land
83
+ there; `--create-variant-branch` is only for deliberately creating a new variant branch.
84
+ (`branch-variants.md`)
78
85
  - **On a variant branch, sync with `remits-cli components sync --safe`.** It dry-runs first and refuses
79
86
  a plan that would write components this checkout did not change — which is what a branch that is
80
87
  behind trunk produces, because it still physically carries old copies of files nobody touched.
@@ -82,8 +89,12 @@ reference named after it.
82
89
  - **`stage` is always safe. `components commit` on trunk is the most dangerous command in the CLI.**
83
90
  It is not a convenience wrapper: it `git add -A`, commits, pushes, and then reconciles the whole
84
91
  pushed repo into the live component database — creating, updating, renaming, and **hard-deleting**
85
- rows. Prefer the observable `git commit → git push → components sync → git pull`.
86
- (`component-integrity.md`)
92
+ rows. Prefer the observable `git commit → git push → components sync → git pull`. On trunk it refuses
93
+ before any git write unless you pass `--yes`. (`component-integrity.md`)
94
+ - **After anyone lands, ask whether your lane is stale: `remits-cli components status`.** A landing clears
95
+ only the lander's lane; yours keeps shadowing their new rows with content staged from the old base.
96
+ `LANDED SINCE YOUR BASE` / `STALE OVERLAY` mean pull, re-stage, then verify — a pass against a stale
97
+ lane proves nothing. (`component-resolution.md`)
87
98
  - **A component filename's numeric id prefix is load-bearing.** Renumber it and the next trunk sync
88
99
  creates a duplicate at the new id and hard-deletes the original. A live component whose files are
89
100
  missing from the repo at trunk-sync time is hard-deleted. Never renumber, rename across ids, or
@@ -44,13 +44,21 @@ Three facts that everything else follows from:
44
44
 
45
45
  ### Which world does your working tree resolve? (read this before you run anything)
46
46
 
47
- You will work from **two different checkouts of the same repo**, and they behave differently on both ends
48
- of the loop. The rule turns entirely on **trunk vs non-trunk**:
47
+ You will work from **different checkouts of the same repo**, and they behave differently on both ends of
48
+ the loop. **You only ever stage the edits you intend to test** — the world beneath them comes from the
49
+ account, not from what you named your git branch:
49
50
 
50
51
  | Working tree | Staging scope | A run resolves | `components sync`/`commit` writes |
51
52
  |---|---|---|---|
52
53
  | **trunk** (`main`, or whatever `account-info.json` says) | that branch | trunk + **each account's subscribed** variant branch (production semantics) | the **live component rows** — full reconcile, creates/updates/**deletes** |
53
- | **any other branch** (`feature_branch`) | that branch | trunk + **`feature_branch`** overlays | **`ComponentVariant` overlays on that branch only** — never touches trunk rows |
54
+ | **a variant branch** (it has committed variants, or an account subscribes to it — e.g. `forked`) | that branch | trunk + **that branch's** overlays | **`ComponentVariant` overlays on that branch only** — never touches trunk rows |
55
+ | **any other branch** (`codex/x`, `feature/y`) | that branch | the **same world as trunk**: trunk + the account's subscribed branch (`forked` for its subscriber) | **refused** (`feature_branch_landing`) — merge into the branch it resolves and land from there |
56
+
57
+ A branch like that is a **feature branch**, and it is safe to *run* from: stage only the components you edited,
58
+ and runs still resolve every `forked` overlay for the subscriber. Do **not** stage untouched components to
59
+ "restore" something reported missing — check `components status` first. It is never a place to *land* from.
60
+ For parallel agents the preferred shape is still the real branch name plus a workspace; see
61
+ `features/multi-agent-development.md` ("Per-agent git branches: safe to run, never to land").
54
62
 
55
63
  Do not infer this from the branch name. Ask:
56
64
 
@@ -61,12 +69,17 @@ remits-cli components status
61
69
  ```
62
70
  Working tree: VARIANT BRANCH "feature_branch" (trunk is "main")
63
71
  runs resolve: trunk + the 'feature_branch' variant overlays
72
+ variant world: feature_branch [branch-has-variants]
64
73
  commit writes: ComponentVariant overlays on 'feature_branch' (never touches trunk rows)
65
74
  variants stored on this branch: 3
66
75
  subscribing accounts: 101 (Acme Child)
67
76
  ```
68
77
 
69
- **The precedence trap that costs the most time:** `variantBranch` **outranks every account's
78
+ From a branch that is not a variant branch the header reads `FEATURE BRANCH` and `runs resolve` names the
79
+ subscribed branch, tagged `[subscription-fallback]`. `test run`, `token` and `tool` responses carry the
80
+ same `variantBranch` / `variantBranchSource` fields, and a verification envelope records that world.
81
+
82
+ **The precedence trap that costs the most time:** a variant branch's world **outranks every account's
70
83
  subscription**. So running a Test suite that asserts *production* semantics from a **variant checkout**
71
84
  pins every account in that suite — including fixture accounts subscribed to their own generated branches —
72
85
  to your branch, where they have no variants, and they all read trunk. The suite fails in a way that looks
@@ -274,7 +287,8 @@ remits-cli components branch <name> --retire [--force]
274
287
  ```
275
288
 
276
289
  Branch administration commands act **as the account you are running from**, which is treated as the branch
277
- **owner** — run them from the owner's trunk checkout. Authorization is downward-only.
290
+ **owner** — run them from the owner's trunk checkout. Authorization is downward-only. (`--retire` checks
291
+ this and refuses from a non-owner; the read commands below resolve the owner for you.)
278
292
 
279
293
  - **`--subscribe` sets the branch on an edge that must already exist — it cannot create one.** Failure
280
294
  reads *"Account N has no relationship edge to subscribe; add a membership edge first"*. Create it with
@@ -295,7 +309,22 @@ Branch administration commands act **as the account you are running from**, whic
295
309
  subscriptions.
296
310
  - **Retiring is explicit.** Deleting the *git* branch does **not** remove its overlays; subscribers would
297
311
  keep resolving a branch that no longer exists. `--retire` refuses while subscribers remain unless you
298
- pass `--force`.
312
+ pass `--force`, and it refuses (naming the owner) when run from any account other than the branch owner.
313
+ - **Reads work from any checkout.** `components branch <name>` (status, `--diff`, `--subscribers`) and
314
+ `components promotion` resolve the branch owner the account actually resolves the branch from —
315
+ including an inherited subscription held by an ancestor — and report it as `branchOwnerAccountId`.
316
+ `components branches` lists branches this account OWNS; from a subscriber it also names the branch it
317
+ resolves and from whom. If `components status` prints `INHERITED BRANCH`, this account gets the branch
318
+ through an ancestor's subscription: a sync from here varies THIS account's own components (for it and the
319
+ accounts beneath it). To change the owner's components, work in the owner's repository on that branch.
320
+ - **A commit must push to the repository the platform syncs.** `components status` names it (`sync reads
321
+ repository`). `components commit` refuses before any git write, and `components sync --safe` refuses,
322
+ when this checkout's `origin` is a different repository; a plain sync warns.
323
+ - **Every prompt varies on a branch, including the README and agent prompts.** Edit the repo-root
324
+ `README.md`, an agent's `.md` in `components/agents/`, or a prompt in `components/prompts/` exactly as
325
+ you would any other component file: stage, verify, sync, and subscribers resolve it; merging to trunk
326
+ lands it. The README becomes an overlay of the account's README prompt (a branch without `README.md`
327
+ reverts to trunk's); an agent's prompt travels inside that agent's overlay.
299
328
 
300
329
  **Every component kind can be varied** — `schema`, `reader`, `action`, `embeddable`, `i18n`, `htmltemplate`,
301
330
  `rule`, `test`, `utility` (agent), `tool`, `prompt` — including tombstones and branch-only additions. A
@@ -367,7 +396,9 @@ branch that overlays it.
367
396
 
368
397
  **`components branches` only lists branches that already have overlays.** A branch you just pushed is
369
398
  invisible here until its first sync — that is not an error. Preview it by name (`components sync --dry-run`
370
- from that checkout).
399
+ from that checkout). Its first real sync (or commit) needs `--create-variant-branch`: until a branch has
400
+ variants or a subscriber the platform treats it as a feature branch and refuses to land it, so creating a
401
+ new variant branch is always a stated decision, never a side effect of a feature branch's name.
371
402
 
372
403
  **Trunk moving also invalidates a branch.** Variant sparseness compares branch content against *current*
373
404
  trunk, so a trunk change can make an overlay obsolete without the branch changing at all. A trunk sync
@@ -193,20 +193,20 @@ remits-cli listen [stop|status] [--foreground true] # compatibility alias
193
193
  remits-cli data-mode [set test|prod]
194
194
  remits-cli components stage [--workset | --changed-only] [--branch <name>] [--workspace <name>] [--empty-workset clear] [--data-mode test|prod] [--json|--verbose] # default = FULL SNAPSHOT of the repo; --workset = only what git says changed, lane reconciled to it
195
195
  remits-cli workspace [show | use <name> | use --auto | clear]
196
- remits-cli components status [--branch <name>] [--component-type <type>] [--component-id <id>] [--json|--verbose]
196
+ remits-cli components status [--branch <name>] [--component-type <type>] [--component-id <id>] [--json|--verbose] # also: has anyone landed since this lane was staged (freshness)
197
197
  remits-cli components lanes [--json] # every indexed staging lane on the account
198
198
  remits-cli components entries --lane-id <id> [--json|--verbose] # authoritative staged files for one lane
199
199
  remits-cli components clear [--branch <name>] [--component-type <type>] [--component-id <id>] [--all] [--json|--verbose] # id alone scopes to one component when unambiguous (ids are type-local; add --component-type if the same id is staged in multiple families); no filter clears the whole branch scope; --all forces the full wipe
200
- remits-cli components sync [--safe [--yes]] [--branch <name>] [--data-mode test|prod] [--force-tombstones] [--dry-run] [--summary] [--changed-only [--changed-since <ref>]] # gated; on trunk = full repo->DB reconcile, on a variant branch = ComponentVariant overlays only
201
- remits-cli components commit [--safe] [--message "msg"] [--data-mode test|prod] [--force-tombstones] # phase 1 merge-stages + compile-validates changed source (never reconciles the lane); --safe gates sync writes
200
+ remits-cli components sync [--safe [--yes]] [--branch <name>] [--data-mode test|prod] [--force-tombstones] [--dry-run] [--create-variant-branch] [--summary] [--changed-only [--changed-since <ref>]] # gated; on trunk = full repo->DB reconcile, on a variant branch = ComponentVariant overlays only
201
+ remits-cli components commit [--yes] [--safe] [--allow-shared-branch] [--create-variant-branch] [--message|-m "msg"] [--data-mode test|prod] [--force-tombstones] [--json [--summary]] # phase 1 merge-stages + compile-validates changed source (never reconciles the lane); on TRUNK refuses before any git write unless --yes; --safe gates variant sync writes
202
202
  remits-cli components branches [--json] # branches carrying committed variants, with counts + drift
203
- remits-cli components branch <name> [--json] # one branch: overridden / added / removed, drift flags, subscribers
203
+ remits-cli components branch <name> [--json] # one branch: owner account, overridden / added / removed, drift flags, subscribers
204
204
  remits-cli components branch <name> --diff <componentId> --component-type <kind> [--json]
205
205
  remits-cli components branch <name> --subscribers [--json]
206
206
  remits-cli components branch <name> --subscribe <accountId> [--parent-account <id>] [--domain <host>] [--dry-run] [--confirm-primary-edge] # make an account resolve this branch
207
207
  remits-cli components branch <name> --unsubscribe <accountId> # return that account to trunk
208
208
  remits-cli components branch <name> --retire [--force] # delete the branch's overlays
209
- remits-cli test run --test <id|name> [--branch <stagingScope>] [--names "a|b"] [--watch true|false] [--data-mode test|prod] [--as-account <ID>] [--variant-branch <name|none>]
209
+ remits-cli test run --test <id|name> [--branch <stagingScope>] [--names "a|b"] [--watch true|false] [--data-mode test|prod] [--as-account <ID>] [--variant-branch <name|none>] [--json]
210
210
  remits-cli token [--path <embeddablePathOrId>] [--data-mode test|prod] [--as-account <ID>] [--variant-branch <name|none>]
211
211
  remits-cli token inspect --token <token|tokenKey|URL> # inspect token metadata, safety/dataMode evidence, and full context
212
212
  remits-cli tools [--branch <name>] [--data-mode test|prod] [--variant-branch <name|none>]
@@ -316,16 +316,45 @@ For tests specifically:
316
316
  `--variant-branch none` when an existing staged cache on the real git branch would shadow committed trunk
317
317
  or variant rows. On `components sync` / `commit`, `--branch` is different: it names the GitHub branch to
318
318
  reconcile.
319
+ - `--json` on `test run` prints exactly one JSON document to stdout: the final status/result. Safety
320
+ banners, start/progress lines, and websocket case progress go to stderr so shell callers can parse
321
+ stdout directly. The exit code is non-zero when the run fails, does not complete, or a requested case
322
+ selector matches nothing.
319
323
  - `--force-tombstones` is only for non-trunk variant syncs, when missing trunk component files are known,
320
324
  intentional tombstone overrides. It is rejected on trunk.
321
325
  - `--dry-run` is only for `components sync` on non-trunk variant branches. It reports the variant write
322
326
  plan without writing rows, caching the sync SHA, or clearing staging.
323
- - `--summary` on `components sync --dry-run` prints compact counts, removals/tombstones, skipped items, errors,
324
- and warnings instead of the full override/add/remove payload.
327
+ - `--summary` on `components sync` prints compact counts plus named updated (with the fields that
328
+ changed), renamed, skipped, removal/tombstone, error, and gate details instead of the full payload. A
329
+ trunk sync reports an untouched component under `unchanged`, not `updated`.
330
+ - `--json` on `components stage`, `components sync`, `components commit`, and `tool` prints one
331
+ parseable JSON document to stdout. Safety banners and prose go to stderr, and sync safety-gate failures
332
+ are reported inside `gateViolations` with a non-zero exit code instead of appending prose after the JSON.
333
+ - `components commit --json` prints the COMMIT outcome, not the sync's: `phase` (`stage` → `git` → `sync`
334
+ → `pull` → `complete`), `gitCommitted`, `pushed`, `pushedSha`, `synced`, `postSyncSha`, `pulled`, the
335
+ nested `sync` (summary with `--summary`), and on failure `error` + `nextStep`. It stops at the first
336
+ failed phase. `phase: "sync"` with `pushed: true` means the remote holds work the platform has not
337
+ reconciled — follow `nextStep`; do not re-run `components commit`.
338
+ - `components commit` on trunk refuses before staging, committing, or pushing unless `--yes` is present —
339
+ with or without `--safe`. Trunk has no dry-run plan, so nothing can preview the full repo-to-DB reconcile.
340
+ - `components commit` refuses before any git write while its branch is checked out in another worktree
341
+ (`sharedBranchWorktrees` in `--json`). Worktrees of one branch share its ref, so a stale one would commit
342
+ over landed work. Use one clone per agent; `--allow-shared-branch` overrides after `git status` is clean
343
+ apart from your own changes.
344
+ - `components commit` refuses before any git write, and `components sync` refuses, on a **feature branch** — one
345
+ `components status` reports as `[subscription-fallback]` (no committed variants, no subscribers). Runs from
346
+ it resolve the subscribed branch; landing it would write overlays nobody subscribes to and flip every sibling
347
+ lane on that branch to them (`refusal: "feature_branch_landing"` in `--json`). Merge it into the branch it
348
+ resolves and land from there. `--create-variant-branch` overrides, for deliberately creating a NEW variant
349
+ branch (its first sync looks identical). `--dry-run` previews are never refused.
350
+ - `components commit` refuses before any git write, and `components sync --safe` refuses, when this checkout's
351
+ `origin` is not the repository the platform syncs for the resolved account (`branchContext.repository` in
352
+ `components status`). A plain sync warns and reports `repositoryCheck`, including under `--summary`.
325
353
  - **Fail-closed sync gates.** On non-trunk variant branches these flags now force a server dry-run first,
326
354
  evaluate that plan before any overlay row is written, and only then run the mutating sync when the plan
327
355
  passes. On trunk, there is no safe dry-run plan, so do not treat these as scoped commit controls:
328
- - `--changed-only` — fail unless every planned write is a component **this checkout actually changed**.
356
+ - `--changed-only` — fail unless every planned write is a component **this checkout actually changed**
357
+ (matched by type + id, type + name, or the repo file it came from — so a root `README.md` edit counts).
329
358
  This is the strongest guard against a sync that quietly rewrites components you never touched. It
330
359
  also fails when the checkout is not a git working tree, because "git could not answer" must never
331
360
  be read as "nothing changed".
@@ -388,6 +417,11 @@ REPRESENTABLE. On a non-trunk variant branch, prove a deletion through
388
417
  `components sync --dry-run --summary --fail-on-errors`; on trunk there is no dry-run plan, so use the
389
418
  full pre-sync safety check before any mutating reconcile.
390
419
 
420
+ The repo-root `README.md` is staged as the account's README-purpose Prompt. It is part of the git workset
421
+ for `components stage --workset`, even though it does not live under `components/`. It behaves like any
422
+ other component on trunk AND on a variant branch: a variant sync stores a README change as an overlay of
423
+ the README prompt, and an agent's `.md` in `components/agents/` travels with that agent's overlay.
424
+
391
425
  ### Prod banners and retryable failures
392
426
 
393
427
  - Every command that can touch production (`tool`, `test run`, `components sync`) prints a `PROD DATA`
@@ -115,6 +115,18 @@ Key implications:
115
115
  immediately syncs. Never run it while the tree contains drift or unexplained changes. Prefer the explicit,
116
116
  observable `components stage → git commit → git push → components sync → git pull` sequence so each
117
117
  phase can be inspected.
118
+ - **`components commit` on trunk refuses before any git write unless `--yes` is present** — with or
119
+ without `--safe`, and with `--skip-git`. Trunk has no dry-run sync plan, so an explicit acknowledgement
120
+ is the only honest gate; the CLI must not create or push a commit and only then discover it.
121
+ - **A commit that fails after the push says so.** `phase`, `pushed`, `pushedSha` and `nextStep` (in
122
+ `--json`, one document on stdout) tell you whether the remote now holds work the platform has not
123
+ reconciled. If it does, fix the cause and run `components sync` — do not re-run `components commit`.
124
+ - **A commit refuses when the push and the sync would hit different repositories** — this checkout's
125
+ `origin` versus the repository the platform syncs for the account the command resolved. Fix the account
126
+ (account-info.json, `--account-id`) or run from the right checkout; never force it.
127
+ - **A commit refuses while its branch is checked out in another worktree.** Worktrees of one branch share
128
+ its ref: a pull in one moves `HEAD` under the others, and `git add -A` from a stale one reverts work that
129
+ has already landed. Give each agent its own clone.
118
130
  - **`components sync` acts on the pushed remote**, so local edits are invisible to it until committed **and
119
131
  pushed**, and a drifted **remote** is dangerous even when your local tree looks fine.
120
132
  - **Runtime-compiled component source is validated before durable writes.** When a trunk sync or variant
@@ -165,14 +177,14 @@ file is catastrophic.
165
177
  push generated artifacts back to the branch.
166
178
  - Local filenames and live inventory (`mcp_account_view`) **agree on id and name for every component**: no live
167
179
  component appears locally under a different id, and no expected component is missing a repo file.
168
- > **Do not run this comparison against `account-info.json` alone — it will report false orphans.** That
180
+ > **Do not run this comparison against `account-info.json` alone — it can still be incomplete.** That
169
181
  > file omits `auxiliary: true` components by design, so every auxiliary component looks like a repo file
170
182
  > with no DB row, i.e. exactly the "a trunk sync will CREATE a duplicate" signal this check exists to
171
- > catch. It also omits README- and AGENT-purpose Prompts, which live at the repo root and as `.md`
172
- > sidecars in `components/agents/` rather than in `components/prompts/`, so they look like DB rows with
173
- > no repo file — the "will be DELETED" signal. Both are benign. Before treating a flagged component as
174
- > drift, confirm against the live row: `mcp_component_view`, or
175
- > `mcp_run_action controlAction:"describe"` for an Action. A component that answers is not an orphan.
183
+ > catch. README- and AGENT-purpose Prompts are also intentionally absent from the `Prompts` collection:
184
+ > they live at repo-root `README.md` and as `.md` sidecars in `components/agents/`, not in
185
+ > `components/prompts/`. Before treating a flagged component as drift, confirm against the live row:
186
+ > `mcp_component_view`, or `mcp_run_action controlAction:"describe"` for an Action. A component that
187
+ > answers is not an orphan.
176
188
  - You can state the expected create/update/delete set. **If any delete or renumber is unexpected, stop.**
177
189
 
178
190
  ### If something looks wrong — stop, don't paper over
@@ -174,22 +174,21 @@ overwrite each other, and a `components commit` clears the lane out from under t
174
174
  If more than one agent is working on the same branch, give each its own workspace:
175
175
 
176
176
  ```bash
177
- git fetch origin
177
+ git clone <repository-url> repo-agent-a # one CLONE per agent, same branch
178
+ cd repo-agent-a
178
179
  git switch forked
179
- git pull --ff-only origin forked
180
180
  git rev-list --left-right --count HEAD...origin/forked # must print: 0 0
181
- git worktree add --force ../repo-agent-a forked # one checkout per agent, same branch
182
- cd ../repo-agent-a
183
181
  remits-cli workspace use --auto # names the lane after this directory
184
182
  remits-cli components stage # isolated: nobody else sees it, nobody overwrites it
185
183
  remits-cli test run --test 42
186
184
  remits-cli token --path /page/whatever
187
185
  ```
188
186
 
189
- That first block matters. `git worktree add ... forked` uses the local `forked` ref; it does not fetch or
190
- prove that `forked` equals `origin/forked`. If the local ref is stale, every isolated staging lane starts
191
- from the same stale files and a later sync looks like a deliberate revert. Before the first edit in a new
192
- or reused worktree, `git status --porcelain`, `git log origin/<branch>..<branch>`, and
187
+ **A clone, not `git worktree add --force`.** Worktrees of one branch share its ref: a pull or commit in one
188
+ moves `HEAD` under the others, and a `components commit` from a stale one reverts work that already landed.
189
+ `components commit` refuses while its branch is checked out in another worktree (`--allow-shared-branch`
190
+ overrides, only once `git status` shows nothing but your own changes). A stale clone is still stale: before
191
+ the first edit in a new or reused clone, `git status --porcelain`, `git log origin/<branch>..<branch>`, and
193
192
  `git log <branch>..origin/<branch>` should all be empty. For variant branches, run
194
193
  `remits-cli components promotion --branch <branch>` too; a branch can be current with its own remote and
195
194
  still stale relative to trunk.
@@ -199,7 +198,7 @@ account, and the run still resolves whatever committed variant branch the accoun
199
198
  does **not** have the side effects of inventing a throwaway git branch per agent (which would make a
200
199
  commit write `ComponentVariant` overlays for a branch nobody subscribes to).
201
200
 
202
- - `.remits-cli/workspace` is per-checkout and gitignored, so each worktree keeps its own lane.
201
+ - `.remits-cli/workspace` is per-checkout and gitignored, so each clone keeps its own lane.
203
202
  - Precedence: `--workspace NAME` > `REMITS_WORKSPACE` > `.remits-cli/workspace` > shared default lane.
204
203
  - `--no-workspace` targets the shared lane for one command without clearing the file.
205
204
  - Every stage / test run / token / clear prints its `Staging lane:` — if a change seems to have had no
@@ -211,6 +210,18 @@ commit write `ComponentVariant` overlays for a branch nobody subscribes to).
211
210
  - `remits-cli components lanes` is the review view across users/branches/workspaces, and
212
211
  `remits-cli components entries --lane-id <id>` is the drill-down into actual staged files.
213
212
  - `remits-cli components clear --all` is scoped to YOUR lane and never touches another agent's.
213
+ - In lane rows, `currentLane` (also `mine`) marks THIS command's lane; `ownedByCaller` marks every lane
214
+ staged by your CLI user — your other clones' agents included.
215
+ - **A landing clears only the lander's lane.** Every stage records the commit it came from
216
+ (`stageBaseSha`), and `components status` compares that with the last commit the platform synced for the
217
+ branch (`branchContext.lastSyncedSha`) using your local git:
218
+ - `LANDED SINCE YOUR BASE` — the platform synced a commit this checkout does not contain. Somebody landed
219
+ after you pulled: `git fetch origin && git pull --ff-only`, then re-stage.
220
+ - `STALE OVERLAY` — entries staged from a commit older than the last sync. They shadow rows that landed
221
+ after they were staged; re-stage with `--workset` or clear them.
222
+ - `--json` carries the same answer as `freshness` (`landedSinceHead`, `entriesBehindLastSync`, `stale`).
223
+ `null` means unknown — a lane staged by an older CLI, or a branch whose last sync is not recorded —
224
+ never "fresh".
214
225
 
215
226
  ### A lane holds an OVERLAY; your workset is a different number
216
227
 
@@ -354,7 +354,7 @@ Inspect individual lifecycle records with line-range or grep.
354
354
  | `recordType` | yes | `object`, `object_log`, `event`, or `alert` |
355
355
  | `recordId` | yes | Record primary key |
356
356
  | `field` | no | `content` (default) or `body` (objects only) |
357
- | `revisionId` | no | Envers revision ID (not for object_log) |
357
+ | `revisionId` | no | Envers revision ID (not for object_log). Revision history does not retain `content`/`body`; omit it to read the current payload |
358
358
  | `lineRange` | no | `{start, end}` (1-based inclusive) |
359
359
  | `grep` | no | `{pattern, caseSensitive, contextBefore, contextAfter}` |
360
360
 
@@ -39,7 +39,8 @@
39
39
  | A custom hostname resolves to an unexpected account | Compare `resolution.domainName` with `resolvedDomainName` and the edge `domainName`s. An **edge** host wins over the account's own host and additionally supplies the path travelled (which is what makes that edge's branch variants apply). |
40
40
  | Need users of an account, accounts of a user, or account-scoped user fields | Use `mcp_account_user_admin` (`action:'users'`, `action:'user'`, or `action:'user_update'`). Use `mcp_sql_query` on `user` / `user_account` only for raw join-table investigation. Remember user custom fields are stored **per bound account**, so the same person can differ per account. |
41
41
  | One account behaves differently from its siblings on the same component | It probably subscribes to a **branch variant**. Check `remits-cli components branches` and `remits-cli components branch <name> --subscribers`, and reproduce with `remits-cli test run --as-account <ID>`. Do NOT "fix" this by adding per-account logic to the origin component. |
42
- | Edits on a feature branch seem to run against trunk code | You are likely on the **trunk** branch, or passed `--variant-branch none`. Run `remits-cli components status` — it states which world the working tree resolves. |
42
+ | Edits on a feature branch seem to run against trunk code | A branch with no committed variants and no subscribers resolves the account's **subscription** (trunk, if it subscribes to nothing) beneath what you staged — `components status` shows `FEATURE BRANCH … [subscription-fallback]` and names the world. To see a specific branch's overlays, run from that branch's checkout or pass `--variant-branch <name>`. |
43
+ | `components commit`/`sync` refused with `feature_branch_landing` | The branch is a feature branch, not a variant branch. Merge it into the branch the message names and land from that checkout. Do **not** pass `--create-variant-branch` to get past it — that flag deliberately creates a new variant branch nobody subscribes to. |
43
44
  | A component vanished for one account after a variant-branch sync | Its file is missing from that branch, so the sync created a **tombstone** that hides it from subscribers. Restore the file on the branch and re-sync. Trunk is unaffected. |
44
45
  | A variant Test suite fails wholesale, asserting trunk where you expect a variant | You are almost certainly running it from a **variant checkout**: `variantBranch` outranks every subscription, so the suite's own fixture accounts resolve YOUR branch. Re-run from trunk or with `--variant-branch none` before treating it as a regression. |
45
46
  | `components sync` on a branch says "No changes detected" but trunk has moved | Re-run it; a trunk sync now invalidates the branch's cached verdict. If it still skips, the branch genuinely matches trunk - check `components branch <name>` for what is actually stored. |