@remits/remits-cli 0.1.164 → 0.1.165

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/index.js CHANGED
@@ -8,14 +8,14 @@
8
8
  - L631 Local State, Workspaces, And Verification Evidence
9
9
  - L2669 Account Repos, Guide Sync, And Platform Repo
10
10
  - L3509 Component Discovery And HTTP Logging
11
- - L4277 Skill Delivery And TOC Resolution
12
- - L4592 Auth And Component Staging
13
- - L5224 Component Summaries, Status, And Sync Gates
14
- - L7548 Branches, Promotion, Commit, And Test Runs
15
- - L9802 Tokens, Tools, Verification, And Config
16
- - L11319 Service Dashboard And WebSocket Listener
17
- - L13829 Agent And Ticket Workflows
18
- - L18090 Help, Auto Update, And Command Dispatch
11
+ - L4279 Skill Delivery And TOC Resolution
12
+ - L4594 Auth And Component Staging
13
+ - L5226 Component Summaries, Status, And Sync Gates
14
+ - L7550 Branches, Promotion, Commit, And Test Runs
15
+ - L9813 Tokens, Tools, Verification, And Config
16
+ - L11330 Service Dashboard And WebSocket Listener
17
+ - L13840 Agent And Ticket Workflows
18
+ - L18101 Help, Auto Update, And Command Dispatch
19
19
  */
20
20
 
