@remits/remits-cli 0.1.89 → 0.1.91

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.
@@ -7,121 +7,124 @@ description: Use remits-cli for fast branch-scoped component staging, test execu
7
7
 
8
8
  ## Table of Contents
9
9
 
10
- - Line 127: Account Targeting Model
11
- - Line 134: Account types
12
- - Line 149: How accounts connect (and why it changes what runs)
13
- - Line 179: Users are a separate model — don't reason about them as a tree
14
- - Line 192: Reading the shape
15
- - Line 218: Repo selection rules
16
- - Line 230: Component Integrity Rules: Repo ↔ Database Reconciliation (read before any sync/commit)
17
- - Line 236: How the platform reconciles the repo into the database (the mechanism you must understand)
18
- - Line 298: The surfaces and their intended behavior
19
- - Line 322: Intended workflows
20
- - Line 343: Pre-sync safety check (confirm ALL before `components sync` or `components commit`)
21
- - Line 356: If something looks wrong — stop, don't paper over
22
- - Line 380: Required Local Index Reads
23
- - Line 414: Big Picture: How remits-cli State Is Organized
24
- - Line 444: Support Ticket Mental Model
25
- - Line 480: Efficiency Rules
26
- - Line 492: Account Repository Index
27
- - Line 517: Two Workflows
28
- - Line 524: Test Mode vs Prod Mode
29
- - Line 556: Platform Mental Model: Front Stage vs Back Stage
30
- - Line 563: Documents vs Records
31
- - Line 573: HTTP Audits
32
- - Line 627: Record `content` / Context Mental Model
33
- - Line 647: Provenance Fields
34
- - Line 665: Why Persisted Context Looks Different From Runtime Context
35
- - Line 686: Investigation Rule for Record Context
36
- - Line 701: AI Request Response Records
37
- - Line 708: AI Session Groupings
38
- - Line 727: Correlation Keys
39
- - Line 733: Node Reference Table
40
- - Line 743: Repository vs External Context
41
- - Line 750: Getting Started
42
- - Line 752: Authentication
43
- - Line 765: Host vs Data Mode
44
- - Line 784: Tool Execution Lifecycle
45
- - Line 838: Data Mode
46
- - Line 848: Development Workflow
47
- - Line 850: The Golden Rule: Writing Code Is Not Finishing the Job
48
- - Line 862: Avoid Brittle Front-Stage Intelligence
49
- - Line 875: The Development Fast Loop
50
- - Line 879: Step 1: Understand the Request
51
- - Line 894: Step 2: Make the Change
52
- - Line 932: Step 3: Stage to Platform
53
- - Line 947: Step 4: Verify the Change
54
- - Line 1012: Step 5: Iterate If Needed
55
- - Line 1022: Step 6: Update Documentation
56
- - Line 1034: Step 7: Commit and Durable Sync
57
- - Line 1072: Step 8: Close the Ticket
58
- - Line 1087: User Confirmation Preferences
59
- - Line 1097: Component Resolution: Staging Cache vs DB (which "version" actually runs)
60
- - Line 1103: The three source layers + the compile cache
61
- - Line 1126: Staging cache key format
62
- - Line 1141: How the platform picks staged vs DB (the compile signature)
63
- - Line 1163: When staged overrides apply
64
- - Line 1187: Diagnosing which version is in play
65
- - Line 1208: Stage / commit / clear with the MCP tools
66
- - Line 1232: Stale after sync / commit (the in-memory compile cache)
67
- - Line 1242: Account Resolution: how a request travels the account graph
68
- - Line 1335: Branched Component Variants (per-account component overrides)
69
- - Line 1343: The model (three moving parts)
70
- - Line 1410: Which world does your working tree resolve? (read this before you run anything)
71
- - Line 1476: Two levers, two different questions
72
- - Line 1490: The SDLC is identical on a variant branch
73
- - Line 1515: Promotion: getting the branch back into trunk
74
- - Line 1557: Verifying as the subscriber
75
- - Line 1576: Agents (Utility) on a variant branch
76
- - Line 1588: Danger profile on a variant branch (different, not absent)
77
- - Line 1616: Inspecting branches and drift
78
- - Line 1648: Diagnosing a variant
79
- - Line 1655: Production Support Workflow
80
- - Line 1663: Investigation Strategy
81
- - Line 1693: Presenting Findings
82
- - Line 1701: Verifying a Production Issue Fix
83
- - Line 1714: Tool Reference
84
- - Line 1716: Execute a Tool
85
- - Line 1745: `mcp_account_view`
86
- - Line 1777: `mcp_account_user_admin`
87
- - Line 1812: `mcp_firestore_search`
88
- - Line 1850: `mcp_object_activity`
89
- - Line 1859: `mcp_record_listing`
90
- - Line 1884: `mcp_record_view`
91
- - Line 1897: `mcp_ai_session_search`
92
- - Line 1933: `mcp_run_action`
93
- - Line 1977: `mcp_run_agent`
94
- - Line 2013: `mcp_system_logs`
95
- - Line 2036: `mcp_component_view`
96
- - Line 2059: `mcp_component_grep`
97
- - Line 2072: `mcp_support_ticket`
98
- - Line 2121: `mcp_run_test`
99
- - Line 2130: `mcp_component_edit`
100
- - Line 2145: `mcp_component_create`
101
- - Line 2159: `mcp_component_commit`
102
- - Line 2167: `mcp_component_branches`
103
- - Line 2186: `mcp_cache`
104
- - Line 2198: `mcp_sql_query`
105
- - Line 2233: `mcp_index_search`
106
- - Line 2253: `mcp_get_guide`
107
- - Line 2265: `mcp_test_fixture`
108
- - Line 2278: `mcp_embeddable_test_url`
109
- - Line 2290: `mcp_playwright_replay`
110
- - Line 2305: `mcp_jvm_spike_triage`
111
- - Line 2318: `mcp_support_ticket_queue`
112
- - Line 2335: Multi-Session Support
113
- - Line 2355: Persistent Service, Control Center, and Agent Dispatch
114
- - Line 2364: Starting the Service
115
- - Line 2390: Control Center
116
- - Line 2405: Agent Dispatch
117
- - Line 2426: Configuring the Preferred Agent
118
- - Line 2437: Local State Files
119
- - Line 2485: Command Reference
120
- - Line 2527: Troubleshooting
121
- - Line 2569: When Something Doesn't Work as Expected
122
- - Line 2580: Back-Stage Escalation Workflow (platform defect/limitation)
123
- - Line 2589: Escalation Bundle (tooling/operational issue)
124
-
10
+ - Line 130: Account Targeting Model
11
+ - Line 137: Account types
12
+ - Line 152: How accounts connect (and why it changes what runs)
13
+ - Line 184: Users are a separate model — don't reason about them as a tree
14
+ - Line 197: Reading the shape
15
+ - Line 223: Repo selection rules
16
+ - Line 235: Component Integrity Rules: Repo ↔ Database Reconciliation (read before any sync/commit)
17
+ - Line 241: How the platform reconciles the repo into the database (the mechanism you must understand)
18
+ - Line 303: The surfaces and their intended behavior
19
+ - Line 327: Intended workflows
20
+ - Line 348: Pre-sync safety check (confirm ALL before `components sync` or `components commit`)
21
+ - Line 361: If something looks wrong — stop, don't paper over
22
+ - Line 385: Required Local Index Reads
23
+ - Line 419: Big Picture: How remits-cli State Is Organized
24
+ - Line 449: Support Ticket Mental Model
25
+ - Line 485: Efficiency Rules
26
+ - Line 497: Account Repository Index
27
+ - Line 522: Two Workflows
28
+ - Line 529: Test Mode vs Prod Mode
29
+ - Line 561: Platform Mental Model: Front Stage vs Back Stage
30
+ - Line 568: Documents vs Records
31
+ - Line 578: HTTP Audits
32
+ - Line 632: Record `content` / Context Mental Model
33
+ - Line 652: Provenance Fields
34
+ - Line 670: Why Persisted Context Looks Different From Runtime Context
35
+ - Line 691: Investigation Rule for Record Context
36
+ - Line 706: AI Request Response Records
37
+ - Line 713: AI Session Groupings
38
+ - Line 732: Correlation Keys
39
+ - Line 738: Node Reference Table
40
+ - Line 748: Repository vs External Context
41
+ - Line 755: Getting Started
42
+ - Line 757: Authentication
43
+ - Line 770: Host vs Data Mode
44
+ - Line 789: Tool Execution Lifecycle
45
+ - Line 843: Data Mode
46
+ - Line 853: Development Workflow
47
+ - Line 855: The Golden Rule: Writing Code Is Not Finishing the Job
48
+ - Line 867: Avoid Brittle Front-Stage Intelligence
49
+ - Line 880: The Development Fast Loop
50
+ - Line 884: Step 1: Understand the Request
51
+ - Line 899: Step 2: Make the Change
52
+ - Line 938: Step 3: Stage to Platform
53
+ - Line 953: Step 4: Verify the Change
54
+ - Line 1018: Step 5: Iterate If Needed
55
+ - Line 1028: Step 6: Update Documentation
56
+ - Line 1040: Temporary Experiment Workflow
57
+ - Line 1060: Step 7: Commit and Durable Sync
58
+ - Line 1098: Step 8: Close the Ticket
59
+ - Line 1113: User Confirmation Preferences
60
+ - Line 1123: Component Resolution: Staging Cache vs DB (which "version" actually runs)
61
+ - Line 1129: The three source layers + the compile cache
62
+ - Line 1152: Staging cache key format
63
+ - Line 1167: How the platform picks staged vs DB (the compile signature)
64
+ - Line 1189: When staged overrides apply
65
+ - Line 1213: Diagnosing which version is in play
66
+ - Line 1234: Stage / commit / clear with the MCP tools
67
+ - Line 1258: Stale after sync / commit (the in-memory compile cache)
68
+ - Line 1268: Account Resolution: how a request travels the account graph
69
+ - Line 1373: Branched Component Variants (per-account component overrides)
70
+ - Line 1381: The model (three moving parts)
71
+ - Line 1454: Which world does your working tree resolve? (read this before you run anything)
72
+ - Line 1521: Two levers, two different questions
73
+ - Line 1535: The SDLC is identical on a variant branch
74
+ - Line 1560: Promotion: getting the branch back into trunk
75
+ - Line 1602: Verifying as the subscriber
76
+ - Line 1621: Agents (Utility) on a variant branch
77
+ - Line 1633: Danger profile on a variant branch (different, not absent)
78
+ - Line 1661: Inspecting branches and drift
79
+ - Line 1693: Diagnosing a variant
80
+ - Line 1700: Production Support Workflow
81
+ - Line 1708: Investigation Strategy
82
+ - Line 1770: Presenting Findings
83
+ - Line 1778: Verifying a Production Issue Fix
84
+ - Line 1791: Tool Reference
85
+ - Line 1793: Execute a Tool
86
+ - Line 1839: `mcp_account_view`
87
+ - Line 1871: `mcp_account_user_admin`
88
+ - Line 1965: `mcp_firestore_search`
89
+ - Line 2004: `mcp_firestore_patch`
90
+ - Line 2033: `mcp_object_activity`
91
+ - Line 2042: `mcp_record_listing`
92
+ - Line 2067: `mcp_record_view`
93
+ - Line 2080: `mcp_ai_session_search`
94
+ - Line 2116: `mcp_run_action`
95
+ - Line 2169: `mcp_run_agent`
96
+ - Line 2205: `mcp_system_logs`
97
+ - Line 2228: `mcp_performance_trace`
98
+ - Line 2263: `mcp_component_view`
99
+ - Line 2286: `mcp_component_grep`
100
+ - Line 2299: `mcp_support_ticket`
101
+ - Line 2359: `mcp_run_test`
102
+ - Line 2368: `mcp_component_edit`
103
+ - Line 2383: `mcp_component_create`
104
+ - Line 2397: `mcp_component_commit`
105
+ - Line 2405: `mcp_component_branches`
106
+ - Line 2424: `mcp_cache`
107
+ - Line 2436: `mcp_sql_query`
108
+ - Line 2471: `mcp_index_search`
109
+ - Line 2491: `mcp_get_guide`
110
+ - Line 2503: `mcp_test_fixture`
111
+ - Line 2516: `mcp_embeddable_test_url`
112
+ - Line 2528: `mcp_playwright_replay`
113
+ - Line 2543: `mcp_jvm_spike_triage`
114
+ - Line 2556: `mcp_support_ticket_queue`
115
+ - Line 2573: Multi-Session Support
116
+ - Line 2593: Persistent Service, Control Center, and Agent Dispatch
117
+ - Line 2602: Starting the Service
118
+ - Line 2628: Control Center
119
+ - Line 2643: Agent Dispatch
120
+ - Line 2664: Configuring the Preferred Agent
121
+ - Line 2675: Local State Files
122
+ - Line 2723: Command Reference
123
+ - Line 2783: Prod banners and retryable failures
124
+ - Line 2795: Troubleshooting
125
+ - Line 2837: When Something Doesn't Work as Expected
126
+ - Line 2848: Back-Stage Escalation Workflow (platform defect/limitation)
127
+ - Line 2857: Escalation Bundle (tooling/operational issue)
125
128
  `remits-cli` is the brainstem for both **development** and **production support**. You might run it inside an account repository (where `account-info.json` and `/components` already exist) or from outside any repo when a user needs help on another account. Your users are business professionals — they think in terms of what they can see in a browser.
