@remits/remits-cli 0.1.112 → 0.1.114
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/README.md +3 -1
- package/index.js +990 -42
- package/package.json +3 -2
- package/skills/remits-cli/SKILL.md +139 -3366
- package/skills/remits-cli/references/account-targeting.md +165 -0
- package/skills/remits-cli/references/agent-sessions.md +218 -0
- package/skills/remits-cli/references/branch-variants.md +372 -0
- package/skills/remits-cli/references/cli-state.md +158 -0
- package/skills/remits-cli/references/command-reference.md +268 -0
- package/skills/remits-cli/references/component-integrity.md +175 -0
- package/skills/remits-cli/references/component-resolution.md +209 -0
- package/skills/remits-cli/references/development-loop.md +366 -0
- package/skills/remits-cli/references/investigation.md +251 -0
- package/skills/remits-cli/references/support-tickets.md +389 -0
- package/skills/remits-cli/references/tool-reference.md +962 -0
- package/skills/remits-cli/references/troubleshooting.md +135 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Component Resolution: Staged, Variant, Trunk
|
|
2
|
+
|
|
3
|
+
> A `remits-cli` skill reference. **Load this when** a change "is not working", you need to prove which version of a component actually ran, or several agents share one branch.
|
|
4
|
+
>
|
|
5
|
+
> The table of contents below carries **real line numbers** (`- L84 Some Heading`), resolved when
|
|
6
|
+
> this file is installed, so they are never stale. Read the head, pick your sections, and offset-read
|
|
7
|
+
> only those. The entry text is the heading verbatim, so it also greps.
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
- [Component Resolution: Staging Cache vs DB (which "version" actually runs)](#component-resolution-staging-cache-vs-db-which-version-actually-runs)
|
|
12
|
+
- [The three source layers + the compile cache](#the-three-source-layers--the-compile-cache)
|
|
13
|
+
- [Staging cache key format](#staging-cache-key-format)
|
|
14
|
+
- [How the platform picks staged vs DB (the compile signature)](#how-the-platform-picks-staged-vs-db-the-compile-signature)
|
|
15
|
+
- [When staged overrides apply](#when-staged-overrides-apply)
|
|
16
|
+
- [Diagnosing which version is in play](#diagnosing-which-version-is-in-play)
|
|
17
|
+
- [Working alongside other agents: the staging WORKSPACE](#working-alongside-other-agents-the-staging-workspace)
|
|
18
|
+
- [Stage / sync / clear with remits-cli](#stage--sync--clear-with-remits-cli)
|
|
19
|
+
- [Stale after sync / commit (the in-memory compile cache)](#stale-after-sync--commit-the-in-memory-compile-cache)
|
|
20
|
+
|
|
21
|
+
## Component Resolution: Staging Cache vs DB (which "version" actually runs)
|
|
22
|
+
|
|
23
|
+
When the platform executes a component it resolves the source from one of two places, then compiles it
|
|
24
|
+
behind an in-memory cache. Understanding this is the difference between "my change isn't working" guesses
|
|
25
|
+
and a precise diagnosis.
|
|
26
|
+
|
|
27
|
+
### The three source layers + the compile cache
|
|
28
|
+
|
|
29
|
+
1. **CLI staging cache (Redis, 240-min TTL).** Branch + user + account scoped overrides written by
|
|
30
|
+
`remits-cli components stage`. These shadow the layers below **only during CLI/test-mode execution**
|
|
31
|
+
(see "When staged overrides apply" below).
|
|
32
|
+
2. **Committed branch variants (`ComponentVariant`, MySQL).** Durable, branch-scoped overlays of a
|
|
33
|
+
component. Unlike staging these are **not** user-scoped, do **not** expire, and **do** apply to normal
|
|
34
|
+
production traffic — for the accounts that subscribe to that branch. See
|
|
35
|
+
`branch-variants.md`. Most accounts have none, in which case this layer is inert.
|
|
36
|
+
3. **Database trunk row (the committed live component).** What `mcp_component_view` reads, what an
|
|
37
|
+
unsubscribed prod run uses, and what a trunk `commit` writes to.
|
|
38
|
+
|
|
39
|
+
Resolution order is **staged → variant → trunk**, and each layer *layers over* the one beneath it rather
|
|
40
|
+
than replacing it: a payload that only carries `source` inherits `path`, `objectType`, `inputSchema` etc.
|
|
41
|
+
from the layer below. A staged edit made on a variant branch therefore layers over **that variant**, not
|
|
42
|
+
over trunk.
|
|
43
|
+
|
|
44
|
+
Plus the compile cache:
|
|
45
|
+
|
|
46
|
+
- **Compiled-closure cache (`BaseClosureDomain.CLOSURE_CACHE`).** An in-memory, **per-JVM-instance** Guava
|
|
47
|
+
cache of the parsed closure, keyed by `(componentId, type, compileSignature)`. This is why a change that
|
|
48
|
+
is correctly in the DB can still execute stale on a running instance — see "Stale after sync" below.
|
|
49
|
+
|
|
50
|
+
### Staging cache key format
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
# default lane (no workspace)
|
|
54
|
+
account:<accountId>:cli:<cliUserId>:components:<branch>:<family>:id:<componentId>
|
|
55
|
+
account:<accountId>:cli:<cliUserId>:components:<branch>:<family>:name:<normalizedName>
|
|
56
|
+
|
|
57
|
+
# workspace lane
|
|
58
|
+
account:<accountId>:cli:<cliUserId>:components:<branch>:ws:<workspace>:<family>:id:<componentId>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The staging scope is therefore **account + cli user + branch + workspace**. `workspace` is optional and
|
|
62
|
+
absent by default; see "Working alongside other agents: the staging WORKSPACE" above.
|
|
63
|
+
|
|
64
|
+
`<family>` is the lowercased component family (`reader`, `action`, `test`, `embeddable`, ...). Both an
|
|
65
|
+
`id:` and a `name:` key are written per stage. The entry value carries: `kind` (the family), `type` (the
|
|
66
|
+
component's OWN type enum such as `ObjectType`/`RuleType`, or absent — **never** the family), `hash`,
|
|
67
|
+
`updatedAt`, the staged content field(s) (`source`/`prompt`/`html`/`javascript`/`schema`/
|
|
68
|
+
`inputSchema`/`previewData`), and `.meta.yml` metadata fields such as `description`, `summary`, `mermaid`,
|
|
69
|
+
`path`, Embeddable `injectionType`, `category`, and Schema flags (`enableTrigger`, `enableFullText`, `enableRAG`, `enableRevisions`,
|
|
70
|
+
`enableBigQuerySync`, `enableRules`, `anchor`, `auxiliary`).
|
|
71
|
+
|
|
72
|
+
### How the platform picks staged vs DB (the compile signature)
|
|
73
|
+
|
|
74
|
+
At compile time the platform computes a **signature** that tells you which layer won:
|
|
75
|
+
|
|
76
|
+
- Staged override present → `compileSignature = "cli:<hash>"` (the staged content hash).
|
|
77
|
+
- Committed branch variant → `compileSignature = "variant:<variantId>:<hash12>"`.
|
|
78
|
+
- Neither → `compileSignature = "version:<N>:<sourceHash12>"` (the DB row version plus a source hash
|
|
79
|
+
prefix, so source changes cannot reuse a stale compile entry on the same instance).
|
|
80
|
+
|
|
81
|
+
The three namespaces are distinct on purpose: a component's staged, variant, and trunk closures coexist in
|
|
82
|
+
the compile cache without colliding.
|
|
83
|
+
|
|
84
|
+
That signature is logged. Querying for it is the single most reliable way to know what ran:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
remits-cli tool --name mcp_system_logs --input '{"node":"remitsAdmin-east5","timeRange":"1h","filter":"Using Cached BCD"}' --data-mode prod
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
> **Pass the bare phrase — never hand-write a `textPayload:` filter.** In production the platform's
|
|
91
|
+
> logback encoder writes every `log.*` line to **`jsonPayload.message`**; only `println`/stdout lands in
|
|
92
|
+
> `textPayload`. A `textPayload:"..."` filter therefore matches **zero** rows for nearly every platform
|
|
93
|
+
> log line, and zero rows is indistinguishable from "it never happened" — which has already caused a real
|
|
94
|
+
> misdiagnosis. `mcp_system_logs` now widens a bare phrase (and any `textPayload:"..."` clause) to cover
|
|
95
|
+
> both shapes, and echoes the executed filter back as `filterApplied`. A filter that names `jsonPayload`
|
|
96
|
+
> explicitly is passed through untouched.
|
|
97
|
+
|
|
98
|
+
`Using Cached BCD [ID: 230, Type: Action, Signature: cli:08cc...]` → ran a **staged** override.
|
|
99
|
+
`...Signature: variant:14:9f2c1a...]` → ran a **committed branch variant**.
|
|
100
|
+
`...Signature: version:37:abc123def456]` → ran the **committed trunk** version.
|
|
101
|
+
|
|
102
|
+
### When staged overrides apply
|
|
103
|
+
|
|
104
|
+
Staged overrides resolve whenever the execution carries a **CLI-scoped TestMode** — i.e.
|
|
105
|
+
`TestMode.branchName` and `TestMode.cliUserId` are set. That includes:
|
|
106
|
+
|
|
107
|
+
- `remits-cli test run`
|
|
108
|
+
- `remits-cli tool`
|
|
109
|
+
- `remits-cli tools`
|
|
110
|
+
- tokenized runs minted with a branch-aware CLI token
|
|
111
|
+
|
|
112
|
+
For `remits-cli tool`, the CLI TestMode now stays active for the **entire tool execution**, not just the
|
|
113
|
+
top-level tool lookup. That means nested `reader()`, `action()`, `utility()`, `account.getTool()`, and
|
|
114
|
+
similar component resolution inside the tool also see the staged branch context.
|
|
115
|
+
|
|
116
|
+
`dataMode` is separate from staged resolution:
|
|
117
|
+
|
|
118
|
+
- `branchName` + `cliUserId` decide whether staged components can resolve.
|
|
119
|
+
- `dataMode:test|prod` decides which data surface the tool/test/token runs against.
|
|
120
|
+
|
|
121
|
+
So a `remits-cli tool --data-mode prod` call can intentionally execute **staged code against prod data**
|
|
122
|
+
for investigation or recall testing, while a normal live webhook / non-CLI runtime path with no CLI
|
|
123
|
+
TestMode still uses the committed DB source. Staging remains a dev/verification surface, not a deploy.
|
|
124
|
+
|
|
125
|
+
### Diagnosing which version is in play
|
|
126
|
+
|
|
127
|
+
- **See staging metadata for a component:** `mcp_component_view` (omit `fieldName`) returns `staging` /
|
|
128
|
+
`stagedFields`, telling you whether a staged entry exists and which fields are staged.
|
|
129
|
+
- **Inspect the raw staged entry + TTL in Redis:** use `mcp_cache`.
|
|
130
|
+
```bash
|
|
131
|
+
# find staged entries for one component
|
|
132
|
+
remits-cli tool --name mcp_cache --input '{"action":"scan","pattern":"account:52:cli:*:components:*:reader:id:181","includeValuePreview":true}' --data-mode prod
|
|
133
|
+
# dump one exact key
|
|
134
|
+
remits-cli tool --name mcp_cache --input '{"action":"inspect","key":"account:52:cli:23:components:main:reader:id:181"}' --data-mode prod
|
|
135
|
+
```
|
|
136
|
+
The preview shows `kind`/`type`/`hash`/`updatedAt` + a source snippet — confirm it's your content and
|
|
137
|
+
that `type` is NOT the family (a family value in `type` is a tool bug that crashes hydration, e.g.
|
|
138
|
+
`No enum constant ObjectType.reader`).
|
|
139
|
+
- **Confirm the DB version:** `mcp_component_view` reads the live DB source directly (no staging, no compile
|
|
140
|
+
cache), so it is the source of truth for "what was committed."
|
|
141
|
+
- **Ask the CLI what is staged:** `remits-cli components status` lists this lane's staged entries,
|
|
142
|
+
including staged fields, aliases, hashes, and TTLs. The default terminal output is concise; pass `--json` or
|
|
143
|
+
`--verbose` when you need the full staged-entry payload. `remits-cli components clear` removes those entries
|
|
144
|
+
when you intentionally want to fall back to DB source.
|
|
145
|
+
|
|
146
|
+
### Working alongside other agents: the staging WORKSPACE
|
|
147
|
+
|
|
148
|
+
Staging is scoped by `(account, cli user, branch, workspace)`. Account and user are fixed for a repo, so
|
|
149
|
+
**without a workspace the git branch is the only isolation axis** — and `components stage` uploads the
|
|
150
|
+
ENTIRE repo and REPLACES the lane rather than merging into it. Two agents on one branch therefore
|
|
151
|
+
overwrite each other, and a `components commit` clears the lane out from under the other one.
|
|
152
|
+
|
|
153
|
+
If more than one agent is working on the same branch, give each its own workspace:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
git worktree add ../repo-agent-a forked # one checkout per agent, same branch
|
|
157
|
+
cd ../repo-agent-a
|
|
158
|
+
remits-cli workspace use --auto # names the lane after this directory
|
|
159
|
+
remits-cli components stage # isolated: nobody else sees it, nobody overwrites it
|
|
160
|
+
remits-cli test run --test 42
|
|
161
|
+
remits-cli token --path /page/whatever
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
A workspace narrows STAGING and nothing else. A commit still targets the same branch and the same owner
|
|
165
|
+
account, and the run still resolves whatever committed variant branch the account subscribes to — so it
|
|
166
|
+
does **not** have the side effects of inventing a throwaway git branch per agent (which would make a
|
|
167
|
+
commit write `ComponentVariant` overlays for a branch nobody subscribes to).
|
|
168
|
+
|
|
169
|
+
- `.remits-cli/workspace` is per-checkout and gitignored, so each worktree keeps its own lane.
|
|
170
|
+
- Precedence: `--workspace NAME` > `REMITS_WORKSPACE` > `.remits-cli/workspace` > shared default lane.
|
|
171
|
+
- `--no-workspace` targets the shared lane for one command without clearing the file.
|
|
172
|
+
- Every stage / test run / token / clear prints its `Staging lane:` — if a change seems to have had no
|
|
173
|
+
effect, check that line FIRST. A mismatched lane resolves committed source, which looks identical to
|
|
174
|
+
"the stage did not work".
|
|
175
|
+
- `remits-cli components status` lists every lane staged on the branch, so you can see whether another
|
|
176
|
+
agent is working alongside you.
|
|
177
|
+
- `remits-cli components clear --all` is scoped to YOUR lane and never touches another agent's.
|
|
178
|
+
|
|
179
|
+
### Stage / sync / clear with remits-cli
|
|
180
|
+
|
|
181
|
+
- `remits-cli components stage` writes local file changes into the Redis staging cache for the current
|
|
182
|
+
branch/user/workspace scope. This is the normal edit/test loop.
|
|
183
|
+
- `remits-cli components stage --changed-only` stages just the components this working tree edited. It
|
|
184
|
+
does NOT reconcile, so entries for components it did not mention are left alone rather than deleted.
|
|
185
|
+
Useful on a large repo; a full stage is still the default and the safest.
|
|
186
|
+
- `remits-cli components status` shows which branch/variant world the checkout resolves, plus staged entries,
|
|
187
|
+
staged fields, aliases, hashes, and TTLs. Use `--json` or `--verbose` for the full staged-entry payload.
|
|
188
|
+
- **A full `stage` makes the `.meta.yml` AUTHORITATIVE.** Staging layers a payload over what is already
|
|
189
|
+
staged, which is what lets `mcp_component_edit` write a single field without blanking the others. But a
|
|
190
|
+
`remits-cli components stage` sends the whole sidecar, so a key you DELETE from a sidecar is removed from
|
|
191
|
+
the staged entry rather than lingering — "restore the file and re-stage" restores the staged state, which
|
|
192
|
+
is the only mental model that is safe to have. Content fields still layer (they come from separate files),
|
|
193
|
+
so a partial stage is unaffected.
|
|
194
|
+
- `remits-cli components clear` drops staged entries when you intentionally want to fall back to committed DB
|
|
195
|
+
source. An empty staging scope is clean state, not a failure.
|
|
196
|
+
- `remits-cli components sync` syncs the DB from the pushed git remote and then clears staged entries for the
|
|
197
|
+
synced components, so a clean promotion leaves a clean staging cache. Because sync reconciles the remote repo
|
|
198
|
+
into the live component database, it must pass `component-integrity.md` first. Never use sync only to
|
|
199
|
+
clear staging, to recover from a mismatched ID, or to retry after an unexpected create/delete/rename response.
|
|
200
|
+
|
|
201
|
+
### Stale after sync / commit (the in-memory compile cache)
|
|
202
|
+
|
|
203
|
+
After a `git sync` or a `commit` updates the DB source, a **running instance can keep executing the
|
|
204
|
+
previously-compiled closure** until the version-keyed signature changes and that instance's
|
|
205
|
+
`CLOSURE_CACHE` misses (or the instance recycles). Symptoms: `mcp_component_view` shows the new source, but
|
|
206
|
+
behaviour (or a freshly-staged entry produced by an edited *tool*) still reflects the old code. This is the
|
|
207
|
+
standard Grails no-hot-reload caveat — it is environmental, not a code defect. Verify the live entry/source
|
|
208
|
+
with `mcp_cache` / `mcp_component_view`, and if a platform/tool source change must take effect immediately,
|
|
209
|
+
the platform owner recycles the instance.
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
# The Development Loop
|
|
2
|
+
|
|
3
|
+
> A `remits-cli` skill reference. **Load this when** you are building or changing a component: the edit to stage to verify to commit fast loop, end to end.
|
|
4
|
+
>
|
|
5
|
+
> The table of contents below carries **real line numbers** (`- L84 Some Heading`), resolved when
|
|
6
|
+
> this file is installed, so they are never stale. Read the head, pick your sections, and offset-read
|
|
7
|
+
> only those. The entry text is the heading verbatim, so it also greps.
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
- [Two Workflows](#two-workflows)
|
|
12
|
+
- [Test Mode vs Prod Mode](#test-mode-vs-prod-mode)
|
|
13
|
+
- [Development Workflow](#development-workflow)
|
|
14
|
+
- [The Golden Rule: Writing Code Is Not Finishing the Job](#the-golden-rule-writing-code-is-not-finishing-the-job)
|
|
15
|
+
- [The Development Fast Loop](#the-development-fast-loop)
|
|
16
|
+
- [Step 1: Understand the Request](#step-1-understand-the-request)
|
|
17
|
+
- [Step 2: Make the Change](#step-2-make-the-change)
|
|
18
|
+
- [Step 3: Stage to Platform](#step-3-stage-to-platform)
|
|
19
|
+
- [Step 4: Verify the Change](#step-4-verify-the-change)
|
|
20
|
+
- [Step 5: Iterate If Needed](#step-5-iterate-if-needed)
|
|
21
|
+
- [Step 6: Update Documentation](#step-6-update-documentation)
|
|
22
|
+
- [Temporary Experiment Workflow](#temporary-experiment-workflow)
|
|
23
|
+
- [Step 7: Commit and Durable Sync](#step-7-commit-and-durable-sync)
|
|
24
|
+
- [Step 8: Close the Ticket](#step-8-close-the-ticket)
|
|
25
|
+
- [User Confirmation Preferences](#user-confirmation-preferences)
|
|
26
|
+
|
|
27
|
+
## Two Workflows
|
|
28
|
+
|
|
29
|
+
1. **Development** (test mode) — Build, modify, and verify components using isolated test data.
|
|
30
|
+
2. **Production Support** (prod mode) — Investigate live data, debug issues, trace execution.
|
|
31
|
+
|
|
32
|
+
Every CLI response includes `dataMode` so you always know which context you're in.
|
|
33
|
+
|
|
34
|
+
### Test Mode vs Prod Mode
|
|
35
|
+
|
|
36
|
+
Treat these as two different jobs:
|
|
37
|
+
|
|
38
|
+
- **Prod mode** is for investigation.
|
|
39
|
+
- Read live Firestore documents.
|
|
40
|
+
- Inspect live object activity, events, alerts, and logs.
|
|
41
|
+
- Confirm what actually happened to a customer.
|
|
42
|
+
- Do not use prod mode as your final verification environment for a code fix.
|
|
43
|
+
|
|
44
|
+
- **Test mode** is for verification.
|
|
45
|
+
- Stage local component changes.
|
|
46
|
+
- Run Test components.
|
|
47
|
+
- Generate token URLs and verify behavior in isolated browser flows.
|
|
48
|
+
- Confirm the fix without mutating or depending on live customer processing.
|
|
49
|
+
|
|
50
|
+
The correct support loop is usually:
|
|
51
|
+
1. Investigate in **prod mode**
|
|
52
|
+
2. Identify the responsible implementation repo and make the code change locally
|
|
53
|
+
3. Move back to **test mode** for verification
|
|
54
|
+
4. Verify with a Test component, Playwright/browser confirmation, or both
|
|
55
|
+
|
|
56
|
+
If a production issue needs realistic verification, do **not** copy live customer data from a production account into another account's test collection.
|
|
57
|
+
|
|
58
|
+
The right model is:
|
|
59
|
+
- investigate the source document in **prod mode**
|
|
60
|
+
- model the relevant conditions in a **Test** component
|
|
61
|
+
- or reproduce the scenario through a controlled **test-mode** embeddable/browser flow
|
|
62
|
+
- verify the fix there
|
|
63
|
+
|
|
64
|
+
Never treat "it looks right in prod data inspection" as sufficient proof that a code change is verified.
|
|
65
|
+
|
|
66
|
+
## Development Workflow
|
|
67
|
+
|
|
68
|
+
### The Golden Rule: Writing Code Is Not Finishing the Job
|
|
69
|
+
|
|
70
|
+
**A change is not complete until it is verified.** Writing the component is the first step, not the last.
|
|
71
|
+
Two ways to prove it:
|
|
72
|
+
|
|
73
|
+
1. **A Test component** (preferred) — it exercises the change *and* becomes permanent regression
|
|
74
|
+
protection. Run it with `remits-cli test run`.
|
|
75
|
+
2. **Visual verification** — `remits-cli token` for a browser URL, then drive it with `playwright-cli`.
|
|
76
|
+
This is how most users think about verification: "let me see it working."
|
|
77
|
+
|
|
78
|
+
Use a Test when the behavior can be asserted programmatically, a browser when the change is visual.
|
|
79
|
+
Often both.
|
|
80
|
+
|
|
81
|
+
**Never skip verification.** "Just do it" and "that's fine, commit it" are not evidence. If you genuinely
|
|
82
|
+
cannot verify — no Test component, no relevant embeddable — say what you would need and ask how the user
|
|
83
|
+
wants to proceed rather than reporting the work as done.
|
|
84
|
+
|
|
85
|
+
> The *design* rule that pairs with this — never solve interpretive problems with regex cascades, keyword
|
|
86
|
+
> lists, or layout-specific branching when the platform's AI surface is the right tool — is in the account
|
|
87
|
+
> repo's `CLAUDE.md` and, in depth, in `features/ai-strategy.md`.
|
|
88
|
+
|
|
89
|
+
### The Development Fast Loop
|
|
90
|
+
|
|
91
|
+
This is how every development task should flow:
|
|
92
|
+
|
|
93
|
+
#### Step 1: Understand the Request
|
|
94
|
+
Read the user's request. If you may need a repo other than the current one, read `~/.remits-cli/account-repos.json` first. Then review `account-info.json` and `README.md` to understand what components exist and how they relate. Read the source of any component you'll modify before changing it.
|
|
95
|
+
|
|
96
|
+
**Establish the account's shape too, not just its components.** Read the `resolution` block in
|
|
97
|
+
`account-info.json` (or `mcp_account_view`): the account `type` decides whether this repo is even the right
|
|
98
|
+
place to change code, `resolution.relationships` shows whether the account has more than one parent (and
|
|
99
|
+
which link carries a branch/namespace/host), and `resolvedDatabaseName` tells you where its data actually
|
|
100
|
+
lands. See `account-targeting.md` and `features/account-management.md` (`mcp_get_guide`).
|
|
101
|
+
|
|
102
|
+
**Also establish which world you are working in.** `remits-cli components status` reports whether the
|
|
103
|
+
working tree is a **trunk** checkout or a **variant branch** checkout — which decides both what your test
|
|
104
|
+
runs resolve and what a sync writes. If `account-info.json` carries a `componentBranches` section, branch
|
|
105
|
+
variants of these components exist: editing an origin component will drift them, so check
|
|
106
|
+
`remits-cli components branches` before changing shared code. See `branch-variants.md`.
|
|
107
|
+
|
|
108
|
+
#### Step 2: Make the Change
|
|
109
|
+
Edit component files under `components/`. This is local file editing — the platform doesn't know about your changes yet.
|
|
110
|
+
|
|
111
|
+
**Creating a component that does not exist yet.** Files are named `<id>_<Name>.<ext>`, where the numeric
|
|
112
|
+
prefix is the platform's component id. A new component has no id, so name its files with the **`new_`
|
|
113
|
+
prefix** and let the sync assign one (it then renames the files to that id):
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
components/embeddables/new_MerchantPortal.groovy # source
|
|
117
|
+
components/embeddables/new_MerchantPortal.html # markup
|
|
118
|
+
components/embeddables/new_MerchantPortal.js # client script
|
|
119
|
+
components/embeddables/new_MerchantPortal.meta.yml # metadata sidecar
|
|
120
|
+
components/prompts/new_PricingReviewPrompt.md # standalone Prompt body
|
|
121
|
+
components/prompts/new_PricingReviewPrompt.meta.yml # standalone Prompt metadata
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Do NOT put an `id:` in a new component's sidecar.** `id` is what links a sidecar to an *existing*
|
|
125
|
+
component and is parsed as a number, so a placeholder (`id: new`, `id: TBD`) fails the **entire**
|
|
126
|
+
stage/sync request with a `NumberFormatException` — not just that one file, and the error does not name
|
|
127
|
+
the file. Omit the key; the platform fills it in on sync:
|
|
128
|
+
|
|
129
|
+
```yaml
|
|
130
|
+
# components/embeddables/new_MerchantPortal.meta.yml — no `id:` yet
|
|
131
|
+
name: Merchant Portal
|
|
132
|
+
summary: One-line statement of what this component is for. This is the compact text account-info.json uses first.
|
|
133
|
+
description: |
|
|
134
|
+
Longer technical description with line-number references to the key logic.
|
|
135
|
+
path: /page/merchant-portal # Readers and Embeddables only
|
|
136
|
+
injectionType: DIRECT # Embeddables only: DIRECT or IFRAME
|
|
137
|
+
category: default
|
|
138
|
+
auxiliary: false # `true` means the sync SKIPS the file entirely — see Auxiliary
|
|
139
|
+
mermaid: |
|
|
140
|
+
graph TD
|
|
141
|
+
A[Request] --> B[Load documents]
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
For `components/prompts/new_*.meta.yml`, include `description` and `purpose: CUSTOM`; missing
|
|
145
|
+
`description` fails trunk validation, and missing/mismatched `purpose` leaves a post-promotion Prompt
|
|
146
|
+
overlay instead of pruning cleanly.
|
|
147
|
+
|
|
148
|
+
> **Staging creates nothing in the database, so a `new_` component has no id yet — address it BY NAME.**
|
|
149
|
+
> `remits-cli test run --test "My Suite"`, not `--test <id>`. Component-to-component resolution and
|
|
150
|
+
> request-level addressing are name-based too; the component guides cover those. After a trunk sync the
|
|
151
|
+
> component has a real id and either form works.
|
|
152
|
+
|
|
153
|
+
#### Step 3: Stage to Platform
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
remits-cli components stage
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
This uploads your local file changes to the platform's staging cache (Redis, 240-minute TTL). It does NOT commit anything. The platform cannot see your local edits until you stage them.
|
|
160
|
+
|
|
161
|
+
**THE STAGE-BEFORE-RUN RULE:** You MUST run `remits-cli components stage` after EVERY file edit and BEFORE any test run or verification. The platform executes whatever version is in the staging cache at the moment the test starts. If you edit a file and run a test without staging first, the test runs the OLD code — not your changes. This is the single most common mistake. Never skip staging. The sequence is always: **edit → stage → run**.
|
|
162
|
+
|
|
163
|
+
This applies to:
|
|
164
|
+
- Creating new components (the platform won't find them until staged)
|
|
165
|
+
- Editing existing components (the platform runs the previously staged version until you re-stage)
|
|
166
|
+
- Every iteration of the fix loop — every edit requires a fresh stage before the next test run
|
|
167
|
+
|
|
168
|
+
#### Step 4: Verify the Change
|
|
169
|
+
|
|
170
|
+
**Option A — Run Tests** (if Test components exist for this area):
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
remits-cli test run --test <TEST_ID_OR_NAME>
|
|
174
|
+
remits-cli test run --test "Invoice Tests" --names "specific test case"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
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.
|
|
178
|
+
|
|
179
|
+
Important test-runner constraints:
|
|
180
|
+
- `remits-cli test run` now defaults to `test` dataMode unless you explicitly pass `--data-mode prod`.
|
|
181
|
+
- **`--names` is delimited by `|`, and may be repeated.** A comma still splits a single `--names` value
|
|
182
|
+
(legacy behaviour), which is why a case name containing a comma used to be cut in half and match
|
|
183
|
+
nothing. Prefer `|` or repetition whenever a name might contain punctuation:
|
|
184
|
+
```bash
|
|
185
|
+
remits-cli test run --test 13 --names "a case, with a comma|another case"
|
|
186
|
+
remits-cli test run --test 13 --names "a case, with a comma" --names "another case"
|
|
187
|
+
```
|
|
188
|
+
- **A selector that matches no case FAILS the run.** It used to report `0 passed, 0 failed`,
|
|
189
|
+
`completed`, and exit 0 — indistinguishable from a suite where everything passed. The run now names
|
|
190
|
+
the unmatched selectors and lists the cases the suite actually declared, and exits non-zero.
|
|
191
|
+
|
|
192
|
+
If no relevant Test component exists yet, consider creating one. Test components live in `components/tests/` and follow the same component structure. They provide permanent regression protection — every test you write today saves debugging time tomorrow.
|
|
193
|
+
|
|
194
|
+
New test files use the `new_` prefix (e.g., `new_MyTest.groovy`) and no `id:` in the sidecar — see "Creating a component that does not exist yet" in Step 2. Run them **by name** (`remits-cli test run --test "My Test"`) until a sync assigns an id and renames the file.
|
|
195
|
+
|
|
196
|
+
**How to write the Test itself is not a CLI concern** — what a suite can assert, how mocks behave across HTTP/relay boundaries, driving an embeddable in-process, and the front-stage-only rule all live in `guides/components/test-components.md`. Read that before authoring a suite.
|
|
197
|
+
|
|
198
|
+
**Option B — Visual verification with Playwright** (for UI changes or when the user wants to "see it"):
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# Generate a browser-accessible URL for an embeddable
|
|
202
|
+
remits-cli token --path embeddable/index/<EMBEDDABLE_ID>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
This returns an `embeddableUrl`. Use Playwright to open and interact with it:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
# Open the embeddable in a headed browser
|
|
209
|
+
playwright-cli open --headed "<embeddableUrl>"
|
|
210
|
+
|
|
211
|
+
# Take a snapshot to see the current state
|
|
212
|
+
playwright-cli snapshot
|
|
213
|
+
|
|
214
|
+
# Interact with elements
|
|
215
|
+
playwright-cli click "text=Submit"
|
|
216
|
+
playwright-cli fill "#amount" "500.00"
|
|
217
|
+
|
|
218
|
+
# Verify specific content
|
|
219
|
+
playwright-cli eval "() => document.querySelector('.total-amount').textContent"
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
The `testMode` metadata confirms you're testing against staged changes, not production.
|
|
223
|
+
|
|
224
|
+
**Two different token keys come back, for two different jobs.** When `--path` resolves to an
|
|
225
|
+
Embeddable, the response carries an `embedTokenKey` and a paste-ready `embedSnippet` alongside the usual
|
|
226
|
+
`tokenKey` / `embeddableUrl`:
|
|
227
|
+
|
|
228
|
+
| Field | Use it for |
|
|
229
|
+
|---|---|
|
|
230
|
+
| `tokenKey` / `embeddableUrl` | Opening the page in a browser (Playwright, or clicking the link) |
|
|
231
|
+
| `embedTokenKey` / `embedSnippet` | The `<script>` embed loader — verifying the page as a HOST SITE embeds it |
|
|
232
|
+
|
|
233
|
+
They are not interchangeable. The loader's request carries **no path**, so it resolves the component
|
|
234
|
+
purely from the embeddable-scoped token key's persisted context. The browser `tokenKey` names the account
|
|
235
|
+
preview URL; `embedTokenKey` names the host-loader credential. The response also echoes `injectionType` /
|
|
236
|
+
`renderMode` / `headMode`, which decide what a host actually receives
|
|
237
|
+
(`guides/components/embeddable-components.md`).
|
|
238
|
+
|
|
239
|
+
**This works for a `new_` component that has never been synced.** The embed token key carries the
|
|
240
|
+
component NAME as well as its id, so a staged, id-less Embeddable is loader-addressable — you do not
|
|
241
|
+
have to sync it, or borrow another component's id, just to verify a host embed.
|
|
242
|
+
|
|
243
|
+
**Option C — Use investigation tools** (for backend/data changes):
|
|
244
|
+
|
|
245
|
+
For changes to Readers, Actions, or Rules that process data rather than display UI, verify by examining the data they produce:
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
# After triggering the component (via test or manual action), check the result
|
|
249
|
+
remits-cli tool --name "mcp_firestore_search" --input '{"accountId": <ID>, "collection": "<collection>", "limit": 5, "sort": [{"field": "_lastModifiedAt", "direction": "DESC"}]}'
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
For long-running backend verification, use the Action runner's own async mode (`executionMode:"async"`) and
|
|
253
|
+
poll by `actionRunId` rather than holding a single request open (see `command-reference.md` → *Tool Execution Lifecycle* for why not
|
|
254
|
+
to also stack the CLI `--async` flag):
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
remits-cli tool --name "mcp_run_action" --input '{"accountId": <ID>, "actionId": <ACTION_ID>, "executionMode": "async", "actionInput": {...}}' --data-mode test
|
|
258
|
+
# then poll: {"controlAction":"status","accountId": <ID>, "actionRunId":"<actionRunId>"}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
#### Step 5: Iterate If Needed
|
|
262
|
+
|
|
263
|
+
If verification reveals issues, repeat the loop: **edit → stage → run**. Every iteration must include a fresh `remits-cli components stage` after your edits and before the next test run. Never run a test immediately after editing without staging first — the platform will execute the previous version, not your latest changes.
|
|
264
|
+
|
|
265
|
+
Don't ask the user for permission to re-iterate — just do it. Only stop to ask if you're stuck or unsure about the intended behavior.
|
|
266
|
+
|
|
267
|
+
If the work is tied to a support ticket:
|
|
268
|
+
- Use `remits-cli ticket status --status in_progress` once you have started substantive work.
|
|
269
|
+
- If a new reply arrives, re-read the ticket and incorporate the reply into your current plan.
|
|
270
|
+
|
|
271
|
+
#### Step 6: Update Documentation
|
|
272
|
+
|
|
273
|
+
Before committing, update metadata so the next session understands what changed:
|
|
274
|
+
|
|
275
|
+
1. **`.meta.yml` sidecars** — Update `summary`, `description`, and `mermaid` for each modified component. `summary` is what drives the compact component description in generated `account-info.json`; `description` is the fallback when no summary is set and is capped in that file.
|
|
276
|
+
2. **`README.md`** — If the change affects account-level capabilities or workflows.
|
|
277
|
+
3. **New components** — Always fill in `.meta.yml` immediately.
|
|
278
|
+
|
|
279
|
+
`account-info.json` is read-only — never edit it. It regenerates automatically after sync. Component
|
|
280
|
+
entries prefer `summary`, fall back to capped `description`, and cap `mermaid`; relationships remain as
|
|
281
|
+
generated. On a trunk sync it describes the owning repo account. On a subscriber-initiated variant sync it
|
|
282
|
+
describes the subscribing account reached through the branch edge, even though the component files still
|
|
283
|
+
belong to the owner's repo.
|
|
284
|
+
|
|
285
|
+
#### Temporary Experiment Workflow
|
|
286
|
+
|
|
287
|
+
Use this when you need to prove a guard or assertion by temporarily making a local component fail. The staged
|
|
288
|
+
Redis cache can affect later test/tool runs, so always clear it after restoring the file:
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
# make temporary local edit
|
|
292
|
+
remits-cli components stage
|
|
293
|
+
remits-cli test run --test <id-or-name> --names "<case name>"
|
|
294
|
+
git restore <file>
|
|
295
|
+
remits-cli components clear --all
|
|
296
|
+
remits-cli components status
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
For narrower cleanup when only one staged component should be cleared:
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
remits-cli components clear --component-type Action --component-id 25
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
#### Step 7: Commit and Durable Sync
|
|
306
|
+
|
|
307
|
+
Once verified and documented, create a normal git commit first:
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
git add -A
|
|
311
|
+
git commit -m "description of what changed and why"
|
|
312
|
+
git push origin <branch>
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
This separates the local failure boundaries cleanly:
|
|
316
|
+
1. Local git commit
|
|
317
|
+
2. Remote push
|
|
318
|
+
|
|
319
|
+
After the push, run the **`component-integrity.md`** safety checks before any durable platform sync. Do not run
|
|
320
|
+
`remits-cli components sync` when local files, `account-info.json`, and live inventory disagree about component
|
|
321
|
+
IDs or when unexpected deletes/renumbers are present.
|
|
322
|
+
|
|
323
|
+
Only after those checks pass, and only when the user intends to promote the repo to the platform database:
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
remits-cli components sync
|
|
327
|
+
git pull --ff-only origin <branch>
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
`remits-cli components sync` is the authoritative platform-sync step. It does not perform local git operations,
|
|
331
|
+
and it is capable of reconciling creates/deletes/renames from the remote repository into the database. Treat it
|
|
332
|
+
as a gated promote/reconciliation command, not as an exploratory command or fallback.
|
|
333
|
+
|
|
334
|
+
The CLI now returns the post-sync branch SHA from the platform and verifies that your `git fetch` and final `git pull --ff-only` land on that exact commit. If that SHA does not match `origin/<branch>` or local `HEAD`, stop immediately and investigate the race or branch drift instead of guessing.
|
|
335
|
+
|
|
336
|
+
`remits-cli components commit` still exists as a convenience wrapper, but agents should not call unsupported
|
|
337
|
+
subcommand help variants such as `remits-cli components commit --help` to discover behavior. Consult the `remits-cli` skill and its references,
|
|
338
|
+
the CLI source, or `remits-cli components` documentation instead. If an exploratory or commit command behaves
|
|
339
|
+
unexpectedly, stop and inspect the repo-local session log before running any mutating follow-up command.
|
|
340
|
+
|
|
341
|
+
**Git is required for durable sync.** The platform syncs by pulling from the git remote (`GitHubClient.syncFromRepository`). If `git push` fails, the server has nothing new to sync. You can still **stage** and **test** without git — only durable sync requires it.
|
|
342
|
+
|
|
343
|
+
#### Step 8: Close the Ticket
|
|
344
|
+
|
|
345
|
+
If the request came from a support ticket, the task is not complete until you update the ticket lifecycle yourself:
|
|
346
|
+
|
|
347
|
+
1. Re-read the ticket if needed to confirm the latest state and replies.
|
|
348
|
+
2. If the work is done and verified, call `remits-cli ticket complete` and include a concise resolution summary.
|
|
349
|
+
3. If you cannot finish, use `remits-cli ticket status` or `remits-cli ticket release` with clear notes so the next agent can continue.
|
|
350
|
+
4. Do this automatically. The human user should not need to instruct you to update the ticket.
|
|
351
|
+
|
|
352
|
+
Options:
|
|
353
|
+
```bash
|
|
354
|
+
--message "commit msg" # Commit message (default: auto-generated timestamp)
|
|
355
|
+
--allow-empty true # Allow empty git commits
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### User Confirmation Preferences
|
|
359
|
+
|
|
360
|
+
Some users want to review every change before staging. Others want you to move fast and only stop if something breaks. **Pay attention to how the user communicates:**
|
|
361
|
+
|
|
362
|
+
- If they say "just fix it" or "go ahead" — move through the loop without asking for confirmation at each step. Stage, verify, commit.
|
|
363
|
+
- If they say "show me first" or "wait before committing" — pause at the appropriate step.
|
|
364
|
+
- If they say "you don't need to ask me" or "stop asking" — remember this preference and work autonomously through the full loop.
|
|
365
|
+
|
|
366
|
+
The default should be: make the change, stage it, verify it, and present the results. Only block on the user when you're genuinely unsure about intent.
|