@linzumi/cli 1.0.171 → 1.0.173

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.
@@ -0,0 +1,58 @@
1
+ import { createRequire as __linzumiBundleCreateRequire } from 'node:module';
2
+ const require = __linzumiBundleCreateRequire(import.meta.url);
3
+ import*as K from"node:crypto";function k(e){if(e===null||e.BS_PRIVATE_NESTED_SOME_NONE===void 0)return e;let t=e.BS_PRIVATE_NESTED_SOME_NONE;if(t!==0)return{BS_PRIVATE_NESTED_SOME_NONE:t-1|0}}function W(e,t){let i=e.length,s=new Array(i),o=0;for(let l=0;l<i;++l){let n=e[l],u=t(n);u!==void 0&&(s[o]=k(u),o=o+1|0)}return s.length=o,s}var P=(e=>t=>t&&typeof t[e]=="string"?t[e]:void 0),ye=P("stack"),C=P("message"),we=P("name"),Se=P("fileName");function p(e,t){if(e!==void 0)return t(k(e))}function _(e,t){return e!==void 0?k(e):t}function z(e,t){return e!==void 0?e:t}function U(e){return e===void 0}function B(e,t){let i=e.indexOf(t);if(i!==-1)return i}function se(e){return e==null?!1:typeof e.RE_EXN_ID=="string"}function L(e){return se(e)?e:{RE_EXN_ID:"JsExn",_1:e}}function ae(e){return K.createHash("sha256").update(e,"utf8").digest().subarray(0,8).toString("base64url")}function R(e,t){return{operationName:e,documentId:ae(t),text:t}}var Q=R("TopicsCliTopicLookup",`query TopicsCliTopicLookup($workspaceSlug: String!, $slug: String!) {
4
+ topic(workspaceSlug: $workspaceSlug, slug: $slug) {
5
+ id
6
+ slug
7
+ title
8
+ status
9
+ }
10
+ }`),Y=R("TopicsCliCreateTopic",`mutation TopicsCliCreateTopic($input: CreateTopicInput!) {
11
+ createTopic(input: $input) {
12
+ ok
13
+ error
14
+ topic {
15
+ id
16
+ slug
17
+ }
18
+ }
19
+ }`),Z=R("TopicsCliPostEntry",`mutation TopicsCliPostEntry($input: PostTopicEntryInput!) {
20
+ postTopicEntry(input: $input) {
21
+ ok
22
+ error
23
+ entry {
24
+ entrySeq
25
+ }
26
+ }
27
+ }`),ke=[Q,Y,Z],M=["plan","reasoning","command_execution","terminal_input","file_change","tool_call","approval_request","web_search","status","artifact","assistant_output"];function G(){return`Usage: linzumi topics post [options]
28
+
29
+ Post one entry into a long-lived topic (spec/topics-rules.md). The topic
30
+ auto-creates on first post, so producers never lose an entry to a missing
31
+ topic.
32
+
33
+ Required:
34
+ --workspace <slug> Workspace the topic lives in.
35
+ --topic <slug> The topic's per-workspace slug.
36
+
37
+ Options:
38
+ --kind <kind> Entry kind (default: status). One of:
39
+ `+M.join(", ")+`.
40
+ --preview <text> Short preview line for collapsed rendering.
41
+ --body <text> Full entry body text.
42
+ --payload-json <json> JSON object payload (e.g. '{"severity":"error"}').
43
+ --dedupe-key <key> Idempotency key; a replayed post with the same key
44
+ returns the existing entry.
45
+ --title <text> Title used only when the topic auto-creates.
46
+ --no-create Fail instead of auto-creating a missing topic.
47
+ --json Machine-readable output.
48
+ --linzumi-url <url> Server URL (defaults to the production server).
49
+ --token <token> Explicit access token (defaults to cached login).
50
+ -h, --help Show this help.
51
+ `}var de=["workspace","topic","kind","preview","body","payload-json","dedupe-key","title","linzumi-url","api-url","token"],ce=["json","help","no-create"];function pe(e){let t=[],i={},s,o=0;for(;U(s)&&o<e.length;){let n=e[o];if(n==="-h"||n==="--help")i.help="FlagOn";else if(n.startsWith("--")){let u=B(n,"="),r=u!==void 0?n.slice(2,u):n.slice(2);if(ce.includes(r))u!==void 0?s="--"+r+" does not take a value":i[r]="FlagOn";else if(de.includes(r))if(u!==void 0)i[r]={TAG:"FlagString",_0:n.slice(u+1|0)};else{let d=e[o+1|0],O=0;d!==void 0&&!d.startsWith("--")?(i[r]={TAG:"FlagString",_0:d},o=o+1|0):O=1,O===1&&(s="--"+r+" requires a value")}else s="unknown flag --"+r+" (see: linzumi topics --help)"}else t.push(n);o=o+1|0}let l=s;return l!==void 0?{TAG:"Error",_0:l}:{TAG:"Ok",_0:{subcommand:t[0],flags:i}}}function m(e,t){let i=e[t];if(typeof i=="object")return i._0}function I(e,t){let i=e[t];return i!==void 0?typeof i!="object":!1}function _e(e){let t;try{t=JSON.parse(e)}catch{return{TAG:"Error",_0:"--payload-json must be valid JSON"}}return typeof t=="object"&&t!==null&&!Array.isArray(t)?{TAG:"Ok",_0:void 0}:{TAG:"Error",_0:"--payload-json must be a JSON object"}}function f(e,t){if(typeof e=="object"&&e!==null&&!Array.isArray(e))return e[t]}function w(e){if(typeof e=="string")return e}function V(e){if(typeof e=="boolean")return e}function me(e){if(typeof e=="number")return e}function he(e,t,i,s){let o=f(s,"errors"),l=o!==void 0?Array.isArray(o)?o:[]:[];if(l.length!==0){let u=W(l,r=>p(f(r,"extensions"),d=>w(f(d,"code"))));return u.includes("PERSISTED_DOCUMENT_NOT_FOUND")?"DocumentNotFound":{TAG:"GraphqlErrors",_0:{messages:l.map(r=>_(w(f(r,"message")),"unknown error")),codes:u}}}if(!e)return{TAG:"HttpFailure",_0:"HTTP "+t.toString()+" "+i};let n=f(s,"data");return n!==void 0?{TAG:"Data",_0:n}:{TAG:"HttpFailure",_0:"empty response body"}}function H(e){if(typeof e!="object")return"topics request failed";switch(e.TAG){case"Data":return"topics request failed";case"GraphqlErrors":let t=e._0;if(t.codes.includes("FREE_FORM_GRAPHQL_FORBIDDEN"))return"this Linzumi server does not know this CLI version's topics documents yet (its persisted-document manifest predates them); nothing was changed - retry after the next server deploy";let i=t.messages;return i.some(o=>{let l=o.toLowerCase();return l.includes("cannot query field")||l.includes("unknown argument")||l.includes("unknown type")||l.includes("unknown field")?!0:l.includes("has invalid value $input")})?"this Linzumi server does not support topics yet (the topics server rollout has not reached it); nothing was changed":"topics request returned errors: "+i.join("; ");case"HttpFailure":return"topics request failed: "+e._0}}function Oe(e,t,i){let s=async o=>{let l=Object.fromEntries([["content-type","application/json"],["authorization","Bearer "+t]]),n=await i(e,{method:"POST",headers:l,body:JSON.stringify(o)}),u;try{u=await n.json()}catch{u=null}return he(n.ok,n.status,n.statusText,u)};return async(o,l)=>{let n=await s(Object.fromEntries([["documentId",o.documentId],["operationName",o.operationName],["variables",l]]));if(typeof n!="object"){let u=await s(Object.fromEntries([["query",o.text],["operationName",o.operationName],["variables",l]]));return typeof u!="object"||u.TAG!=="Data"?{TAG:"Error",_0:H(u)}:{TAG:"Ok",_0:u._0}}switch(n.TAG){case"Data":return{TAG:"Ok",_0:n._0};case"GraphqlErrors":case"HttpFailure":return{TAG:"Error",_0:H(n)}}}}function ge(e){return Object.fromEntries([["workspaceSlug",e.workspaceSlug],["slug",e.topicSlug]])}async function X(e,t){let i=await e(Q,ge(t));return i.TAG==="Ok"?{TAG:"Ok",_0:w(p(f(i._0,"topic"),s=>f(s,"id")))}:{TAG:"Error",_0:i._0}}async function Ee(e,t){if(!M.includes(t.kind))return{TAG:"Error",_0:'unknown entry kind "'+t.kind+'" (one of: '+M.join(", ")+")"};let i=t.payloadJson,s=i!==void 0?_e(i):{TAG:"Ok",_0:void 0};if(s.TAG!=="Ok")return{TAG:"Error",_0:s._0};let o=await X(e,t);if(o.TAG!=="Ok")return{TAG:"Error",_0:o._0};let l=o._0,n;if(l!==void 0)n={TAG:"Ok",_0:[l,!1]};else if(t.createMissing){let h=Object.fromEntries([["workspaceSlug",t.workspaceSlug],["slug",t.topicSlug]]),j=t.title;j!==void 0&&(h.title=j);let N=await e(Y,Object.fromEntries([["input",h]]));if(N.TAG==="Ok"){let F=f(N._0,"createTopic"),ee=_(V(p(F,c=>f(c,"ok"))),!1),D=w(p(p(F,c=>f(c,"topic")),c=>f(c,"id"))),A=w(p(F,c=>f(c,"error"))),q=0;if(ee&&D!==void 0?n={TAG:"Ok",_0:[D,!0]}:q=1,q===1){let c;if(A!==void 0){let T=A.toLowerCase();c=T.includes("taken")||T.includes("slug")}else c=!1;if(c){let T=await X(e,t),$=0;if(T.TAG==="Ok"){let J=T._0;J!==void 0?n={TAG:"Ok",_0:[J,!1]}:$=2}else $=2;$===2&&(n={TAG:"Error",_0:'could not create topic "'+t.topicSlug+'": '+_(A,"unknown error")})}else n={TAG:"Error",_0:'could not create topic "'+t.topicSlug+'": '+_(A,"unknown error")}}}else n={TAG:"Error",_0:N._0}}else n={TAG:"Error",_0:'topic "'+t.topicSlug+'" does not exist in workspace "'+t.workspaceSlug+'" (drop --no-create to auto-create it)'};if(n.TAG!=="Ok")return{TAG:"Error",_0:n._0};let u=n._0,r=Object.fromEntries([["topicId",u[0]],["kind",t.kind.toUpperCase()]]),d=t.preview;d!==void 0&&(r.previewText=d);let O=t.body;O!==void 0&&(r.body=O);let S=t.payloadJson;S!==void 0&&(r.payloadJson=S);let v=t.dedupeKey;v!==void 0&&(r.dedupeKey=v);let g=await e(Z,Object.fromEntries([["input",r]]));if(g.TAG!=="Ok")return{TAG:"Error",_0:g._0};let y=f(g._0,"postTopicEntry"),b=_(V(p(y,h=>f(h,"ok"))),!1),a=me(p(p(y,h=>f(h,"entry")),h=>f(h,"entrySeq")));if(b&&a!==void 0)return{TAG:"Ok",_0:{topicSlug:t.topicSlug,entrySeq:a|0,created:u[1]}};let E=w(p(y,h=>f(h,"error")));return{TAG:"Error",_0:'could not post to topic "'+t.topicSlug+'": '+_(E,"unknown error")}}async function be(e,t){let i=t.stdout,s=i!==void 0?i:u=>{process.stdout.write(u)},o=t.stderr,l=o!==void 0?o:u=>{process.stderr.write(u)},n=pe(e);if(n.TAG==="Ok"){let u=n._0,r=u.flags,d=u.subcommand;if(I(r,"help"))return s(G()),0;if(d!==void 0){if(d==="post"){let O=m(r,"workspace"),S=m(r,"topic");if(O!==void 0){if(S!==void 0){let v=_(z(m(r,"linzumi-url"),m(r,"api-url")),t.defaultUrl),g,y=0,b;try{let a=m(r,"token");b=await(a!==void 0?t.resolveToken({kandanUrl:v,explicitToken:a}):t.resolveToken({kandanUrl:v})),y=1}catch(a){let E=L(a);if(E.RE_EXN_ID==="JsExn")g={TAG:"Error",_0:_(C(E._1),"token resolution failed")};else throw E}if(y===1){let a=Oe(t.graphqlEndpoint(v),b,_(t.fetchImpl,fetch));g=await Ee(a,{workspaceSlug:O,topicSlug:S,kind:_(m(r,"kind"),"status"),preview:m(r,"preview"),body:m(r,"body"),payloadJson:m(r,"payload-json"),dedupeKey:m(r,"dedupe-key"),title:m(r,"title"),createMissing:!I(r,"no-create")})}if(g.TAG==="Ok"){let a=g._0;if(I(r,"json")){let E=Object.fromEntries([["topicSlug",a.topicSlug],["entrySeq",a.entrySeq],["created",a.created]]);s(JSON.stringify(E)+`
52
+ `)}else{let E=a.created?" (topic auto-created)":"";s("posted entry #"+a.entrySeq.toString()+" to "+O+"/"+a.topicSlug+E+`
53
+ `)}return 0}return l(g._0+`
54
+ `),1}return l(`--workspace and --topic are required (see: linzumi topics --help)
55
+ `),1}return l(`--workspace and --topic are required (see: linzumi topics --help)
56
+ `),1}return l('unknown topics subcommand "'+d+`"
57
+ `),s(G()),1}return s(G()),1}return l(n._0+`
58
+ `),1}export{ce as booleanFlags,Y as createDocument,Oe as createTransport,R as documentOf,ke as documents,H as errorFromOutcome,I as flagOn,m as flagString,G as helpText,he as interpretGraphqlResponse,V as jsonBool,f as jsonField,me as jsonNumber,w as jsonString,Q as lookupDocument,X as lookupTopicId,ge as lookupVariables,pe as parseTopicsArgs,ae as persistedDocumentId,Z as postDocument,Ee as postTopicEntry,be as runTopicsCommand,M as topicEntryKinds,_e as validatePayloadJson,de as valueFlags};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linzumi/cli",
3
- "version": "1.0.171",
3
+ "version": "1.0.173",
4
4
  "description": "Linzumi CLI \u2014 point a Codex agent at the real code on your laptop, with your team watching and steering from shared threads.",