126
129
 
127
130
  ## Account Targeting Model
@@ -173,8 +176,10 @@ Two consequences that generate most "this account is weird" tickets:
173
176
  different component version, a different namespace, a different host. Establish which path a failing
174
177
  request travelled before comparing behavior. (Full detail in "Account Resolution: how a request travels
175
178
  the account graph".)
176
- 2. **An account with no primary parent and several membership edges inherits nothing and runs trunk** until
177
- a path is named — the platform refuses to guess between equally valid parents. That is by design.
179
+ 2. **An account with no primary parent and SEVERAL membership edges inherits nothing and runs trunk** until
180
+ a path is named — the platform refuses to guess between equally valid parents. That is by design. With
181
+ exactly ONE membership edge there is nothing to guess, so it (and everything below it) inherits normally
182
+ — a missing `parentId` is not itself a problem.
178
183
 
179
184
  ### Users are a separate model — don't reason about them as a tree
180
185
 
@@ -917,6 +922,7 @@ summary: One-line statement of what this component is for.
917
922
  description: |
918
923
  Longer technical description with line-number references to the key logic.
919
924
  path: /page/merchant-portal # Readers and Embeddables only
925
+ injectionType: DIRECT # Embeddables only: DIRECT or IFRAME
920
926
  category: default
921
927
  auxiliary: false # `true` means the sync SKIPS the file entirely — see Auxiliary
922
928
  mermaid: |
@@ -1031,6 +1037,26 @@ Before committing, update metadata so the next session understands what changed:
1031
1037
  describes the owning repo account. On a subscriber-initiated variant sync it describes the subscribing
1032
1038
  account reached through the branch edge, even though the component files still belong to the owner's repo.
1033
1039
 
1040
+ #### Temporary Experiment Workflow
1041
+
1042
+ Use this when you need to prove a guard or assertion by temporarily making a local component fail. The staged
1043
+ Redis cache can affect later test/tool runs, so always clear it after restoring the file:
1044
+
1045
+ ```bash
1046
+ # make temporary local edit
1047
+ remits-cli components stage
1048
+ remits-cli test run --test <id-or-name> --names "<case name>"
1049
+ git restore <file>
1050
+ remits-cli components clear --all
1051
+ remits-cli components status
1052
+ ```
1053
+
1054
+ For narrower cleanup when only one staged component should be cleared:
1055
+
1056
+ ```bash
1057
+ remits-cli components clear --component-type Action --component-id 25
1058
+ ```
1059
+
1034
1060
  #### Step 7: Commit and Durable Sync
1035
1061
 
1036
1062
  Once verified and documented, create a normal git commit first:
@@ -1135,7 +1161,7 @@ account:<accountId>:cli:<cliUserId>:components:<branch>:<family>:name:<normalize
1135
1161
  component's OWN type enum such as `ObjectType`/`RuleType`, or absent — **never** the family), `hash`,
1136
1162
  `updatedAt`, the staged content field(s) (`source`/`prompt`/`html`/`javascript`/`schema`/
1137
1163
  `inputSchema`/`previewData`), and `.meta.yml` metadata fields such as `description`, `summary`, `mermaid`,
1138
- `path`, `category`, and Schema flags (`enableTrigger`, `enableFullText`, `enableRAG`, `enableRevisions`,
1164
+ `path`, Embeddable `injectionType`, `category`, and Schema flags (`enableTrigger`, `enableFullText`, `enableRAG`, `enableRevisions`,
1139
1165
  `enableBigQuerySync`, `enableRules`, `anchor`, `auxiliary`).
1140
1166
 
1141
1167
  ### How the platform picks staged vs DB (the compile signature)
@@ -1280,19 +1306,31 @@ with a branch.
1280
1306
 
1281
1307
  **The anchor is the branch of the graph you travelled.** At runtime it is `scope_account_id` (stamped
1282
1308
  onto the `Object`/`Event`/`Alert`/`ObjectLog` records a run creates, so async workers re-resolve on the
1283
- same branch). A **null** anchor means "walk the primary `parentId` chain" — today's legacy behavior.
1309
+ same branch). A **null** anchor means "walk the structural chain" — see below.
1284
1310
 
1285
- **Default-anchor derivation is deliberately conservative, and this is the #1 gotcha:**
1311
+ **How the chain is walked, and the #1 gotcha.** The walk follows `Account.parentId`, and at an account with
1312
+ **no** `parentId` it continues through that account's *single* active membership edge. Applied at every hop:
1286
1313
 
1287
- | Account shape | Derived anchor |
1314
+ | Account shape at a hop | What the walk does |
1288
1315
  |---|---|
1289
- | has a `parentId` | `null` → primary chain (legacy, unchanged) |
1290
- | no `parentId`, **exactly one** membership edge | that edge's parent |
1291
- | no `parentId`, **multiple** membership edges | `null` — **ambiguous, refuses to guess** |
1316
+ | has a `parentId` | follow it (legacy, unchanged) |
1317
+ | no `parentId`, **exactly one** membership edge | **continue through that edge** |
1318
+ | no `parentId`, **multiple** membership edges | **stop** — ambiguous, refuses to guess |
1319
+ | no `parentId`, no edges | stop — a true root |
1320
+
1321
+ **Primary-vs-membership does not gate inheritance; only ambiguity does.** A `parentId`-less subscriber shell
1322
+ linked to its owner by one membership edge inherits that owner's components and branch — **and so does
1323
+ everything beneath it**. You do not need to give it a real `parentId`.
1324
+
1325
+ But a `parentId`-less account with **two** membership edges resolves **trunk and inherits nothing** until an
1326
+ anchor is supplied. That is correct-by-design (the inheritance path must stay linear, or component
1327
+ name-dedupe would pick an arbitrary winner between two sibling products), not a bug. Entry points that
1328
+ already know the branch disambiguate it by branch name; from the CLI you supply it explicitly.
1292
1329
 
1293
- So a `parentId`-less account with two membership edges resolves **trunk and inherits nothing** until an
1294
- anchor is supplied. That is correct-by-design, not a bug. Entry points that already know the branch
1295
- disambiguate it by branch name; from the CLI you supply it explicitly.
1330
+ > Before 2026-08 the continuation was applied **only to the account a lookup started from**, so a
1331
+ > membership-only account truncated the chain for all of its descendants — they inherited nothing and
1332
+ > resolved trunk while the subscriber itself looked fine. If you are reading an older investigation that
1333
+ > "fixed" this by reparenting a subscriber under its owner, that workaround is no longer needed.
1296
1334
 
1297
1335
  **Same account, two parents, two answers.** An account reached through Product A versus Product B can
1298
1336
  legitimately resolve a different component variant *and* a different data segment. When you investigate
@@ -1406,7 +1444,7 @@ changes validation and where the subscriber's documents physically land. Treat s
1406
1444
  same care as a trunk schema change.
1407
1445
 
1408
1446
  **What a branch may override.** A variant speaks the same `.meta.yml` vocabulary trunk does — `name`,
1409
- `description`, `summary`, `mermaid`, `category`, `type`, `path`, `collectionName`, `job`, `model`,
1447
+ `description`, `summary`, `mermaid`, `category`, `type`, `path`, `injectionType`, `collectionName`, `job`, `model`,
1410
1448
  `agentTimeout`, `mcp`, `cli`, `global`, `purpose`, `auxiliary`, plus Schema flags (`enableTrigger`,
1411
1449
  `enableFullText`, `enableRAG`, `enableRevisions`, `enableBigQuerySync`, `enableRules`, `anchor`) — and the
1412
1450
  component's content files. Keys outside that set are ignored, deliberately: trunk cannot express them either,
@@ -1465,8 +1503,9 @@ Read the `resolution` block before acting from any checkout — it is the ONE pl
1465
1503
  - `resolution.componentBranch` / `resolution.scopeAccountId` — the branch and the path anchor that made this
1466
1504
  subscriber resolution possible.
1467
1505
  - `resolution.parents` / `resolution.children` / `resolution.relationships` — the account graph, stated once
1468
- and compactly. The full descendant tree is a lookup (`mcp_account_user_admin`, `mcp_account_view`), not a
1469
- committed artifact.
1506
+ and compactly. For quick live hierarchy checks, prefer `mcp_account_user_admin` with `action:"account"` or
1507
+ `action:"hierarchy"`; use `mcp_account_view` only when component inventory or detailed configuration is also
1508
+ needed. The full descendant tree is a lookup, not a committed artifact.
1470
1509
 
1471
1510
  **One branch, one `account-info.json`.** There is exactly one git branch, so when a branch has MORE THAN ONE
1472
1511
  subscriber the refresh is skipped (the sync result says so under `accountInfo.skipped`/`reason`) and the file
@@ -1683,8 +1722,9 @@ Before starting an investigation outside the confirmed current repo:
1683
1722
  5. `mcp_record_listing` — search or filter alerts, events, object logs, or objects when you need to find the suspicious record first.
1684
1723
  6. `mcp_record_view` — drill into suspicious entries for full content.
1685
1724
  7. `mcp_ai_session_search` — if the workflow involves AI, inspect session groupings, prompts, tool definitions, and responses in human-readable form.
1686
- 8. `mcp_system_logs` — correlate via `threadGroupingId` for execution traces.
1687
- 9. `mcp_component_view`/`mcp_component_grep` — explain how the responsible component works.
1725
+ 8. `mcp_performance_trace` — for slow/sluggish reports, start with `action:"slowest"` when you only have a window, or `action:"trace"` when you have a `threadGroupingId`; this is the MCP wrapper for the Diagnostics page request-trace data.
1726
+ 9. `mcp_system_logs` — correlate via `threadGroupingId` for raw log context when the trace needs supporting log lines.
1727
+ 10. `mcp_component_view`/`mcp_component_grep` — explain how the responsible component works.
1688
1728
 
1689
1729
  **Error or Alert Investigation:**
1690
1730
  1. `mcp_record_listing` — search by alert type, content, error text, action, status, `threadGroupingId`, or other exact-match record properties when you do not yet know the record ID.
@@ -1696,6 +1736,40 @@ Before starting an investigation outside the confirmed current repo:
1696
1736
  7. If the context looks missing, redacted, or truncated, consider sanitization rules before concluding data was never present.
1697
1737
  8. If AI behavior is part of the symptom, use `mcp_ai_session_search` and compare the persisted session content against the Agent component implementation and `docs/guides/features/ai-support.md`.
1698
1738
 
1739
+ **Stuck / failed / recovered Event:**
1740
+
1741
+ Do **not** open the Action source first. The platform records each attempt's delivery envelope (which
1742
+ queue delivered it, which delivery attempt this was, which instance owned it, how long it was ever
1743
+ allowed to run) and will classify the failure for you. From a Test or any component:
1744
+
1745
+ ```groovy
1746
+ eventDiagnostics(18838)
1747
+ ```
1748
+
1749
+ Read `classification` before anything else:
1750
+
1751
+ - `APPLICATION_FAILURE` — **the only one that means the bug is in the component.** Read `errorMessage`
1752
+ and the correlated `alerts`, then investigate the component normally.
1753
+ - `ORPHANED_*` / `RECOVERED_*` — the attempt was abandoned. Read `abandonmentCause`:
1754
+ - `REQUEST_TIMEOUT_LIKELY` — used its whole deadline (`timing.deadlineUsed` near `1.0`). The unit of
1755
+ work is too big for one event; the fix is resumable batches, not component logic.
1756
+ - `PROCESS_TERMINATED_LIKELY` — stopped well inside its deadline (`deadlineUsed` near `0`). The worker
1757
+ was killed (memory pressure, restart). Not a logic bug.
1758
+ - `UNKNOWN_NO_DEADLINE_EVIDENCE` — no deadline recorded, so the cause is genuinely unknown. Use
1759
+ `logQuery`; do not assume. Events predating delivery-envelope capture always look like this.
1760
+ - `AWAITING_DELIVERY` — never claimed. A queue/delivery problem.
1761
+ - `IN_FLIGHT_HEALTHY` — still running with a fresh heartbeat. A long Action is not a stuck one; wait.
1762
+
1763
+ `delivery.deliveryAttempt` above `1` means Cloud Tasks had **already** retried this event, so any
1764
+ non-idempotent side effect may have run more than once — check for duplicate records before concluding
1765
+ the component "ran twice for no reason".
1766
+
1767
+ `delivery.threadGroupingId` is the same id everything else uses, so you can pivot straight into
1768
+ `mcp_performance_trace` (`action:"trace"`) or `mcp_system_logs` with it. `logQuery` in the response
1769
+ carries ready-made Cloud Logging filters, including the container-lifecycle and 504 queries.
1770
+
1771
+ Full detail: `docs/guides/features/observability.md` §5b and `events-builder-guide.md`.
1772
+
1699
1773
  ### Presenting Findings
