@remits/remits-cli 0.1.167 → 0.1.169
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 +1 -0
- package/index.js +628 -28
- package/lib/local-ai.js +2 -2
- package/package.json +1 -1
- package/skills/remits-cli/SKILL.md +3 -0
- package/skills/remits-cli/references/agent-sessions.md +32 -6
- package/skills/remits-cli/references/command-reference.md +20 -4
- package/skills/remits-cli/references/development-loop.md +8 -0
- package/skills/remits-cli/references/investigation.md +21 -0
- package/skills/remits-cli/references/support-tickets.md +42 -9
- package/skills/remits-cli/references/tool-reference.md +31 -1
package/lib/local-ai.js
CHANGED
|
@@ -525,7 +525,7 @@ function help() {
|
|
|
525
525
|
console.log('Decisions: {"content":"reply","toolCalls":[]} or {"content":null,"toolCalls":[{"name":"tool","arguments":{}}]}');
|
|
526
526
|
}
|
|
527
527
|
|
|
528
|
-
async function command({ subcommand, flags, context, root, axios, Client, WebSocket, defaultAgent = 'claude' }) {
|
|
528
|
+
async function command({ subcommand, flags, context, root, axios, Client, WebSocket, defaultAgent = 'claude', requestHeaders }) {
|
|
529
529
|
if (!subcommand || flags.help || subcommand === 'help') return help();
|
|
530
530
|
if (!['serve', 'workers', 'work', 'request', 'respond', 'status', 'sessions', 'release'].includes(subcommand)) throw new Error('Unknown ai subcommand');
|
|
531
531
|
const agent = flags.agent || defaultAgent;
|
|
@@ -545,7 +545,7 @@ async function command({ subcommand, flags, context, root, axios, Client, WebSoc
|
|
|
545
545
|
try {
|
|
546
546
|
const result = await axios.post(baseUrl.replace(/\/+$/, '') + '/cli/ai',
|
|
547
547
|
{ ...payload, command: action, workerId: worker.workerId, accountId, dataMode },
|
|
548
|
-
{ headers: { Authorization: 'Bearer ' + session.token }, timeout: 15000, maxContentLength: MAX_BYTES, maxBodyLength: MAX_BYTES });
|
|
548
|
+
{ headers: requestHeaders ? requestHeaders(session.token) : { Authorization: 'Bearer ' + session.token }, timeout: 15000, maxContentLength: MAX_BYTES, maxBodyLength: MAX_BYTES });
|
|
549
549
|
if (!result.data?.success) throw new Error(result.data?.message || 'Local AI command failed');
|
|
550
550
|
return result.data;
|
|
551
551
|
} catch (error) {
|
package/package.json
CHANGED
|
@@ -64,6 +64,9 @@ reference named after it.
|
|
|
64
64
|
- **edit → stage → run, every time.** The platform executes whatever is in the staging cache at the
|
|
65
65
|
moment a run starts. Edit a file, run a test without `remits-cli components stage`, and the test runs
|
|
66
66
|
the OLD code. This is the single most common mistake. (`development-loop.md`)
|
|
67
|
+
- **Iterate on the failing cases; run the whole suite once before landing.** Waiting on test runs is most
|
|
68
|
+
of a slow build loop, not staging. After each edit run `test run --test X --failed` (only what did not
|
|
69
|
+
pass last time) or `--names "a|b"`, not the full suite. (`development-loop.md`)
|
|
67
70
|
- **Staging and sync fail early on broken runtime-compiled Groovy.** Stage validates changed source in the
|
|
68
71
|
active lane; sync validates changed/new compiled components before writing DB rows or branch variants.
|
|
69
72
|
Agent files are Utility components internally. A stage refused BY COMPILE VALIDATION still wrote the
|
|
@@ -100,15 +100,41 @@ whole point is that it needs no supervision. Following the transcript is the way
|
|
|
100
100
|
strictly better than a terminal would be: the output is structured, so it can be read as events
|
|
101
101
|
rather than scraped back out of ANSI text.
|
|
102
102
|
|
|
103
|
-
**
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
**Whether a worker lands is the account's choice, not the supervisor's.** Nothing in the supervisor runs
|
|
104
|
+
git. The brief states the account's landing profile: by default a person lands (the worker leaves changes in
|
|
105
|
+
the working tree and says so on the ticket); an account with `supportPolicy.landing: agent` lets the worker
|
|
106
|
+
land with `remits-cli components commit`, which re-checks the account's rules when it runs.
|
|
107
|
+
|
|
108
|
+
**Each worker gets its own credential.** For every child the supervisor mints a credential bound to that
|
|
109
|
+
attempt (agent + ticket + run) and revokes it when the child exits; the child authenticates with it
|
|
110
|
+
(`REMITS_AGENT_TOKEN`). The platform therefore knows which participant is calling from the credential, so a
|
|
111
|
+
missing or wrong identity header cannot make a worker a human or another agent. Against an older platform
|
|
112
|
+
the worker simply uses the supervisor's session, as before. Each poll also reports, per running child, when
|
|
113
|
+
it last produced output and its last progress line — separate from the supervisor's own heartbeat, so
|
|
114
|
+
`agent map` can tell a connected supervisor from a child that is actually producing work.
|
|
106
115
|
|
|
107
116
|
### Resolving which agent a command means
|
|
108
117
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
118
|
+
For agent lifecycle commands, explicit `--agent-id` or `REMITS_AGENT_ID` wins; otherwise the CLI looks
|
|
119
|
+
for the registration anchored to this terminal's owning process. It never borrows another terminal's
|
|
120
|
+
registration just because it shares the checkout.
|
|
121
|
+
|
|
122
|
+
For platform request attribution, set `REMITS_AGENT_ID` for the agent's shell or pass `--agent-id` on
|
|
123
|
+
each command. Both reach the shared HTTP client, including status, tools and local-AI requests.
|
|
124
|
+
Supervised ticket workers receive `REMITS_AGENT_ID`, `REMITS_WORKER_RUN_ID` and
|
|
125
|
+
`REMITS_SUPPORT_TICKET_ID` automatically. A manually named interactive agent does not need to register
|
|
126
|
+
for ticket routing just to declare its identity. Registered roles and labels are accepted only from a
|
|
127
|
+
registration owned by the authenticated user. `--local-agent` / `REMITS_LOCAL_AGENT_ID` remains a local
|
|
128
|
+
folder choice and does not declare platform agent identity.
|
|
129
|
+
|
|
130
|
+
System → Activity groups these requests under the authenticated user, with separate agent/run sessions
|
|
131
|
+
and source filters. Undeclared CLI requests are labeled **CLI · no declared agent**, never assumed to be
|
|
132
|
+
human. Browser sessions can also be automated. Only platform requests are observed, not local editing
|
|
133
|
+
or reasoning between commands. Creating a preview token does not mark every subsequent browser user
|
|
134
|
+
of that token as an agent.
|
|
135
|
+
|
|
136
|
+
`ticket route --agent <target>` names the destination. Its legacy `--agent-id` alias also names the
|
|
137
|
+
destination, not the caller; use `REMITS_AGENT_ID` to identify the agent making a routing request.
|
|
112
138
|
|
|
113
139
|
### Which agent gets a ticket
|
|
114
140
|
|
|
@@ -218,13 +218,21 @@ remits-cli agent register [--label NAME] [--data-mode test|prod] [--account-id I
|
|
|
218
218
|
remits-cli agent work [--wait SECONDS] [--json]
|
|
219
219
|
remits-cli agent status [--state idle|working|paused] [--ticket ID] [--activity "..."] [--step "..."]
|
|
220
220
|
remits-cli agent list [--account-id ID] [--json]
|
|
221
|
-
remits-cli agent map [--account-ids 1,4] [--json] # who is EDITING which repository, from which checkout/branch/staging lane
|
|
221
|
+
remits-cli agent map [--account-ids 1,4] [--json] # who is EDITING which repository, from which checkout/branch/staging lane; first line = live work vs stored (staged/last-reported) facts
|
|
222
|
+
remits-cli capabilities [--json] # collaboration features this platform supports, verbs + how they settle, refusal codes
|
|
223
|
+
remits-cli policy explain --point commit|land|stage|complete|deliver|... [--as human|agent] [--workstream W] [--components type:name[:category],...] [--json] # what the account rules would decide, and why; nothing applied
|
|
224
|
+
remits-cli evidence [--limit N] [--json] | evidence flush # your world-stamped trail; inside a ticket attempt it is also published to the ticket as receipts
|
|
222
225
|
remits-cli agent inspect [--account-id ID] [--scope self|children] [--user-id ID|--user-email EMAIL] [--limit N] [--json]
|
|
223
226
|
remits-cli activity inspect [--account-id ID] [--scope self|children|related] [--workspace NAME] [--branch NAME] [--workstream ID] [--user-id ID|--user-email EMAIL] [--limit N] [--json]
|
|
224
227
|
remits-cli workstream status [--workstream ID|--workspace NAME] [--json]
|
|
225
228
|
remits-cli agent release
|
|
226
|
-
remits-cli ticket read|accept|status|progress|complete|release|reopen|assign|planning --ticket ID [--status S] [--resolution "..."] [--summary "..."] [--category C] [--assignee EMAIL] [--workstream VALUE] [--planned-in VALUE] [--board-stage VALUE] [--rank N] [--size VALUE] [--blocked-by VALUE] [--notes "..."]
|
|
227
|
-
remits-cli ticket
|
|
229
|
+
remits-cli ticket read|accept|status|progress|complete|cancel|release|reopen|assign|planning --ticket ID [--status S] [--resolution "..."] [--reason "..."] [--summary "..."] [--category C] [--assignee EMAIL] [--workstream VALUE] [--planned-in VALUE] [--board-stage VALUE] [--rank N] [--size VALUE] [--blocked-by VALUE] [--notes "..."]
|
|
230
|
+
remits-cli ticket cancel --ticket ID --reason "..." [--expected-revision N] # close with disposition cancelled; history kept; stops worker
|
|
231
|
+
remits-cli ticket reset-budget --ticket ID # OPERATOR: restore run and spend budget after review
|
|
232
|
+
remits-cli ticket redeliver-events --ticket ID # OPERATOR: re-dispatch undelivered lifecycle events
|
|
233
|
+
remits-cli ticket lease|unlease|force-unlease --ticket ID [--reason "..."] # force-unlease breaks SOMEBODY ELSE'S lease; operator only. 503 code=unavailable = holder unknown: investigate, retry
|
|
234
|
+
remits-cli ticket handoff --ticket ID --summary "..." [--next-step "..."] [--findings "a|b"] [--artifact-refs a,b] [--evidence-refs r1,r2] [--waiting-on X] [--needs cap] [--workstream W] [--exclude] [--expected-revision N]
|
|
235
|
+
remits-cli ticket decide|complete ... [--expected-revision N] # refused with code=stale_revision (nothing written) if the ticket moved past N
|
|
228
236
|
remits-cli ticket where --ticket ID # WHERE this work is: repo account, checkout, branch, staging lane, live lease + holder's location, claim, your phase
|
|
229
237
|
remits-cli ticket ask --ticket ID --question "..." [--context "..."] [--to WHO] # park on a human decision
|
|
230
238
|
remits-cli ticket answer --ticket ID --message "..." [--route false] # answer it (alias: reply); re-routes by default
|
|
@@ -265,7 +273,7 @@ remits-cli components branch <name> --copy-to <newBranch> [--dry-run] [--force]
|
|
|
265
273
|
remits-cli components branch <name> --subscribe <accountId> [--parent-account <id>] [--domain <host>] [--dry-run] [--confirm-primary-edge] # make an account resolve this branch
|
|
266
274
|
remits-cli components branch <name> --unsubscribe <accountId> # return that account to trunk
|
|
267
275
|
remits-cli components branch <name> --retire [--force] # delete the branch's overlays
|
|
268
|
-
remits-cli test run --test <id|name> [--branch <stagingScope>] [--names "a|b"] [--watch true|false] [--wait true|false] [--data-mode test|prod] [--as-account <ID>] [--variant-branch <name|none>] [--label <text>] [--param name=value ...] [--repeat N] [--parallel N] [--json]
|
|
276
|
+
remits-cli test run --test <id|name> [--candidate <laneContentHash>] [--branch <stagingScope>] [--names "a|b" | --failed] [--watch true|false] [--wait true|false] [--data-mode test|prod] [--as-account <ID>] [--variant-branch <name|none>] [--label <text>] [--param name=value ...] [--repeat N] [--parallel N] [--json]
|
|
269
277
|
remits-cli test status --task-id <taskId|groupId> [--branch <stagingScope>] [--data-mode test|prod] [--json] # falls back to the DURABLE run record once the live status expires
|
|
270
278
|
remits-cli test runs [--test <id|name>] [--limit 20] [--compare] [--all-lanes] [--as-account <ID>] [--json] # durable run history: pass counts, live AI cost, lane, content hash
|
|
271
279
|
remits-cli test compare --base <taskId> --head <taskId> [--json] # per-case improved / regressed / changed, cost and world deltas
|
|
@@ -281,6 +289,10 @@ remits-cli corpus consistency --corpus <name> --case <caseKey> [--json]
|
|
|
281
289
|
remits-cli corpus retire --corpus <name> --case <caseKey> [--case ...] [--restore] [--json] # drop a case from future runs; past measurements stay readable
|
|
282
290
|
```
|
|
283
291
|
|
|
292
|
+
`--candidate <hash>` names the staged content you mean to test (the lane content hash `components status`
|
|
293
|
+
reports); if another process restaged or the lane expired, the run is refused with `stale_revision` instead of
|
|
294
|
+
testing different source. It binds the start of the run, not every later lookup.
|
|
295
|
+
|
|
284
296
|
`test run` starts a server-side task immediately. By default the CLI process polls until the task is
|
|
285
297
|
terminal; `--watch false` disables websocket progress streaming but still waits. Pass `--wait false` to
|
|
286
298
|
return after launch with the task id. A single run with `--names "a|b|c"` selects cases into one suite task,
|
|
@@ -589,6 +601,10 @@ For tests specifically:
|
|
|
589
601
|
- `--names` is `|`-delimited and may be repeated. A selector containing commas matches a case with that
|
|
590
602
|
exact name first, else its comma-separated parts; an unmatched selector fails the run instead of
|
|
591
603
|
reporting zero cases as success.
|
|
604
|
+
- `--failed` re-runs only the cases that did not pass in YOUR last finished run of the suite on this git
|
|
605
|
+
branch and staging workspace (a `--parallel` run is read as its whole group; the launch lane is preferred,
|
|
606
|
+
else the lane the suite recorded in). The launch prints the run it read and the cases. "Nothing failed"
|
|
607
|
+
starts nothing and exits 0; no earlier run is refused. Not combinable with `--names`.
|
|
592
608
|
- `--as-account <ID>` runs AS a descendant subscriber so its edge selects the component branch
|
|
593
609
|
(*"what does customer X get?"*); `--variant-branch <name>` probes a branch from any checkout
|
|
594
610
|
(*"what does branch Y look like?"*), and `--variant-branch none` forces production/subscription semantics.
|
|
@@ -421,9 +421,17 @@ This applies to:
|
|
|
421
421
|
```bash
|
|
422
422
|
remits-cli test run --test <TEST_ID_OR_NAME>
|
|
423
423
|
remits-cli test run --test "Invoice Tests" --names "specific test case"
|
|
424
|
+
remits-cli test run --test "Invoice Tests" --failed
|
|
424
425
|
remits-cli test status --task-id <TASK_ID>
|
|
425
426
|
```
|
|
426
427
|
|
|
428
|
+
**Iterate narrowly, and run the whole suite once before landing.** Waiting on test runs is most of
|
|
429
|
+
an hour-long build loop, not staging. A suite whose cases run one after another re-pays every case's
|
|
430
|
+
fixture work on every rerun. Run the suite once to see what fails. After each edit, run `--failed` (the
|
|
431
|
+
cases that did not pass in your last finished run of this suite, on this git branch and staging
|
|
432
|
+
workspace) or `--names` for the cases your change touches. Then run the full suite once before landing.
|
|
433
|
+
A full rerun after every edit, with every case passing, is the most common way an agent spends an hour.
|
|
434
|
+
|
|
427
435
|
Tests run on the platform against your staged snapshot. They stream results in real-time. **Read the
|
|
428
436
|
`World:` block printed before the run** — host, execution account, data lane, component world, staging lane
|
|
429
437
|
id + content hash, platform sync vs local HEAD. If it is not the world you meant, stop: the result will be
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
- [Investigation Strategy](#investigation-strategy)
|
|
21
21
|
- [Presenting Findings](#presenting-findings)
|
|
22
22
|
- [Verifying a Production Issue Fix](#verifying-a-production-issue-fix)
|
|
23
|
+
- [Missing or deleted business documents](#missing-or-deleted-business-documents)
|
|
23
24
|
|
|
24
25
|
## The Investigation Model
|
|
25
26
|
|
|
@@ -281,3 +282,23 @@ When a bug is reported from production, use this pattern:
|
|
|
281
282
|
6. If useful, create or update a dedicated embeddable "playground" in test mode to reproduce the scenario in a controlled way.
|
|
282
283
|
|
|
283
284
|
Do not move production customer data into another account's test collection as a routine verification strategy. If you cannot verify with a Test component, Playwright flow, or controlled test-mode embeddable, explain the gap clearly instead of improvising with live production validation.
|
|
285
|
+
|
|
286
|
+
## Missing or deleted business documents
|
|
287
|
+
|
|
288
|
+
`PROCESSED` is the MySQL object's processing outcome, not a guarantee that its Firestore document
|
|
289
|
+
still exists. Read `documentEvidence` from `mcp_object_activity` or a current object `mcp_record_view`:
|
|
290
|
+
it includes the resolved path, observed data lane, presence, recent revision metadata, and the latest
|
|
291
|
+
Object `Document Delete` receipt when available. `state` is `present`, `missing`, `deleted`, `unknown`
|
|
292
|
+
(read failed), or `out_of_scope`. `deleted` requires retained deletion evidence; absence alone is not proof.
|
|
293
|
+
A `laneMismatch` means the requested read lane differs from the object's persisted lane.
|
|
294
|
+
|
|
295
|
+
`Document Delete` ObjectLog entries expose structured `documentOperation` (outcome, document path,
|
|
296
|
+
user/agent, component/action, node, data lane, scope, run and trace ids). The operation's
|
|
297
|
+
`threadGroupingId` can differ from `request.traceId`; both are retained for correlation. Failed deletes
|
|
298
|
+
never generate success revisions or downstream deletion messages. The processing status remains intact.
|
|
299
|
+
|
|
300
|
+
To read retained history without a live parent document, call `mcp_firestore_search` with one
|
|
301
|
+
`targetAccountId`, `collection`, `documentId`, and `includeHistory: true`. Use `historyLimit` (default 10,
|
|
302
|
+
maximum 100), `includeRevisionSnapshots: true` for the pre-delete business snapshot, or `revisionId`
|
|
303
|
+
for one exact revision. History is explicitly truncated when more rows exist. Legacy revisions may
|
|
304
|
+
identify the user and time without the newer component/request provenance; do not invent missing facts.
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
- [Moving a ticket through its lifecycle](#moving-a-ticket-through-its-lifecycle)
|
|
27
27
|
- [When a worker needs a decision from a human](#when-a-worker-needs-a-decision-from-a-human)
|
|
28
28
|
- [Approvals, reviews and handing work on](#approvals-reviews-and-handing-work-on)
|
|
29
|
+
- [Coming back later, waiting on other tickets, and cost](#coming-back-later-waiting-on-other-tickets-and-cost)
|
|
29
30
|
|
|
30
31
|
## Support Ticket Mental Model
|
|
31
32
|
|
|
@@ -346,19 +347,26 @@ discouraged.
|
|
|
346
347
|
- **A refusal is an ANSWER.** The message names the rule and says what to do instead. Act on that
|
|
347
348
|
sentence. Do not retry the identical call, and do not go looking for another door — the rules govern the
|
|
348
349
|
DSL, the MCP tools and this CLI identically.
|
|
349
|
-
- **`[require]` rules mean a human.** You cannot acknowledge one
|
|
350
|
-
|
|
351
|
-
`ticket progress` and hand off.
|
|
350
|
+
- **`[require]` rules mean a human.** You cannot acknowledge one. A supervised worker authenticates with a
|
|
351
|
+
credential bound to its own attempt, so the platform knows it is an agent from the credential itself —
|
|
352
|
+
omitting identity headers does not change that. Record what you found with `ticket progress` and hand off.
|
|
352
353
|
- **`[warn]` rules let the call through and write a `policy` worklog entry.** Mention it in your handoff.
|
|
353
354
|
- **Rules can name your role** (`"when":{"role":"triage"}`, or `"role":{"not":["release_manager"]}` for
|
|
354
355
|
"only release managers"). Your role is the one your session registered with; you cannot change it from a
|
|
355
356
|
worker, and passing one on a call does nothing. A refusal naming your role means hand off to the role that
|
|
356
357
|
may.
|
|
357
|
-
- **If you see
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
358
|
+
- **If you see a policy problem banner**, part of the account's rules could not be parsed. The rules listed
|
|
359
|
+
under it are still enforced (a broken replacement keeps its last valid version); do not read the absence
|
|
360
|
+
of a refusal as permission for the rest — say so on the ticket. **`policy_unavailable`** means a published
|
|
361
|
+
policy could not be read at all: landing, committing, completing and sending are refused until it can be.
|
|
362
|
+
Retry later; do not look for another door.
|
|
363
|
+
- **Check before you act**: `remits-cli policy explain --point commit --as agent` says what the rules would
|
|
364
|
+
decide and which rules apply, without applying anything.
|
|
365
|
+
|
|
366
|
+
The same rules govern `components stage` and `components commit`. Whether you may land at all is the
|
|
367
|
+
account's **landing profile**, stated in your brief: by default a person lands (leave changes in the working
|
|
368
|
+
tree and describe them); an account that sets `supportPolicy.landing: agent` lets you land with
|
|
369
|
+
`remits-cli components commit`, which re-checks the rules when it runs. A `no-commit` rule always wins.
|
|
362
370
|
|
|
363
371
|
### Roles and who may launch them
|
|
364
372
|
|
|
@@ -432,6 +440,7 @@ remits-cli ticket accept --ticket 22454 # claim it before changing anyt
|
|
|
432
440
|
remits-cli ticket progress --ticket 22454 --summary "Traced it to the posting Action" --category investigation
|
|
433
441
|
remits-cli ticket status --ticket 22454 --status in_progress
|
|
434
442
|
remits-cli ticket complete --ticket 22454 --resolution "What you found and did"
|
|
443
|
+
remits-cli ticket cancel --ticket 22454 --reason "Customer withdrew request" # outcome no longer wanted; stops running worker
|
|
435
444
|
remits-cli ticket ask --ticket 22454 --question "Re-issue or skip?" --context "412 affected"
|
|
436
445
|
remits-cli ticket answer --ticket 22454 --message "Skip them." # alias: reply
|
|
437
446
|
remits-cli ticket message --ticket 22454 --message "We reproduced it; a fix is staged."
|
|
@@ -589,9 +598,33 @@ remits-cli ticket handoff --summary "fix staged in ticket-19463; needs independe
|
|
|
589
598
|
```
|
|
590
599
|
|
|
591
600
|
The handoff is queued even if nobody is online, `--exclude` keeps you off it (independent review needs
|
|
592
|
-
that), and your own exit will not undo it.
|
|
601
|
+
that), and your own exit will not undo it. It is a checkpoint: `--findings`, `--next-step`,
|
|
602
|
+
`--artifact-refs`, `--evidence-refs`, `--waiting-on` and `--needs` land in the next worker's brief, so give
|
|
603
|
+
durable references (artifact ids, receipt ids), never local paths. Add `--expected-revision N` (the revision
|
|
604
|
+
you read) to `handoff`, `decide` or `complete` and a ticket that moved on is refused with `stale_revision`
|
|
605
|
+
instead of being overwritten. Your evidence trail is published to the ticket as receipts automatically;
|
|
606
|
+
`remits-cli evidence flush` sends anything still queued. A reviewer decides with `ticket decide --request R3 --decision
|
|
593
607
|
approve|changes|reject --revision <rev>`; "changes" sends the work back with the reviewer's note.
|
|
594
608
|
|
|
609
|
+
An approval or review can need several people: `request-approval ... --min-approvals 2` stays open until two
|
|
610
|
+
different eligible deciders approve; one rejection settles it.
|
|
611
|
+
|
|
612
|
+
### Coming back later, waiting on other tickets, and cost
|
|
613
|
+
|
|
614
|
+
```bash
|
|
615
|
+
remits-cli ticket wake --in 1440 --reason "requester promised logs tomorrow" # or --at <ISO time>; --cancel
|
|
616
|
+
remits-cli ticket depends-on --tickets 19463,19470 # no value clears
|
|
617
|
+
remits-cli ticket cost --usd 1.25 # usually reported for you
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
- **`wake` instead of waiting.** Never sleep or poll inside a run. Record what you are waiting for, set a
|
|
621
|
+
wake-up, and finish the run; when the time comes a fresh worker gets the ticket with `resumed for: timer`
|
|
622
|
+
and your reason in its brief.
|
|
623
|
+
- **`depends-on`** when this ticket genuinely cannot start until others are resolved. The sweep holds it
|
|
624
|
+
until they are; nothing else has to remember to release it.
|
|
625
|
+
- **Cost** is reported automatically by `agent serve` from each worker's transcript. An account can cap a
|
|
626
|
+
ticket's spend; when it is reached, starts are refused until a person resets the budget.
|
|
627
|
+
|
|
595
628
|
**`mcp_support_ticket` is an account convention, not a platform guarantee.** It belongs to one
|
|
596
629
|
particular System Account: it may not exist on the platform you are on, it scopes to its own
|
|
597
630
|
account, and it will refuse a ticket owned by a different one. Use it only when you are working in
|
|
@@ -141,6 +141,29 @@ The account-graph and user surface: the middle ground between `account-info.json
|
|
|
141
141
|
compactly, because it is read into your context every session) and `mcp_account_view` (everything about one
|
|
142
142
|
account).
|
|
143
143
|
|
|
144
|
+
**Recurring schedules:** `action_schedules` lists the target account's Action schedules;
|
|
145
|
+
`action_schedule_update` upserts by `targetAccountId` + `actionId` (or an account-scoped `scheduleId`);
|
|
146
|
+
`action_schedule_delete` removes that schedule and its cloud job. Updates accept `cron`, `timeZone`,
|
|
147
|
+
`enabled` and `dryRun`. Each run executes as the schedule's owner (`ownerUserId` in reads), who defaults to
|
|
148
|
+
whoever first saves it and is rechecked at every run. `enabled:false` pauses; `enabled:true` resumes while preserving omitted settings.
|
|
149
|
+
`regression_schedule` reads the per-account regression settings and latest report;
|
|
150
|
+
`regression_schedule_update` accepts the same scheduling fields plus `resultAction`, `suiteConcurrency`
|
|
151
|
+
(1–16) and explicit `ownerUserId`. Existing owners are preserved. Only admins may assign another owner;
|
|
152
|
+
an eligible caller may take ownership themselves.
|
|
153
|
+
|
|
154
|
+
Both use five-field cron and IANA time zones, default UTC. Existing Action schedules retain UTC.
|
|
155
|
+
All writes require production mode; `dryRun:true` validates from either lane without writing or creating
|
|
156
|
+
a cloud job. Action jobs resolve committed enabled `job:true` Actions on the target account; regression
|
|
157
|
+
suites run committed source in test data. Optional `includeSchedulerStatus:true` on reads reports cloud
|
|
158
|
+
registration/next delivery/last transport status; this does not prove Action or regression success.
|
|
159
|
+
An empty regression update does not repair registration: explicitly pass cron/timeZone/enabled.
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
remits-cli tool --name mcp_account_user_admin --data-mode test --input '{"action":"action_schedule_update","targetAccountId":4655,"actionId":21,"cron":"0 1 * * *","timeZone":"America/New_York","enabled":true,"dryRun":true}'
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Inspect the preview, then omit `dryRun` and use `--data-mode prod` when authorized to save the schedule.
|
|
166
|
+
|
|
144
167
|
- `action: 'hierarchy'` (default) — the descendant tree trimmed to `depth` (1-10, default 2; nodes cut off
|
|
145
168
|
are marked `truncated` and still report their child count) and/or the anchored ancestor chain plus every
|
|
146
169
|
edge (`direction: 'down'|'up'|'both'`). Nodes include `testAccount`. **This is how you get the deep tree
|
|
@@ -299,6 +322,11 @@ evidence at all, is in `investigation.md` → *HTTP audits*.
|
|
|
299
322
|
remits-cli tool --name "mcp_firestore_search" --input '{"accountId": 37, "collection": "http-audits/http-audits-2026-05/entries", "filters": [{"field": "direction", "operation": "EQUALS", "value": "OUTBOUND"}, {"field": "request.path", "operation": "EQUALS", "value": "/api/orders"}, {"field": "success", "operation": "EQUALS", "value": false}], "sort": [{"field": "timestamp", "direction": "DESC"}], "pagination": {"limit": 10}}' --data-mode prod
|
|
300
323
|
```
|
|
301
324
|
|
|
325
|
+
Exact-account history reads also accept `includeHistory` (boolean), `historyLimit` (1–100, default 10),
|
|
326
|
+
`includeRevisionSnapshots` (boolean, default false), and `revisionId` (exact Firestore revision id).
|
|
327
|
+
These require one `targetAccountId`, a collection name and `documentId`. They return `documentEvidence`
|
|
328
|
+
even when the live document is deleted. A normal exact-id miss also returns bounded evidence.
|
|
329
|
+
|
|
302
330
|
### `mcp_firestore_patch`
|
|
303
331
|
Guarded exact-document Firestore patch tool for bounded repairs. It defaults to `dryRun:true` and refuses broad
|
|
304
332
|
updates, wildcard collections, delete/remove operations, protected identity fields, and `_lastModified*` audit
|
|
@@ -329,7 +357,9 @@ Response fields include `dataMode`, `accountId`, `collection`, `documentId`, `dr
|
|
|
329
357
|
`diff`. Switch to `"dryRun":false` only after the diff and preconditions are exactly what you intended.
|
|
330
358
|
|
|
331
359
|
### `mcp_object_activity`
|
|
332
|
-
Object lifecycle timeline — metadata + recent activity.
|
|
360
|
+
Object lifecycle timeline — metadata + recent activity. Object metadata includes `documentEvidence`
|
|
361
|
+
with path, current presence/data lane, recent revisions and latest deletion receipt. Document Delete
|
|
362
|
+
activity entries include structured `documentOperation` evidence; PROCESSED is independent of document presence.
|
|
333
363
|
|
|
334
364
|
| Parameter | Required | Description |
|
|
335
365
|
|-----------|----------|-------------|
|