21
21
  /*
@@ -899,7 +899,7 @@ function localStateWarnings(cwd, flags = {}) {
899
899
  .sort((a, b) => Date.parse(b.updatedAt || 0) - Date.parse(a.updatedAt || 0));
900
900
  const shown = recent.slice(0, 3).map((a) => a.actor);
901
901
  const stale = report.foreignActors.length - recent.length;
902
- const setOne = 'Name this one with --actor <name> (or REMITS_AGENT_ID) if another agent shares this checkout.';
902
+ const setOne = 'Name this one with --local-agent <name> (or REMITS_LOCAL_AGENT_ID) if another agent shares this checkout; REMITS_AGENT_ID also declares agent identity to the platform.';
903
903
  const pruneHint = stale
904
904
  ? stale + ' spent actor dir(s) (idle, or left behind by finished processes) can be cleared with `remits-cli doctor local-state --prune-actors`.'
905
905
  : '';
@@ -3669,7 +3669,9 @@ function collectComponents(cwd) {
3669
3669
  component.html = content;
3670
3670
  } else if (type === 'htmltemplate' && ext === 'json') {
3671
3671
  component.previewData = content;
3672
- } else if (type === 'tool' && ext === 'json') {
3672
+ } else if ((type === 'tool' || type === 'action') && ext === 'json') {
3673
+ // An Action's .json sidecar is its input schema (manual-run form and x-remits-operations), exactly as
3674
+ // repository sync maps it; staging used to drop it, so a staged declaration silently did not apply.
3673
3675
  component.inputSchema = content;
3674
3676
  } else if (type === 'i18n' && ext === 'json') {
3675
3677
  component.messages = content;
@@ -3850,7 +3852,7 @@ function componentPathInfo(cwd, filePath) {
3850
3852
  else if (type === 'embeddable' && ext === 'js') field = 'javascript';
3851
3853
  else if (type === 'htmltemplate' && ext === 'html') field = 'html';
3852
3854
  else if (type === 'htmltemplate' && ext === 'json') field = 'previewData';
3853
- else if (type === 'tool' && ext === 'json') field = 'inputSchema';
3855
+ else if ((type === 'tool' || type === 'action') && ext === 'json') field = 'inputSchema';
3854
3856
  else if (type === 'i18n' && ext === 'json') field = 'messages';
3855
3857
  else if (type === 'schema' && ext === 'json') field = 'schema';
3856
3858
 
@@ -9130,10 +9132,18 @@ async function waitForToolStatus(api, cwd, options) {
9130
9132
 
9131
9133
  // One compact progress line for a streamed TestSuite frame: a finished case, or the suite roll-up.
9132
9134
  function testSuiteProgressLine(payload = {}) {
9135
+ if (payload.event === 'case_started') {
9136
+ return '[ws] running ' + (payload.activeCases || []).map((c) =>
9137
+ c.name + (c.traceId ? ' [trace ' + c.traceId + ']' : '')).join(', ');
9138
+ }
9133
9139
  if (payload.total != null || Array.isArray(payload.tests)) {
9134
9140
  const total = payload.total != null ? payload.total : (payload.tests || []).length;
9135
9141
  const passed = payload.passed != null ? payload.passed : (payload.tests || []).filter((t) => t && t.passed).length;
9136
- return '[ws] ' + (payload.testName || 'suite') + ': ' + passed + '/' + total + ' passed';
9142
+ const active = (payload.activeCases || []).map((c) => c.name + (c.traceId ? ' [trace ' + c.traceId + ']' : ''));
9143
+ const queued = (payload.shards || []).filter((s) => s.status === 'queued').length;
9144
+ return '[ws] ' + (payload.testName || 'suite') + ': ' + passed + '/' + total + ' passed' +
9145
+ (payload.status ? ' (' + payload.status + ')' : '') +
9146
+ (active.length ? '; running: ' + active.join(', ') : '') + (queued ? '; ' + queued + ' workers queued' : '');
9137
9147
  }
9138
9148
  const mark = payload.passed === false ? 'FAIL' : 'pass';
9139
9149
  const detail = payload.outcome && payload.outcome !== 'passed' ? ' [' + payload.outcome + ']' : '';
@@ -9172,7 +9182,7 @@ function watchWebsocket(baseUrl, topicId, taskId, options = {}) {
9172
9182
  if (payload.taskId && followed.length && !followed.includes(payload.taskId)) {
9173
9183
  return;
9174
9184
  }
9175
- if (payload.tests || payload.name || payload.total != null) {
9185
+ if (payload.tests || payload.name || payload.total != null || payload.event === 'case_started') {
9176
9186
  // Progress, not the payload. This used to print the whole suite result — every case, every
9177
9187
  // stacktrace — as one enormous line immediately before the readable summary said the same thing,
9178
9188
  // which buried the run world, the outcomes and the pivots an agent actually reads. --verbose still
@@ -9345,6 +9355,7 @@ async function testCommand(flags) {
9345
9355
  workspace,
9346
9356
  dataMode,
9347
9357
  dataModeSource,
9358
+ caseConcurrency: flags.parallel !== undefined && runOptions.parallel === 1 ? 1 : undefined,
9348
9359
  testId: /^\d+$/.test(String(testRef)) ? Number(testRef) : undefined,
9349
9360
  testName: /^\d+$/.test(String(testRef)) ? undefined : String(testRef),
9350
9361
  tests: names
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remits/remits-cli",
3
- "version": "0.1.164",
3
+ "version": "0.1.165",
4
4
  "description": "Local CLI for auth, component sync, and live test execution against Remits",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -181,10 +181,15 @@ reference named after it.
181
181
  from `./.remits-cli/actors/<local-agent>/tool-responses/<callId>.json` (or the legacy flat fallback
182
182
  if `doctor local-state` says the response is there) before reporting the work as done.
183
183
  (`tool-reference.md`)
184
- - **Workspace and local actor are different.** `workspace` is the server-side staging lane namespace;
185
- `local actor` is the repo-local filesystem namespace for session logs, tool responses, and verification
186
- mirrors. Use `REMITS_AGENT_ID=<name>` or `--local-agent <name>` when agents share a checkout, and run
187
- `remits-cli doctor local-state` when inheriting one. (`cli-state.md`, `component-resolution.md`)
184
+ - **Workspace, local actor and agent identity are three different things.** `workspace` is the
185
+ server-side staging lane. The **local actor** is only the repo-local folder for session logs, tool
186
+ responses and verification mirrors: name it with `--local-agent <name>` or `REMITS_LOCAL_AGENT_ID` when
187
+ agents share a checkout, and run `remits-cli doctor local-state` when inheriting one. **Agent identity**
188
+ (`--agent-id` / `REMITS_AGENT_ID`) is what the PLATFORM sees: it is sent on every call, it makes the
189
+ call an `agent` to the account's policy rules, and it decides ticket ownership. `REMITS_AGENT_ID` also
190
+ names the local folder when no local actor is set, which is why setting it "just for the folder" changes
191
+ how the platform treats you. If you are an AI agent, setting it is correct: say who you are, and let the
192
+ account's agent rules apply to you. (`cli-state.md`, `agent-sessions.md`)
188
193
  - **Writing the code is not finishing the job.** A change is complete when it is verified — a Test
189
194
  component (preferred, because it becomes regression protection) or a browser flow through
190
195
  `remits-cli token`. "Just do it" and "that's fine, commit it" are not evidence. If you genuinely
@@ -232,6 +237,11 @@ reference named after it.
232
237
  - **Reading and investigating are parallel-safe; editing one account's repository is exclusive**, via a
233
238
  lease. A refusal is not an error — carry on read-only and hand off with `ticket progress --next-step`.
234
239
  Never wait or poll for a lease. (`support-tickets.md`)
240
+ - **`Refused by this account's '<rule>' rule` is a POLICY decision, not a missing capability.** The
241
+ sentence says who the call presented as (`[This call presents as agent (agentId=…)]`). Find the rule in
242
+ the account's `OPERATIONS.md` `remits-policy` block, report its id, its `when`/`forbid`, and why your call
243
+ matched, then ask a person. Never generalize it ("syncs are impossible here"), and never drop your agent
244
+ identity to get past it. (`support-tickets.md`)
235
245
  - **A brief's `## Rules you will be held to` section is ENFORCED, not requested.** The platform refuses
236
246
  the verb and the message says what to do instead — act on that sentence rather than retrying or
237
247
  looking for another door. A `[require]` rule needs a person; hand off. (`support-tickets.md`)
@@ -76,13 +76,19 @@ Think about remits-cli as two cooperating layers:
76
76
  - where a large tool response was written
77
77
  - which tool schemas were most recently cached here
78
78
 
79
- Per-repo state has two independent namespaces:
79
+ Per-repo state has two independent namespaces, and one identity sits beside them:
80
80
 
81
81
  - **Workspace** (`--workspace`, `REMITS_WORKSPACE`, `.remits-cli/workspace`) chooses the server-side
82
82
  Redis staging lane. It changes what staged entries a run resolves.
83
- - **Local actor** (`--local-agent`, `REMITS_AGENT_ID`, generated fallback) chooses the local filesystem
84
- namespace under `.remits-cli/actors/<local-agent>/`. It changes where session logs, tool responses,
85
- verification mirrors, and diagnostics are written.
83
+ - **Local actor** (`--local-agent` / `--actor`, then `REMITS_AGENT_ID`, then `REMITS_LOCAL_AGENT_ID`, then a
84
+ generated fallback) chooses the local filesystem namespace under `.remits-cli/actors/<local-agent>/`. It
85
+ changes where session logs, tool responses, verification mirrors, and diagnostics are written. To name
86
+ only the folder, use `--local-agent` or `REMITS_LOCAL_AGENT_ID`.
87
+ - **Agent identity** (`--agent-id`, then `REMITS_AGENT_ID`) is not local state. The CLI sends it to the
88
+ platform on every call (`X-Remits-Agent-Id` and the payload `agentId`), so the call is an `agent` to the
89
+ account's `remits-policy` rules, owns the tickets it claims, and is attributed to that agent. Without it
90
+ the call is the signed-in person. `REMITS_AGENT_ID` therefore does two jobs, folder and identity; an AI
91
+ agent should set it deliberately, as identity.
86
92
 
87
93
  Run `remits-cli doctor local-state` to print the active actor, state directory, workspace source,
88
94
  foreign actors, git-tracked `.remits-cli` files, legacy flat state, and large/suspicious logs.
@@ -284,10 +284,12 @@ remits-cli corpus retire --corpus <name> --case <caseKey> [--case ...] [--restor
284
284
  `test run` starts a server-side task immediately. By default the CLI process polls until the task is
285
285
  terminal; `--watch false` disables websocket progress streaming but still waits. Pass `--wait false` to
286
286
  return after launch with the task id. A single run with `--names "a|b|c"` selects cases into one suite task,
287
- and those cases execute sequentially in declaration order. To overlap independent slow cases, launch
288
- separate `remits-cli test run --names "<case>" --wait false` commands from the same staged lane and keep the
289
- printed task ids; complete each proof with `test status --task-id <id>`. Avoid parallel runs for cases that
290
- share mutable fixtures, suite-level side effects, or undeclared live AI/provider calls.
287
+ and those cases execute sequentially by default. Test metadata `caseConcurrency` (1–16, default 1)
288
+ enables native server workers. Explicit `--parallel N` overrides it; `--parallel 1` forces serial.
289
+ Parent/group IDs work with `test status` and corpus commands; case results retain child task and trace IDs.
290
+ Scheduled batches additionally accept `suiteConcurrency` (1–16, default 1) and overlap only suites marked
291
+ `parallelSafe: true`; other suites run as exclusive barriers. Avoid concurrency for shared mutable
292
+ fixtures or order-dependent setup. See the Test component guide's Configuring Parallel Execution section.
291
293
 
292
294
  ### Reading a failing run
293
295
 
@@ -430,8 +430,9 @@ id + content hash, platform sync vs local HEAD. If it is not the world you meant
430
430
  about a different world.
431
431
 
432
432
  The platform launch is asynchronous. By default `remits-cli test run` waits for its task to finish, and any
433
- cases selected by `--names "a|b"` execute sequentially inside that suite task. If several slow cases are
434
- independent, use `--parallel N`. It splits the selected cases across N shards that run side by side, and the run
433
+ cases selected by `--names "a|b"` execute sequentially by default. A Test sidecar can set
434
+ `caseConcurrency: 2` for native server workers, including scheduled runs. Explicit `--parallel N`
435
+ overrides that setting (`--parallel 1` forces serial). It splits the selected cases across N shards that run side by side, and the run
435
436
  keeps ONE id (`grp-…`) for `test status` and every corpus command. An instance runs only a few suites at once
436
437
  (two by default), so shards beyond that wait for a slot. Ask for 2–4. Starting separate
437
438
  `test run --names "<case>" --wait false` commands also works for one-off proofs, but every such run is a separate