1700
1774
 
1701
1775
  Users are not engineers. When reporting investigation results:
@@ -1727,6 +1801,23 @@ remits-cli tool --name "mcp_firestore_search" --input '{"accountId": 37, "collec
1727
1801
 
1728
1802
  Response saved to `./.remits-cli/tool-responses/<callId>.json`. Read the file to see results.
1729
1803
 
1804
+ **"Tool call succeeded" means DISPATCHED, not that the tool did what you asked.** A tool that runs
1805
+ and refuses — an unmet precondition, a rejected enum value, a failed validation — returns HTTP 200
1806
+ with its own `success: false` inside `result`. The CLI now prints `Tool call FAILED — the tool ran
1807
+ and returned an error.` plus a `Tool error:` line and exits non-zero, and the response envelope
1808
+ carries `toolSuccess` / `toolMessage`. **For any MUTATING call, confirm the tool's own verdict before
1809
+ reporting the work as done** — do not grep the terminal output for "succeeded":
1810
+
1811
+ ```bash
1812
+ F=$(remits-cli tool --name mcp_support_ticket --input "$(cat payload.json)" --data-mode prod 2>&1 \
1813
+ | grep -o '[^ ]*tool-responses/[a-f0-9-]*\.json' | tail -1)
1814
+ python3 -c "import json;r=json.load(open('$F'))['result'];print(r.get('success'), r.get('message'))"
1815
+ ```
1816
+
1817
+ Build non-trivial JSON into a file (e.g. with `python3 -c 'json.dumps(...)'`) and pass it as
1818
+ `--input "$(cat payload.json)"`. Long inline single-quoted JSON intermittently produces no response
1819
+ file at all.
1820
+
1730
1821
  For long-running Action/Agent runners, use the tool's own async mode (`executionMode:"async"`), which returns