5
5
  "type": "module",
6
6
  "bin": {
package/scripts/build.mjs CHANGED
@@ -156,6 +156,43 @@ try {
156
156
  );
157
157
  }
158
158
 
159
+ // Long-lived topics producer (spec/topics-rules.md :topics/first-producers-v1
160
+ // slice a): `linzumi topics post` is ReScript per the zero-TS program
161
+ // (CommanderTopicsCli.res); bundle it beside the flat CLI bundle so the
162
+ // dispatcher's `new URL('./topics-cli.mjs', import.meta.url)` resolves at
163
+ // runtime. Publish CI compiles @linzumi/cli-rescript before pack, so real
164
+ // releases always carry it; a checkout without the compiled artifacts gets
165
+ // the same warn-and-skip posture as the mcp bundle above (the dispatcher
166
+ // then falls back to the package-source candidate, and failing that prints
167
+ // an honest "unavailable in this build" refusal).
168
+ try {
169
+ await build({
170
+ entryPoints: [
171
+ join(
172
+ packageRoot,
173
+ '../linzumi-cli-rescript/src/topics/CommanderTopicsCli.res.mjs'
174
+ ),
175
+ ],
176
+ bundle: true,
177
+ platform: 'node',
178
+ target: 'node20',
179
+ format: 'esm',
180
+ outfile: join(packageRoot, 'dist/topics-cli.mjs'),
181
+ minify: true,
182
+ sourcemap: false,
183
+ legalComments: 'none',
184
+ banner,
185
+ });
186
+ } catch (error) {
187
+ console.warn(
188
+ '[build] topics-cli bundle could not be built (are the ' +
189
+ 'linzumi-cli-rescript artifacts compiled?); `linzumi topics post` ' +
190
+ `falls back to the package-source candidate: ${
191
+ error instanceof Error ? error.message : String(error)
192
+ }`
193
+ );
194
+ }
195
+
159
196
  // The in-guest CLOUD turn driver: a self-contained dist/cloud-supervisor.mjs
