@remits/remits-cli 0.1.125 → 0.1.127

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.125",
3
+ "version": "0.1.127",
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
+ }
@@ -77,6 +77,11 @@ reference named after it.
77
77
  it. Each agent works in its own **clone**, never a same-branch worktree: worktrees share the branch
78
78
  ref, so one agent's pull moves `HEAD` under the others, and `components commit` refuses there.
79
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`)
80
85
  - **On a variant branch, sync with `remits-cli components sync --safe`.** It dry-runs first and refuses
81
86
  a plan that would write components this checkout did not change — which is what a branch that is
82
87
  behind trunk produces, because it still physically carries old copies of files nobody touched.
@@ -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
@@ -383,7 +396,9 @@ branch that overlays it.
383
396
 
384
397
  **`components branches` only lists branches that already have overlays.** A branch you just pushed is
385
398
  invisible here until its first sync — that is not an error. Preview it by name (`components sync --dry-run`
386
- 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.
387
402
 
388
403
  **Trunk moving also invalidates a branch.** Variant sparseness compares branch content against *current*
389
404
  trunk, so a trunk change can make an overlay obsolete without the branch changing at all. A trunk sync
@@ -197,8 +197,8 @@ remits-cli components status [--branch <name>] [--component-type <type>] [--comp
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 [--yes] [--safe] [--allow-shared-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
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
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]
@@ -207,6 +207,7 @@ remits-cli components branch <name> --subscribe <accountId> [--parent-account <i
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
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
+ remits-cli test status --task-id <taskId> [--branch <stagingScope>] [--data-mode test|prod] [--json]
210
211
  remits-cli token [--path <embeddablePathOrId>] [--data-mode test|prod] [--as-account <ID>] [--variant-branch <name|none>]
211
212
  remits-cli token inspect --token <token|tokenKey|URL> # inspect token metadata, safety/dataMode evidence, and full context
212
213
  remits-cli tools [--branch <name>] [--data-mode test|prod] [--variant-branch <name|none>]
@@ -268,6 +269,23 @@ remits-cli verify report
268
269
  Existing commands also accept `--verify-envelope <id>` to attach to a specific envelope and
269
270
  `--no-verify-envelope` to suppress automatic attachment for one command.
270
271
 
272
+ Failed `remits-cli test run` output includes compact pivots per failed case: duration, trace id,
273
+ bounded `report(...)` diagnostics, live HTTP signals, and resolved component provenance when the
274
+ platform returns it. Re-read an existing run with `remits-cli test status --task-id <taskId>` before
275
+ rerunning a long suite.
276
+
277
+ Test-run requirements must name the suite/cases they mean:
278
+
279
+ ```json
280
+ {"id":"api_flow", "packetType":"test_run", "suite":"Statement API Flow", "allCases":true}
281
+ {"id":"one_case", "packetType":"test_run", "suite":"Statement API Flow", "cases":["rejects duplicated fee evidence"]}
282
+ ```
283
+
284
+ `verify start` and `verify manifest` warn when a requirement has a `packetType` but no discriminator.
285
+ The evaluator treats pending async tool packets as pending, not passing; a later `tool status` packet is
286
+ the proof. Tool packets store the response file path, byte size and hash rather than copying the whole
287
+ tool payload into the envelope.
288
+
271
289
  Use `remits-cli verify list` to review open envelopes for the account without SQL. If a newer envelope
272
290
  replaces an older one, use `verify supersede`; if a duplicate or abandoned attempt should no longer read
273
291
  as live work, use `verify abandon`. Both keep the evidence history.
@@ -341,6 +359,12 @@ For tests specifically:
341
359
  (`sharedBranchWorktrees` in `--json`). Worktrees of one branch share its ref, so a stale one would commit
342
360
  over landed work. Use one clone per agent; `--allow-shared-branch` overrides after `git status` is clean
343
361
  apart from your own changes.
362
+ - `components commit` refuses before any git write, and `components sync` refuses, on a **feature branch** — one
363
+ `components status` reports as `[subscription-fallback]` (no committed variants, no subscribers). Runs from
364
+ it resolve the subscribed branch; landing it would write overlays nobody subscribes to and flip every sibling
365
+ lane on that branch to them (`refusal: "feature_branch_landing"` in `--json`). Merge it into the branch it
366
+ resolves and land from there. `--create-variant-branch` overrides, for deliberately creating a NEW variant
367
+ branch (its first sync looks identical). `--dry-run` previews are never refused.
344
368
  - `components commit` refuses before any git write, and `components sync --safe` refuses, when this checkout's
345
369
  `origin` is not the repository the platform syncs for the resolved account (`branchContext.repository` in
346
370
  `components status`). A plain sync warns and reports `repositoryCheck`, including under `--summary`.
@@ -57,9 +57,10 @@ source-layer facts the command observed. A staged test packet is proof of the st
57
57
  is proof of a source transition; a token packet is proof of the browser token's resolution tuple. Those
58
58
  are not interchangeable.
59
59
 
60
- Use `remits-cli verify report` before summarizing the work. It will naturally say when the evidence only
61
- covered staged source, when committed variant/trunk proof is missing, or when evidence became stale after
62
- the git head, overlay, or platform sync moved.
60
+ Use `remits-cli verify report` before summarizing the work. It will say when the evidence only covered
61
+ staged source, when committed variant/trunk proof is missing, when the manifest world does not match the
62
+ packet world, or when later packet facts made an earlier proof stale. Packets carry a lane content hash,
63
+ git head, workspace, data lane, and variant-world facts so a re-stage or branch move is visible.
63
64
 
64
65
  ### Staging cache key format
65
66
 
@@ -212,6 +213,9 @@ commit write `ComponentVariant` overlays for a branch nobody subscribes to).
212
213
  - `remits-cli components clear --all` is scoped to YOUR lane and never touches another agent's.
213
214
  - In lane rows, `currentLane` (also `mine`) marks THIS command's lane; `ownedByCaller` marks every lane
214
215
  staged by your CLI user — your other clones' agents included.
216
+ - If your current lane is empty but the same workspace has staged entries on another branch, the CLI
217
+ prints a warning. That usually means the checkout switched branches after staging; re-stage on this
218
+ branch or switch back.
215
219
  - **A landing clears only the lander's lane.** Every stage records the commit it came from
216
220
  (`stageBaseSha`), and `components status` compares that with the last commit the platform synced for the
217
221
  branch (`branchContext.lastSyncedSha`) using your local git:
@@ -97,6 +97,17 @@ remits-cli verify report
97
97
  The report is the final-response source. It separates verified claims, missing evidence, stale packets,
98
98
  and the source/account/lane tuple, so do not replace it with a generic "verified" sentence.
99
99
 
100
+ For Test requirements, be specific enough for the evaluator to know what a pass means:
101
+
102
+ ```json
103
+ {"id":"api_flow", "packetType":"test_run", "suite":"Statement API Flow", "allCases":true}
104
+ {"id":"duplicate_fee_case", "packetType":"test_run", "suite":"Statement API Flow", "cases":["rejects duplicated fee evidence"]}
105
+ ```
106
+
107
+ A requirement that says only `{"packetType":"test_run"}` is intentionally only a warning-worthy sketch:
108
+ it will not turn a random Test packet into acceptance. Full-suite runs emit suite and passed-case
109
+ categories automatically, so case-level requirements can be satisfied by a real full run.
110
+
100
111
  ## Development Workflow
101
112
 
102
113
  ### The Golden Rule: Writing Code Is Not Finishing the Job
@@ -327,9 +338,13 @@ This applies to:
327
338
  ```bash
328
339
  remits-cli test run --test <TEST_ID_OR_NAME>
329
340
  remits-cli test run --test "Invoice Tests" --names "specific test case"
341
+ remits-cli test status --task-id <TASK_ID>
330
342
  ```
331
343
 
332
- Tests run on the platform against your staged snapshot. They stream results in real-time. If they fail, fix the code, re-stage, and re-run.
344
+ Tests run on the platform against your staged snapshot. They stream results in real-time. If they fail,
345
+ read the printed pivots first: failed cases include timing, trace ids, bounded `report(...)`
346
+ diagnostics, live HTTP signals, and resolved component provenance when available. Fix the code,
347
+ re-stage, and re-run only after those pivots explain the failure.
333
348
 
334
349
  Important test-runner constraints:
335
350
  - `remits-cli test run` now defaults to `test` dataMode unless you explicitly pass `--data-mode prod`.
@@ -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. |