1731
1822
  the `actionRunId`/`agentRunId` (and, for agents, `sessionId`) immediately:
1732
1823
 
@@ -1849,11 +1940,19 @@ client accounts beneath it:
1849
1940
  type:'CLIENT' # inherits the branch automatically
1850
1941
  ```
1851
1942
 
1852
- > **Put the branch on the account's PRIMARY edge.** Component inheritance follows the *anchored* path, which
1853
- > for an account with a `parentId` is its primary chain. An account that has both a primary edge and a
1854
- > *membership* edge carrying the branch resolves **trunk** by default — the membership edge is never
1855
- > anchored unless a request names it (`--as-account`, `--variant-branch`, or the edge's own host). Descendants
1856
- > then inherit the branch down that primary chain automatically, which is what makes step 4 free.
1943
+ > **Put the branch on the edge that is UNAMBIGUOUSLY on the account's path up — primary or membership.**
1944
+ > Inheritance walks `parentId` and, at an account that has no `parentId`, continues through its *single*
1945
+ > active membership edge. So a subscriber shell with **no `parentId` and one membership edge** to its owner
1946
+ > is a fully supported shape: it resolves the branch, **and so do all of its descendants**. You do not need
1947
+ > to make the subscriber a structural child of its owner.
1948
+ >
1949
+ > What is NOT resolved by default is genuine **ambiguity** — an account with *several* upward links, where
1950
+ > the platform refuses to guess which product it was reached through. That account (and its descendants)
1951
+ > resolve trunk until a request names the path: `--as-account`, `--variant-branch`, or the edge's own host.
1952
+ > An account that has a `parentId` **and** a separate membership edge carrying the branch is this case: the
1953
+ > `parentId` wins, so put the branch on the link the account actually inherits through.
1954
+ >
1955
+ > Either way, descendants inherit the branch down the chain automatically, which is what makes step 4 free.
1857
1956
 
1858
1957
  | Parameter | Required | Description |
1859
1958
  |-----------|----------|-------------|
@@ -1881,6 +1980,7 @@ Query Firestore documents.
1881
1980
  | `aggregation` | no | `{sum: [...], avg: [...], min: [...], max: [...], count: true}` |
1882
1981
  | `dateRanges` | no | `[{field, startDate, endDate}]` (yyyy-MM-dd) |
1883
1982
  | `textSearch` | no | `[{field, prefix}]` for prefix matching |
1983
+ | `fallbackOnMissingIndex` | no | When `true`, a sorted read that fails on a missing composite index retries without sort and returns `warning`, `missingIndexUrl`, and `sortApplied:false`. Use when an unsorted first page is still useful. |
1884
1984
 
1885
1985
  HTTP audit usage notes:
1886
1986
 
@@ -1904,6 +2004,35 @@ remits-cli tool --name "mcp_firestore_search" --input '{"accountId": 37, "collec
1904
2004
  - `response.statusCode`
1905
2005
  - `success`
1906
2006
 
2007
+ ### `mcp_firestore_patch`
2008
+ Guarded exact-document Firestore patch tool for bounded repairs. It defaults to `dryRun:true` and refuses broad
2009
+ updates, wildcard collections, delete/remove operations, protected identity fields, and `_lastModified*` audit
2010
+ fields.
2011
+
2012
+ Use it when the desired repair is mechanical and smaller than rerunning an expensive Action, for example copying
2013
+ canonical fields into stale UI mirror fields. Always dry-run first and include preconditions:
2014
+
2015
+ ```bash
2016
+ remits-cli tool --name mcp_firestore_patch --data-mode prod --input '{
2017
+ "accountId":743,
2018
+ "collection":"statements",
2019
+ "documentId":"20958",
2020
+ "dryRun":true,
2021
+ "preconditions":[
2022
+ {"field":"interchangeOptimization.status","equals":"Calculated"},
2023
+ {"field":"interchangeOptimizationChecked","equals":false}
2024
+ ],
2025
+ "patch":{
2026
+ "interchangeOptimizationChecked":true,
2027
+ "feeBreakdown.interchangeOptimization":{"$copyFrom":"interchangeOptimization"},
2028
+ "feeBreakdown.interchange.optimization":{"$copyFrom":"interchangeOptimization"}
2029
+ }
2030
+ }'
2031
+ ```
2032
+
2033
+ Response fields include `dataMode`, `accountId`, `collection`, `documentId`, `dryRun`, `patchedFields`, and
2034
+ `diff`. Switch to `"dryRun":false` only after the diff and preconditions are exactly what you intended.
2035
+
1907
2036
  ### `mcp_object_activity`
1908
2037
  Object lifecycle timeline — metadata + recent activity.
1909
2038
 
@@ -1991,6 +2120,15 @@ Audit flow: `action:"search"` to find the grouping → `action:"detail"` + `summ
1991
2120
  Run an Action on a target account, with explicit prod/test data mode, optional staged branch resolution, and