160
197
  // bundle that vmCloudSupervisor injects onto the persistent overlay of a
161
198
  // workspace-agent smolcloud VM and runs with a bare `node` (the guest's
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env bash
2
+ # Codex wire canary launcher (spec/codex-wire-capture-replay.spec.md, "Live
3
+ # canary lane"): resolves the wire corpus + the pinned @openai/codex version
4
+ # and runs the ReScript canary bin (HarnessCodexWireCanaryMain.res).
5
+ #
6
+ # codex-wire-canary.sh corpus the scheduled corpus check
7
+ # (fidelity + shape baseline +
8
+ # freshness vs the pinned codex)
9
+ # codex-wire-canary.sh fresh <capture> drift-diff a freshly recorded
10
+ # canary capture BEFORE promotion
11
+ #
12
+ # The canary corpus is every wire capture the replay lane treats as real
13
+ # wire truth: test/fixtures/agent-raw-replay/wire-corpus/*.ndjson plus the
14
+ # real-probe session (test/fixtures/agent-raw-replay/real-probe/codex.ndjson).
15
+ # The committed shape baseline lives beside the corpus
16
+ # (wire-corpus/shape-baseline.json); the vitest corpus gate pins the same
17
+ # set, so this script and the test cannot disagree silently.
18
+ #
19
+ # Build the ReScript package first (`npx rescript build
20
+ # packages/linzumi-cli-rescript`); the CLI test pipeline already does.
21
+ set -euo pipefail
22
+
23
+ here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
24
+ cli_root="$(cd "$here/.." && pwd)"
25
+ bin_module="$cli_root/../linzumi-cli-rescript/src/harness/HarnessCodexWireCanaryMain.res.mjs"
26
+ baseline="$cli_root/test/fixtures/agent-raw-replay/wire-corpus/shape-baseline.json"
27
+
28
+ if [[ ! -f "$bin_module" ]]; then
29
+ echo "codex-wire-canary: compiled module missing at $bin_module - run: npx rescript build <repo>/packages/linzumi-cli-rescript" >&2
30
+ exit 66
31
+ fi
32
+
33
+ mode="${1:-}"
34
+ case "$mode" in
35
+ corpus)
36
+ pinned_version="$(node -p "require('$cli_root/package.json').dependencies['@openai/codex'].replace(/^[^0-9]*/, '')")"
37
+ captures=("$cli_root"/test/fixtures/agent-raw-replay/wire-corpus/*.ndjson)
38
+ captures+=("$cli_root/test/fixtures/agent-raw-replay/real-probe/codex.ndjson")
39
+ exec node "$bin_module" corpus \
40
+ --baseline "$baseline" \
41
+ --pinned-codex-version "$pinned_version" \
42
+ "${captures[@]}"
43
+ ;;
44
+ fresh)
45
+ shift
46
+ if [[ $# -lt 1 ]]; then
47
+ echo "codex-wire-canary: fresh mode needs the freshly recorded capture path" >&2
48
+ exit 64
49
+ fi
50
+ exec node "$bin_module" fresh --baseline "$baseline" "$@"
51
+ ;;
52
+ *)
53
+ echo "codex-wire-canary: unknown mode '${mode}' (use corpus or fresh)" >&2
54
+ exit 64
55
+ ;;
56
+ esac
@@ -67,6 +67,15 @@ type BackendReplayOptions = {
67
67
  // machinery is exercised against the REAL backend.
68
68
  readonly wire: boolean;
69
69
  readonly wireStrictness: string | undefined;
70
+ // Replay-to-a-point (spec §Replay-to-a-point): --wire-breakpoint specs
71
+ // for the wire stub (`ordinal:<n>`, `method:<rpcMethod>[:<n>]`,
72
+ // `first-delta`, `turn-started[:<n>]`, `turn-completed[:<n>]`), in hold
73
+ // order. While the stub holds, the whole stack (runner -> backend ->
74
+ // client projection) is frozen at the recorded prefix; an external
75
+ // driver (Playwright DOM assertions, the film rig) observes and releases
76
+ // the hold over the stub's HTTP control routes (GET /replay/breakpoint,
77
+ // POST /replay/resume against the printed control URL).
78
+ readonly wireBreakpoints: readonly string[];
70
79
  };
71
80
 
72
81
  type WireReplayServerHandle = {
@@ -93,6 +102,7 @@ async function startWireReplayServerForFixture(
93
102
  readonly capturePath?: string;
94
103
  readonly strictness?: string | undefined;
95
104
  readonly clock?: string | undefined;
105
+ readonly breakpoints?: readonly string[];
96
106
  }) => Promise<WireReplayServerHandle>;
97
107
  wireReplayClockForBackendSpeed: (
98
108
  speed: string | undefined
@@ -105,13 +115,27 @@ async function startWireReplayServerForFixture(
105
115
  // test/agentReplayFixture.test.ts.
106
116
  const wireClock = wireModule.wireReplayClockForBackendSpeed(options.speed);
107
117
 
108
- return wireModule.startWireReplayServerJs({
118
+ const server = await wireModule.startWireReplayServerJs({
109
119
  capturePath: options.fixturePath,
110
120
  ...(options.wireStrictness === undefined
111
121
  ? {}
112
122
  : { strictness: options.wireStrictness }),
113
123
  ...(wireClock === undefined ? {} : { clock: wireClock }),
124
+ ...(options.wireBreakpoints.length === 0
125
+ ? {}
126
+ : { breakpoints: options.wireBreakpoints }),
114
127
  });
128
+ if (options.wireBreakpoints.length > 0) {
129
+ // The external driver's handle on the frozen stack: poll GET
130
+ // /replay/breakpoint until held, assert on the frozen DOM/projection,
131
+ // then POST /replay/resume.
132
+ console.error(
133
+ `[wire-breakpoint] control http://127.0.0.1:${server.port} breakpoints=${options.wireBreakpoints.join(
134
+ ','
135
+ )}`
136
+ );
137
+ }
138
+ return server;
115
139
  }
116
140
 
117
141
  type BackendReplayBrowserAuth = {
@@ -403,6 +427,7 @@ function parseArgs(args: readonly string[]): BackendReplayOptions {
403
427
  oracleFeatureId: argValue(args, '--oracle-feature'),
404
428
  wire: args.includes('--wire'),
405
429
  wireStrictness: argValue(args, '--wire-strictness'),
430
+ wireBreakpoints: argValues(args, '--wire-breakpoint'),
406
431
  };
407
432
  }
408
433
 
@@ -1888,6 +1913,24 @@ function evaluateRequiredFeatureGate(
1888
1913
  }
1889
1914
  }
1890
1915
 
1916
+ // Every value of a repeatable flag, in argv order (--wire-breakpoint may
1917
+ // name several ordered holds).
1918
+ function argValues(args: readonly string[], name: string): readonly string[] {
1919
+ const values: string[] = [];
1920
+ for (let index = 0; index < args.length; index += 1) {
1921
+ if (args[index] !== name) {
1922
+ continue;
1923
+ }
1924
+ const value = args[index + 1];
1925
+ if (value === undefined) {
1926
+ throw new Error(`${name} requires a value`);
1927
+ }
1928
+ values.push(value);
1929
+ index += 1;
1930
+ }
1931
+ return values;
1932
+ }
1933
+
1891
1934
  function argValue(args: readonly string[], name: string): string | undefined {
1892
1935
  const index = args.indexOf(name);
1893
1936
 
@@ -1906,7 +1949,7 @@ function argValue(args: readonly string[], name: string): string | undefined {
1906
1949
 
1907
1950
  function printHelp(): void {
1908
1951
  process.stdout.write(
1909
- `Usage: pnpm run replay:agent-backend -- --fixture <path> [options]\n\nOptions:\n --dry-run Validate fixture/manifest/diagnostics without backend connection\n --probe-backend Also join the real Phoenix local_runner channel, then exit\n --provider auto|codex|claude-code Replay provider. Default: auto\n --speed immediate|realtime|<n>x|<n>ms\n Replay speed. Default: immediate\n --backend-url <url> Local Phoenix backend URL; required by --probe-backend/replay\n --setup-fixture Create a throwaway fixture user/workspace/channel first; requires local fixture registration\n --setup-label <label> Prefix for throwaway fixture setup. Default: agent-backend-replay\n --workspace <slug> Target workspace slug for session-token exchange and future replay\n --channel <slug> Target channel slug for token scoping and future replay\n --thread-id <id> Target thread id for the future backend replay slice\n --runner-id <id> Local runner id for backend probing. Default: generated\n --cwd <path> Cwd advertised in backend probe/replay. Default: current directory\n --work-description <text> Work description sent through the normal start mutation\n --token <token> Local-runner token; also reads LINZUMI_AGENT_BACKEND_REPLAY_TOKEN\n --session-token <token> Browser/session token to exchange for a local-runner token; also reads LINZUMI_AGENT_BACKEND_REPLAY_SESSION_TOKEN\n --out-dir <path> Artifact directory for summary.json. Default: agent-backend-replay-output\n --wire Serve the fixture from the stub codex app-server websocket (spec/codex-wire-capture-replay.spec.md) so the runner's real socket machinery is exercised\n --wire-strictness shape|exact Wire mode validation of runner-sent packets against the recording. Default: shape\n --require-feature <featureId> Fail before backend setup unless manifest readiness says the feature is ready\n --oracle-feature <featureId> Run feature-specific backend oracles without using readiness as a preflight gate\n --no-summary Do not write summary.json; stdout JSON is still printed\n\nExamples:\n pnpm --filter @linzumi/cli run replay:agent-backend -- --fixture test/fixtures/agent-raw-replay/real-probe/claude.ndjson --provider claude-code --dry-run\n pnpm --filter @linzumi/cli run replay:agent-backend -- --fixture test/fixtures/agent-raw-replay/real-probe/claude.ndjson --provider claude-code --probe-backend --backend-url http://127.0.0.1:4140 --workspace default --session-token <browser-session-token>\n pnpm --filter @linzumi/cli run replay:agent-backend -- --fixture test/fixtures/agent-raw-replay/real-probe/claude.ndjson --provider claude-code --backend-url http://127.0.0.1:4140 --setup-fixture\n`
1952
+ `Usage: pnpm run replay:agent-backend -- --fixture <path> [options]\n\nOptions:\n --dry-run Validate fixture/manifest/diagnostics without backend connection\n --probe-backend Also join the real Phoenix local_runner channel, then exit\n --provider auto|codex|claude-code Replay provider. Default: auto\n --speed immediate|realtime|<n>x|<n>ms\n Replay speed. Default: immediate\n --backend-url <url> Local Phoenix backend URL; required by --probe-backend/replay\n --setup-fixture Create a throwaway fixture user/workspace/channel first; requires local fixture registration\n --setup-label <label> Prefix for throwaway fixture setup. Default: agent-backend-replay\n --workspace <slug> Target workspace slug for session-token exchange and future replay\n --channel <slug> Target channel slug for token scoping and future replay\n --thread-id <id> Target thread id for the future backend replay slice\n --runner-id <id> Local runner id for backend probing. Default: generated\n --cwd <path> Cwd advertised in backend probe/replay. Default: current directory\n --work-description <text> Work description sent through the normal start mutation\n --token <token> Local-runner token; also reads LINZUMI_AGENT_BACKEND_REPLAY_TOKEN\n --session-token <token> Browser/session token to exchange for a local-runner token; also reads LINZUMI_AGENT_BACKEND_REPLAY_SESSION_TOKEN\n --out-dir <path> Artifact directory for summary.json. Default: agent-backend-replay-output\n --wire Serve the fixture from the stub codex app-server websocket (spec/codex-wire-capture-replay.spec.md) so the runner's real socket machinery is exercised\n --wire-strictness shape|exact Wire mode validation of runner-sent packets against the recording. Default: shape\n --wire-breakpoint <spec> Replay-to-a-point hold (repeatable, ordered): ordinal:<n> | method:<rpcMethod>[:<n>] | first-delta | turn-started[:<n>] | turn-completed[:<n>]. The stub freezes the stack at the hold; observe/release via GET /replay/breakpoint + POST /replay/resume on the printed control URL\n --require-feature <featureId> Fail before backend setup unless manifest readiness says the feature is ready\n --oracle-feature <featureId> Run feature-specific backend oracles without using readiness as a preflight gate\n --no-summary Do not write summary.json; stdout JSON is still printed\n\nExamples:\n pnpm --filter @linzumi/cli run replay:agent-backend -- --fixture test/fixtures/agent-raw-replay/real-probe/claude.ndjson --provider claude-code --dry-run\n pnpm --filter @linzumi/cli run replay:agent-backend -- --fixture test/fixtures/agent-raw-replay/real-probe/claude.ndjson --provider claude-code --probe-backend --backend-url http://127.0.0.1:4140 --workspace default --session-token <browser-session-token>\n pnpm --filter @linzumi/cli run replay:agent-backend -- --fixture test/fixtures/agent-raw-replay/real-probe/claude.ndjson --provider claude-code --backend-url http://127.0.0.1:4140 --setup-fixture\n`
1910
1953
  );
1911
1954
  }
1912
1955