1992
2121
  staged-vs-DB provenance in the result.
1993
2122
 
2123
+ Describe the Action first when the input shape is not obvious. This does not execute the Action:
2124
+
2125
+ ```bash
2126
+ remits-cli tool --name mcp_run_action --input '{"controlAction":"describe","accountId":743,"actionId":25,"includeInputSchema":true}' --data-mode prod
2127
+ ```
2128
+
2129
+ The describe response reports `hasInputSchema`, optional `inputSchema`, `inferredInputKeys`, and component
2130
+ provenance. If `hasInputSchema:false`, treat `inferredInputKeys` as a best-effort static scan, not a contract.
2131
+
1994
2132
  Use direct mode only for quick Actions:
1995
2133
 
1996
2134
  ```bash
@@ -2090,6 +2228,41 @@ Query Cloud Run service logs.
2090
2228
  {"node": "remitsAdmin-east5", "timeRange": "4h", "severity": "ERROR"}
2091
2229
  ```
2092
2230
 
2231
+ ### `mcp_performance_trace`
2232
+ Read Remits request traces through the same `traces(...)` DSL that powers the admin Diagnostics "Request
2233
+ traces" panel. Use this before raw log spelunking for slow or sluggish requests because it returns profiled
2234
+ span rollups, component annotations, and retained slow-request summaries directly.
2235
+
2236
+ Common flows:
2237
+
2238
+ ```bash
2239
+ # User only knows it was slow this afternoon
2240
+ remits-cli tool --name mcp_performance_trace --input '{"action":"slowest","lookbackHours":4,"accountId":52,"minMs":2000,"limit":10}' --data-mode prod
2241
+
2242
+ # You have the Diagnostics/request/Object/Event/Alert threadGroupingId
2243
+ remits-cli tool --name mcp_performance_trace --input '{"action":"trace","traceId":"msf1y65n-001","lookbackHours":6,"format":"markdown"}' --data-mode prod
2244
+
2245
+ # Same local-node data as the Diagnostics table
2246
+ remits-cli tool --name mcp_performance_trace --input '{"action":"snapshot","limit":100}' --data-mode prod
2247
+ ```
2248
+
2249
+ | Parameter | Required | Description |
2250
+ |-----------|----------|-------------|
2251
+ | `action` | no | `snapshot`, `slowest`, or `trace`. Default: `snapshot`. |
2252
+ | `traceId` / `threadGroupingId` | for `trace` | Request/grouping id to open across local ring and Cloud Logging. |
2253
+ | `lookbackHours` | no | Cloud Logging window for `trace`/`slowest`. Defaults are 6 and 4 hours. |
2254
+ | `accountId` | no | Account filter for `slowest`. |
2255
+ | `kind` | no | Operation kind filter for `slowest`, e.g. `embeddable`, `action`, `reader`. |
2256
+ | `minMs` | no | Minimum duration for `slowest`. Default: 1500. |
2257
+ | `limit` | no | Result limit. |
2258
+ | `format` / `markdown` | no | Set `format:"markdown"` or `markdown:true` for a rendered trace report. |
2259
+
2260
+ Reading rule: first use `slowest` to get candidate trace ids, then call `trace` on the suspicious id, then use
2261
+ `mcp_system_logs` only if you need surrounding log lines. A trace dominated by `firestore.*`, `http.*`,
2262
+ `gorm.save.*`, or component spans points you at the relevant platform seam or front-stage component. Large
2263
+ unaccounted wall time is itself a finding: check cold compile, queueing, blocking I/O, or missing
2264
+ `measure(...)` instrumentation.
2265
+
2093
2266
  ### `mcp_component_view`
2094
2267
  Read component field content with line numbers.
2095
2268
 
@@ -2141,10 +2314,10 @@ Create and manage the full lifecycle of account-relative `support_tickets`.
2141
2314
  | `affectedComponent` | no | Component or platform area affected (`create`) |
2142
2315
  | `implementationAccountId` / `implementationAccountName` | no | Owning `PLATFORM`/`PRODUCT` account when the ticket concerns shared implementation (e.g. a back-stage platform fix) |
2143
2316
  | `stepsToReproduce` / `acceptanceCriteria` / `tags` | no | Extra `create` fields for defect/enhancement tickets |
2144
- | `assignee` | no | Required for `accept` |
2145
- | `status` | no | Required for `update_status`. Valid values: `in_progress`, `pending_review` |
2317
+ | `assignee` | no | Required for `accept`. The agent's own name by convention — `claude`, `codex`, `gemini` |
2318
+ | `status` | no | Required for `update_status`. Valid values: `in_progress`, `pending_review`. **The ticket must be `accept`ed first** — otherwise the call is rejected with *"Ticket must be accepted before updating status"* |
2146
2319
  | `resolution` | no | Required for `complete` |
2147
- | `category` / `summary` / `details` / `findings` / `nextStep` | no | Worklog fields for `record_progress` (`category` + `summary` required) |
2320
+ | `category` / `summary` / `details` / `findings` / `nextStep` | no | Worklog fields for `record_progress` (`category` + `summary` required). `category` is a **fixed enum** — `triage`, `investigation`, `reproduction`, `fix`, `verification`, `handoff`, `other` — and any other value fails the whole call. `findings` is a **list of strings**, not a paragraph |
2148
2321
  | `artifactType` / `artifactLabel` / `contentBase64` / `gcsPath` / `url` | no | Evidence fields for `add_artifact` (screenshot/trace/log/test_result/link) |
2149
2322
  | `notes` | no | Optional lifecycle note stored with the ticket activity |
2150
2323
  | `attachmentIndex` | no | Zero-based index of the attachment to download. Used with `get_attachment`. |
@@ -2159,13 +2332,24 @@ Create and manage the full lifecycle of account-relative `support_tickets`.
2159
2332
 
2160
2333
  This keeps file retrieval self-contained — no separate download endpoint is needed.
2161
2334
 
2162
- **Recommended flow:**
2163
- 1. `read` with the ticket's `accountId` — check ticket state and any attachments
2164
- 2. `accept` with the ticket's `accountId`
2335
+ **Recommended flow** — `accountId` is optional throughout; `ticketId` resolves the owning account:
2336
+ 1. `read` — check ticket state and any attachments
2337
+ 2. **`accept`** (with `assignee`) — this is a **hard precondition for `update_status`**, not just etiquette
2165
2338
  3. `get_attachment` if attachments are present and relevant to the investigation
2166
- 4. `update_status` with the ticket's `accountId`
2167
- 5. investigate/fix/verify on the owning ticket account or its implementation account as appropriate
2168
- 6. `complete` or `release` with the ticket's `accountId`
2339
+ 4. `update_status` — `in_progress` while working, `pending_review` when the fix is done but not yet deployed
2340
+ 5. `record_progress` as you go — one `investigation` entry for the root cause, one `verification` entry for the proof
2341
+ 6. investigate/fix/verify on the owning ticket account or its implementation account as appropriate
2342
+ 7. `complete` (with `resolution`) or `release` if handing off
2343
+
2344
+ **Check each mutation actually landed.** Every action above is a write that can be refused while the
2345
+ CLI still reports the *call* as fine — see "Execute a Tool" for why, and read `result.success` from
2346
+ the response file. A silent no-op here means telling the user a ticket moved when it did not.
2347
+
2348
+ **Duplicates are common.** The same defect is often filed twice — once against the `CLIENT`/subscriber
2349
+ account where it was observed and once against the owning `PLATFORM`/`PRODUCT` account. Before
2350
+ starting, check `mcp_support_ticket_queue` for the same subject or affected component. Close the
2351
+ duplicate with a `resolution` naming the ticket that carries the real work, rather than investigating
2352
+ it twice.
2169
2353
 
2170
2354
  **Automation rule:** If a ticket is involved, you should usually:
2171
2355
  - `read` at the start
@@ -2553,7 +2737,7 @@ remits-cli data-mode [set test|prod]
2553
2737
  remits-cli components stage [--branch <name>] [--data-mode test|prod] [--json|--verbose]
2554
2738
  remits-cli components status [--branch <name>] [--component-type <type>] [--component-id <id>] [--json|--verbose]
2555
2739
  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
2556
- remits-cli components sync [--branch <name>] [--data-mode test|prod] [--force-tombstones] [--dry-run] # gated; on trunk = full repo->DB reconcile, on a variant branch = ComponentVariant overlays only
2740
+ remits-cli components sync [--branch <name>] [--data-mode test|prod] [--force-tombstones] [--dry-run] [--summary] # gated; on trunk = full repo->DB reconcile, on a variant branch = ComponentVariant overlays only
2557
2741
  remits-cli components commit [--message "msg"] [--data-mode test|prod] [--force-tombstones]
2558
2742
  remits-cli components branches [--json] # branches carrying committed variants, with counts + drift
2559
2743
  remits-cli components branch <name> [--json] # one branch: overridden / added / removed, drift flags, subscribers
@@ -2580,6 +2764,36 @@ For tests specifically:
2580
2764
  intentional tombstone overrides. It is rejected on trunk.
2581
2765
  - `--dry-run` is only for `components sync` on non-trunk variant branches. It reports the variant write
2582
2766
  plan without writing rows, caching the sync SHA, or clearing staging.
2767
+ - `--summary` on `components sync --dry-run` prints compact counts, removals/tombstones, skipped items, errors,
2768
+ and warnings instead of the full override/add/remove payload.
2769
+ - **Fail-closed sync gates.** The row below ("Sync response reports unexpected deletes...") tells you to
2770
+ stop *after* an unexpected sync. These flags make sync refuse it up front instead, each exiting
2771
+ non-zero rather than printing a wall of JSON you have to read carefully:
2772
+ - `--changed-only` — fail unless every planned write is a component **this checkout actually edited**.
2773
+ This is the strongest guard against a sync that quietly rewrites components you never touched. It
2774
+ also fails when the checkout is not a git working tree, because "git could not answer" must never
2775
+ be read as "nothing changed".
2776
+ - `--fail-on-removed` — fail if the plan removes or tombstones anything.
2777
+ - `--expected-removed <type:id>` — whitelist the removals you intend (repeatable, or comma-delimited,
2778
+ e.g. `--expected-removed action:5,reader:9`). It **implies** `--fail-on-removed`, so any removal you
2779
+ did not name fails the sync.
2780
+ - `--fail-on-errors` — fail if the server reported any per-component sync error.
2781
+ - `--names-only` — print only `BUCKET type:id name` lines for the planned writes.
2782
+
2783
+ A good default for an unattended promotion is:
2784
+ `remits-cli components sync --dry-run --summary --changed-only --fail-on-errors`
2785
+
2786
+ ### Prod banners and retryable failures
2787
+
2788
+ - Every command that can touch production (`tool`, `test run`, `components sync`) prints a `PROD DATA`
2789
+ banner naming the operation, the resolved account, and the host — and distinguishes a live **WRITE**
2790
+ from a live **READ** and from a **DRY RUN**. If you see a WRITE banner you did not intend, stop.
2791
+ - A tool call that fails **in the platform runtime** rather than in the tool (Groovy reflective dispatch
2792
+ of a runtime-compiled component, an empty connection pool, a Redis reconnect, a lock-wait timeout)
2793
+ now comes back as HTTP `503` with `failureClass: "transient_infrastructure"` and `retryable: true`,
2794
+ and the CLI prints `TRANSIENT INFRASTRUCTURE FAILURE (retryable)`. Retry that **once**; prefer an
2795
+ idempotent input if the tool has side effects. A genuine tool error stays HTTP `500` with
2796
+ `failureClass: "tool_error"` — do **not** retry it, fix the input or the component.
2583
2797
 
2584
2798
  ## Troubleshooting
2585
2799
 
@@ -2601,7 +2815,7 @@ For tests specifically:
2601
2815
  | Staged change has no effect in a live (non-CLI) run | Staged overrides resolve only under a CLI TestMode (`branchName`+`cliUserId`). Live webhooks and other non-CLI runtime paths still use the DB (trunk, or the account's subscribed variant). `commit` to make it durable. See "Component Resolution". |
2602
2816
  | Need to know an account's shape (role, type, parents, namespace, branch) | Read `resolution` — from the repo's `account-info.json`, or `mcp_account_user_admin` `action:'account'` (cheap), or `mcp_account_view` (full inventory): `role`/`summary`, `type`, `resolvedDatabaseName`, `relationships`, `componentBranch`, plus top-level `componentBranches`. Never infer structure from the account's name. |
2603
2817
  | Need the account tree below an account, or its users | `mcp_account_user_admin` (`action:'hierarchy'` with a `depth`, or `action:'users'`). `account-info.json` deliberately carries only direct children plus counts. |
2604
- | An account has two parents and you don't know which one a run used | `resolution.relationships` lists every link with its own `branchName`/`databaseName`/`domainName`. A membership-only account with several edges resolves **trunk and inherits nothing** until a path is named (`--as-account`, `--variant-branch`, or an edge host) — that is by design, not a bug. |
2818
+ | An account has two parents and you don't know which one a run used | `resolution.relationships` lists every link with its own `branchName`/`databaseName`/`domainName`. A membership-only account with SEVERAL edges resolves **trunk and inherits nothing** until a path is named (`--as-account`, `--variant-branch`, or an edge host) — that is by design, not a bug. With exactly ONE membership edge it inherits normally, descendants included. |
2605
2819
  | Documents missing / written to the wrong place | Compare `resolution.databaseName` (the account's own override) with `resolution.resolvedDatabaseName` (what is actually in effect), and check for a `databaseName` on one of the `relationships` edges. Data does not inherit; components do. |
2606
2820
  | 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). |
2607
2821
  | Need users of an account, or accounts of a user | There is no user MCP tool. Use `mcp_sql_query` on `user` / `user_account` (or `account.users([scope:'children'])` inside a component). Remember user custom fields are stored **per bound account**, so the same person can differ per account. |